Asp.Net Core中的自定义IRouter没有发生任何变化

时间:2016-04-19 16:25:09

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

我的路由器实现如下:

public class TenantUrlResolverRouter : IRouter
{
    private readonly IRouter _defaultRouter;

    public TenantUrlResolverRouter(IRouter defaultRouter)
    {
        _defaultRouter = defaultRouter;
    }

    public VirtualPathData GetVirtualPath(VirtualPathContext context)
    {
        return _defaultRouter.GetVirtualPath(context);
    }

    public async Task RouteAsync(RouteContext context)
    {
        var oldRouteData = context.RouteData;
        var newRouteData = new RouteData(oldRouteData);
        newRouteData.Values["library"] = "Default";
        try
        {
            context.RouteData = newRouteData;
            await _defaultRouter.RouteAsync(context);
        }
        finally
        {
            if (!context.IsHandled)
            {
                context.RouteData = oldRouteData;
            }
        }
    }
}

然后我在Startup.cs中定义它:

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

但没有任何结果,RouteData.Values中的RouteContext始终为空,我总是未知,而它需要默认。这不是预定义模板的问题,因为它甚至在没有{library=Unknown}的情况下工作,而{library}/{controller=Home}/{action=Index}/{id?}也不起作用。

这个自定义IRouter有什么问题?

1 个答案:

答案 0 :(得分:2)

您没有提供一整套路线值。要转到某个操作,您需要同时提供controlleraction

此外,您在路线中没有匹配条件。匹配条件将确定传入请求是否与当前路由匹配。在内置路由中,urlconstraints是匹配条件。但是,在自定义路由中,您需要放置if块以确保任何不匹配的请求将传递到下一个已注册的路由。

  

注意:这是自定义路由中最强大的部分。内置路由只能与URL匹配。但是使用自定义路由,您可以匹配请求中的任何内容。例如,您可以仅针对特定域或某个子域进行路由匹配。您甚至可以使其匹配发布的表单值或会话状态等内容。

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);
    }

    var segments = requestPath.Split('/');

    // Required: Match condition to determine if the incoming request
    // matches this route. If not, you should allow the framework to
    // match another route by doing nothing here.
    if (segments.Length > 0 && segments[0].Equals("libraryname", StringComparison.OrdinalIgnoreCase))
    {
        var oldRouteData = context.RouteData;
        var newRouteData = new RouteData(oldRouteData);
        newRouteData.Values["library"] = segments[0];
        newRouteData.Values["controller"] = segments[1];
        newRouteData.Values["action"] = segments[2];
        try
        {
            context.RouteData = newRouteData;
            await _defaultRouter.RouteAsync(context);
        }
        finally
        {
            if (!context.IsHandled)
            {
                context.RouteData = oldRouteData;
            }
        }
    }
}

有关实施IRouter的详情,请参阅this question