如何从控制器动作方法注册新的路由

本文关键字:注册 路由 方法 控制器 | 更新日期: 2023-09-27 18:02:32

我必须为这些页面开发一些页面和公共句柄(也就是别名)。

(得到的想法:在facebook你可以有你的网页别名,最终的URL将看起来像facebook/alias而不是facebook/somelongpieceofsomestuff)。

我在db表中存储公共句柄,并确保所有句柄都是唯一的。现在我已经为句柄添加了路由注册:

public override void RegisterArea(AreaRegistrationContext context)
{
    // Assume, that I already have dictionary of handles and ids for them
    foreach(var pair in publicHandlesDictionary)
    {
        var encId = SomeHelper.Encrypt(pair.Key);
        context.MapRoute(pair.Value, pair.Value,
            new {controller = "MyController", action="Index", id = encId});
    }
}

所以,现在我可以通过使用地址http://example.com/alias1而不是http://example.com/MyController/Index&id=someLongEncryptedId到达某些页面。这个东西很好,对吧

但是如果我启动应用程序,然后添加新的句柄呢?这个新句柄不会被注册,因为所有的路由注册都是在app启动时执行的。基本上,我必须重新启动应用程序(IIS, VS/IIS Express, Azure,无关紧要)才能重新注册所有路由,包括我的新句柄。

那么,有没有办法从控制器的动作方法添加新的路由注册(当添加新的句柄时)?

如何从控制器动作方法注册新的路由

你不需要在应用启动时创建所有的路由。

只是使用IRouteConstraint来确定应该遵循别名逻辑

public class AliasConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        var alias = values[parameterName];
        // Assume, that I already have dictionary of handles and ids for them
        var publicHandlesDictionary = SomeStaticClass.Dic;
        if (publicHandlesDictionary.ContainsValue(alias))
        {
            //adding encId as route parameter
            values["id"] = SomeHelper.Encrypt(publicHandlesDictionary.FirstOrDefault(x => x.Value == alias).Key);
            return true;
        }
        return false;
    }
}   
//for all alias routes
routes.MapRoute(
    name: "Alias",
    url: "{*alias}",
    defaults: new {controller = "MyController", action = "Index"},
    constraints: new { alias = new AliasConstraint() }
);
//for all other default operations
routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

这样你就可以随时更新publicHandlesDictionary, route也会接收这些变化