这是我的场景……
> URL访问网站:[root]
怎么做:转到通常的[Home] Controller和[Index] View(没有[ID]). ……它现在这样做:
app.UseMvc(routes => { routes.MapRoute( name: "default",template: "{controller=Home}/{action=Index}/{id?}"); });
> URL访问网站:[root] / ControllerName / … yada yada …
怎么做:转到控制器等…这一切都有效.
>棘手的一个:URL访问网站:[root] / SomeString
怎么做:访问数据库并做一些逻辑来决定我是否找到了一个事件ID.如果我这样做,我会转到[事件]控制器和[索引]视图和我找到的任何[ID].如果不是,我尝试找到主机ID并转到[主页]控制器和[组织]视图,我找到了[ID].如果我没有找到并且事件或主机转到通常的[Home] Controller和[Index] View(没有[ID]).
这里最大的问题是我想在2个不同的控制器中重定向到三个完全不同的视图之一.
所以底线是我想在用户访问我网站的根目录时做一些逻辑,并且在其上有一个“/ Something”,并且该逻辑是数据库驱动的.
如果你理解了这个问题,你现在就可以停止阅读……如果你觉得需要理解为什么需要所有这些逻辑,你可以继续阅读更详细的背景.
My site has basically two modes: Viewing an Event and Not Viewing an
Event! There are usually 4 or 5 events running at an one time but
most users are only interested in one event but it’s a DIFFERENT event
every 4 months or so..I have a [Host] entity and each Host holds up to
4 events a year,one at a time. Most users only care about one Host’s
events.I’m trying to avoid making a user always go to an event map and find
the event and click on it since I have a limit to how many times I can
show a map (for free) and it’s really not necessary. 99.99% of the
time a user is on my site they are on an Event screen,not my Home
screens,and are interested in only one event at a time. In the
future I want to code it so if they come to my website they go right
to their event or a new event from their favorite host so I can avoid
a LOT of clicks and focus my [Home] controller pages for newbs…but I
don’t have auto-login working yet so that’s on the back burner.But for now I want hosts to always have the same url for their events:
FragSwapper.com/[Host Abbreviation] …and know it will always go to
their current event which has a different ID every 4 months!!!Crazy…I know…but technically very easy to do,I just don’t know
how to do it properly in MVC with how things are done.
解决方法
根据release notes,创建了一个新的RewriteMiddleware
.
这提供了几种不同的预定义重写选项和实用程序扩展方法,这可能最终修改请求路径,就像在此答案中完成的那样.例如,参见RewriteRule
的实现
具体到OP问题,你需要实现自己的IRule类(从头开始或扩展现有的类,如RewriteRule,它基于正则表达式).您可以使用RewriteOptions的新AddMyRule()扩展方法来补充它.
您可以创建自己的middleware并在MVC路由之前将其添加到请求管道.
这允许您在评估MVC路由之前将代码注入管道.通过这种方式,您将能够:
>检查传入请求中的路径
>在数据库中搜索具有相同值的eventId或hostId
>如果找到事件或主机,请将传入请求路径更新为Event / Index / {eventId}或Home / Organization / {hostId}
>让下一个中间件(MVC路由)处理请求.他们会看到前一个中间件对请求路径所做的任何更改
例如,create your own EventIdUrlRewritingMiddleware中间件将尝试将传入请求路径与数据库中的eventId进行匹配.如果匹配,它会将原始请求路径更改为Event / Index / {eventId}:
public class EventIdUrlRewritingMiddleware { private readonly RequestDelegate _next; //Your constructor will have the dependencies needed for database access public EventIdUrlRewritingMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { var path = context.Request.Path.ToUriComponent(); if (PathIsEventId(path)) { //If is an eventId,change the request path to be "Event/Index/{path}" so it is handled by the event controller,index action context.Request.Path = "/Event/Index" + path; } //Let the next middleware (MVC routing) handle the request //In case the path was updated,the MVC routing will see the updated path await _next.Invoke(context); } private bool PathIsEventId(string path) { //The real midleware will try to find an event in the database that matches the current path //In this example I am just using some hardcoded string if (path == "/someEventId") { return true; } return false; } }
然后按照相同的方法创建另一个类HostIdUrlRewritingMiddleware.
最后,在Startup.Configure方法中将新的中间件添加到管道中,确保在Routing和MVC中间件之前添加它们:
app.UseMiddleware<EventIdUrlRewritingMiddleware>(); app.UseMiddleware<HostIdUrlRewritingMiddleware>(); app.UseMvc(routes => { routes.MapRoute( name: "default",template: "{controller=Home}/{action=Index}/{id?}"); });
使用此配置:
> /转到HomeController.Index操作
> / Home /关于HomeController.About动作
> / Event / Index / 1转到EventController.Index操作id = 1
> / someEventId转到EventController.Index操作,id = someEventId
请注意,没有涉及http重定向.在浏览器中打开/ someEventId时,只有一个http请求,浏览器将在addess栏中显示/ someEventId. (即使内部原始路径已更新)