使用 MVC 和 ASP.Net 核心动态 url 重写

Dynamic url rewriting with MVC and ASP.Net Core

我正在使用 ASP.Net Core 和 MVC 6 重写我的 FragSwapper.com 网站(目前在 Asp 2.0!),我正在尝试做一些我通常会做的事情打破 URL 重写工具以及数据库代码和一些重定向,但我想知道在 ASP.Net 核心中是否有 "better" 方法可以使用 MVC 路由和重定向。

这是我的场景...

这里的大问题是我想在 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.

更新:ASP.Net核心 1.1

根据release notes, a new RewriteMiddleware已经创建。

这提供了几种不同的预定义重写选项和实用程序扩展方法,最终可能会修改请求路径,因为它已在此答案中完成。例如,参见 RewriteRule

的实现

具体到 OP 问题,您需要实现自己的 IRule class(从头开始或扩展现有的 RewriteRule,它基于正则表达式).您可能会用 RewriteOptions.

的新 AddMyRule() 扩展方法来补充它

您可以创建自己的 middleware 并将其添加到 MVC 路由之前的请求管道。

这允许您在评估 MVC 路由之前将代码注入管道。这样您将能够:

  1. 检查传入请求中的路径
  2. 在数据库中搜索具有相同值的 eventId 或 hostId
  3. 如果找到事件或主机,请将传入请求路径更新为 Event/Index/{eventId}Home/Organization/{hostId}
  4. 让下一个中间件(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;
    }
}

然后按照相同的方法创建另一个 class HostIdUrlRewritingMiddleware

最后在 Startup.Configure 方法中将新的中间件添加到管道中,确保它们在路由和 MVC 中间件之前添加:

        app.UseMiddleware<EventIdUrlRewritingMiddleware>();
        app.UseMiddleware<HostIdUrlRewritingMiddleware>();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });

使用此配置:

  • / 转到 HomeController.Index 操作
  • /Home/About 转到 HomeController.About 操作
  • /Event/Index/1 转到 EventController.Index 操作 id=1
  • /someEventId 转到 EventController.Index 操作,id=someEventId

请注意不涉及 http 重定向。当在浏览器中打开 /someEventId 时,有一个 http 请求,浏览器将在地址栏中显示 /someEventId。 (即使在内部更新了原始路径)