【问题标题】:Dynamic url rewriting with MVC and ASP.Net Core使用 MVC 和 ASP.Net Core 重写动态 url
【发布时间】:2016-03-23 13:18:19
【问题描述】:

我正在使用 ASP.Net Core 和 MVC 6 重写我的 FragSwapper.com 网站(目前在 Asp 2.0 中!),我正在尝试做一些我通常必须打破 URL Re-Write 工具的事情使用 db 代码和一些重定向,但我想知道在 ASP.Net Core 中是否有“更好”的方法可以使用 MVC 路由和重定向。

这是我的场景...

  • 访问网站的 URL:[root]

    做什么: 转到通常的 [Home] 控制器和 [Index] 视图(没有 [ID])。 ...它现在这样做了:

    app.UseMvc(routes =>
    {
      routes.MapRoute(
      name: "default",
      template: "{controller=Home}/{action=Index}/{id?}");
    });
    
  • 访问网站的 URL:[root]/ControllerName/...yada yada...

    怎么做:去控制器,等等......这一切也都有效。

  • 棘手的一点:URL 访问站点:[root]/SomeString

    该怎么做: 访问数据库并执行一些逻辑来确定是否找到事件 ID。如果我这样做,我会转到 [Event] Controller 和 [Index] View 以及我找到的任何内容的 [ID]。如果不是,我尝试查找主机 ID 并使用我找到的 [ID] 转到 [Home] Controller 和 [Organization] View。如果我没有找到事件或主机,请转到通常的 [Home] 控制器和 [Index] 视图(没有 [ID])。

这里的大问题是我想重定向到 2 个不同控制器中的三个完全不同的视图之一。

所以底线是当用户来到我网站的根目录并且上面有一个“/Something”并且该逻辑是数据库驱动时,我想做一些逻辑。

如果您理解了这个问题,您现在可以停止阅读……如果您觉得有必要了解为什么需要所有这些逻辑,您可以继续阅读以获得更详细的上下文。

我的网站基本上有两种模式:查看活动和不查看活动 事件!通常一次运行 4 或 5 个事件,但 大多数用户只对一个事件感兴趣,但这是一个不同的事件 每 4 个月左右..我有一个 [Host] 实体,每个 Host 最多支持 一年4场,一次一场。大多数用户只关心一个主机的 事件。

我试图避免让用户总是去事件地图并找到 事件并点击它,因为我有次数限制 显示地图(免费),这真的没有必要。 99.99% 的 当用户在我的网站上时,他们在事件屏幕上,而不是在我的主页上 屏幕,并且一次只对一个事件感兴趣。在里面 未来我想对其进行编码,所以如果他们来到我的网站,他们就会正确 参加他们的活动或他们最喜欢的主持人的新活动,这样我就可以避免 大量的点击并将我的 [Home] 控制器页面集中在新手上......但我 还没有自动登录功能,所以它在后面。

但现在我希望主持人始终拥有相同的活动网址: FragSwapper.com/[Host Abbreviation] ...并且知道它总是会转到 他们的当前事件每 4 个月有一个不同的 ID!!!

疯了...我知道...但从技术上讲很容易做到,我只是不知道 如何在 MVC 中正确执行操作。

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-routing asp.net-core asp.net-core-mvc url-redirection


    【解决方案1】:

    更新:ASP.Net Core 1.1

    根据release notes,已经创建了一个新的RewriteMiddleware。

    这提供了几种不同的预定义重写选项和实用程序扩展方法,最终可能会修改请求路径,就像在此答案中所做的那样。例如看RewriteRule的实现

    特别是对于 OP 问题,您需要实现自己的 IRule 类(从头开始或扩展现有的类,例如基于正则表达式的 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;
        }
    }
    

    然后按照相同的方法创建另一个类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。 (即使在内部更新了原始路径)

    【讨论】:

    • 嗯,这肯定超出了我在答案中的预期,而且这个概念肯定是我需要的!我想必须有某种方法可以介入,我只是不知道该往哪里看。我还在玩它,但我毫不怀疑中间件(这对我来说是一个完全未知的概念)是我需要做的。我发现使用 .Net Core 的最大问题是没有足够多的人遇到与我相同的问题,而且它给了我很少的地方可以查看。非常感谢您的宝贵时间。
    • 完全没问题!关于框架,我完全同意你的看法,asp.net core 中的很多东西都发生了变化,有时很难找到解决方法。如果有疑问,我会尝试从docs 开始,但即使在那里你也会发现许多尚未涵盖的主题。
    • 你是在MVC之前还是之后添加了中间件?然后在调用下一个之前更改路径?您正在设置什么路径以及应该处理它的控制器和路由是什么?没有看到您的代码很难知道,但上面的答案在新的 1.0.1 应用程序中运行良好。也许尝试一个新的空应用程序并慢慢开始添加您的代码,如果您仍然有问题,可能值得提出一个新问题! (您可能还会发现我写的有用的this article,它扩展了相同的想法)
    • 对不起,我刚刚删除了我的评论,没有看到你已经回复。我从一开始就重新开始,现在它可以工作了,我不知道究竟是什么导致了这个问题。感谢您的回答。很棒的代码
    猜你喜欢
    • 2018-12-24
    • 2011-08-24
    • 2015-05-07
    • 2011-12-22
    • 2017-09-10
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    • 2017-09-14
    相关资源
    最近更新 更多