【问题标题】:Retrieving Route Data from Virtual Path in MVC Router从 MVC 路由器中的虚拟路径检索路由数据
【发布时间】:2018-08-12 01:48:30
【问题描述】:

我正在开发一个 .NET Core MVC 应用程序,该应用程序需要允许使用替代控制器/操作名称。为此,我在 MapRoute 上使用自己的路由器:

app.UseMvc(routes =>
        {
            routes.Routes.Add(new CustomRouter(routes.DefaultHandler));
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });

我的自定义路由器观察请求的控制器和操作,并基于它在请求中的 RouteData 中放置一个新值:

public async Task RouteAsync(RouteContext context)
{
   [...]
   if (requestedAction == "fakeAction")
    context.RouteData.Values["action"] = "realAction";

但是,要确定requestedAction 的值,我基本上是采用请求的路径,拆分它并以这种方式获取它的值。这似乎不是最理想的。

我想做的应该是这样的:

var rr = new RouteBuilder(app);
var myRoute = rr.MapRoute(...).Build();
var myRouteData = myRoute.GetRouteData(context);
myRouteData["action"] == "fakeAction";

如果我能做到以下几点,我会非常喜欢这个问题的另一个解决方案:

   app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "something",
                template: "{controller=Home}/{action=Index}/{id?}");
            routes.Routes.Add(new CustomRouter(routes.DefaultHandler));
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });

但我的 something 路由实际上并没有路由任何东西,并且仅用作为我的 CustomRouter 定义 RouteData 的一种方式。

这两种可能吗?我不喜欢我们不干净地实现现有功能的想法,因为这既是代码异味,也是未来潜在的维护困难。

【问题讨论】:

    标签: c# asp.net-core asp.net-core-mvc asp.net-mvc-routing


    【解决方案1】:

    希望对你有帮助:

    public async Task RouteAsync(RouteContext context)
    {
        var requestPath = context.HttpContext.Request.Path.Value;
    
        if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
        {
            // Trim the leading slash
            requestPath = requestPath.Substring(1);
        }
    
        // Get the page that matches.
        var page = GetPageList()
            .Where(x => x.VirtualPath.Equals(requestPath))
            .FirstOrDefault();
    
        // If we got back a null value set, that means the URI did not match
        if (page == null)
        {
            return;
        }
    
    
        //Invoke MVC controller/action
        var oldRouteData = context.RouteData;
        var newRouteData = new RouteData(oldRouteData);
        newRouteData.Routers.Add(this.target);
    
        // TODO: You might want to use the page object (from the database) to
        // get both the controller and action, and possibly even an area.
        // Alternatively, you could create a route for each table and hard-code
        // this information.
     if (context.RouteData.Values["action"] == "fakeAction")
        newRouteData.Values["controller"] = "realController";
        newRouteData.Values["action"] = "realAction";
    
        // This will be the primary key of the database row.
        // It might be an integer or a GUID.
        newRouteData.Values["id"] = page.Id;
    
        try
        {
            context.RouteData = newRouteData;
            await this.target.RouteAsync(context);
        }
        finally
        {
            // Restore the original values to prevent polluting the route data.
            if (!context.IsHandled)
            {
                context.RouteData = oldRouteData;
            }
        }
    }
    
    app.UseMvc(routes =>
    {
        routes.Routes.Add(
           new CustomRoute(routes.ServiceProvider.GetRequiredService<IMemoryCache>(), 
                           routes.DefaultHandler));
    
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    
    
    });
    

    【讨论】:

    • 这似乎假设FakeAction 存在并且不是......好吧......假的?这并不能真正解决问题。
    猜你喜欢
    • 2017-07-14
    • 1970-01-01
    • 2011-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-11
    • 1970-01-01
    • 2019-05-12
    相关资源
    最近更新 更多