繁体   English   中英

ASP .Net Core在运行时改变路由

[英]ASP .Net Core changing route on runtime

我的问题:我有多个控制器类,我希望他们的路由改变取决于外部配置文件中的某个值(让我们称之为ID)(可以更改)。 该ID不是常量,它是在应用程序启动时生成的。

[Route("api/projects/" + idForTest1FromConfigFile]
public class Test1Controller : Controller 
{
    public IActionResult Index()
    {
        return View();
    }
}

更新然后我有Test2Controller,它与Test1Controller基本相同,但返回不同的视图

[Route("api/projects/" + idForTest2FromConfigFile]
public class Test2Controller : Controller 
{
    public IActionResult Index()
    {
        return View();
    }
}

所以我在配置文件中说:

Test1 : 123
Test2 : 456

所以当我调用https:// localhost:44391 / api / projects / 123 / Index时我想从Test1Controller获取索引页面,当我调用https:// localhost:44391 / api / projects / 456 / Index我想要从Test2Controller获取索引页面

有什么方法可以做到这一点? 谢谢

如果在启动时产生的标识符,但那么它的不变,你可以生成一个动态路由映射,当你调用UseMvc()的内部Configure方法:

var id1 = GetIdFromSomewhere();
var id2 = GetIdFromSomewhere();
app.UseMvc(routes =>
{
    // Test1Controller
    routes.MapRoute("test-route-1",
        "/api/projects/" + id1 + "/{action}",
        new { controller = "Test1", action = "Index" });

    // Test2Controller
    routes.MapRoute("test-route-2",
        "/api/projects/" + id2 + "/{action}",
        new { controller = "Test2", action = "Index" });

    // …
});

如果您想使用更灵活的方法,可以考虑使用自定义控制器约定,该约定可以使用IControllerModelConvention接口实现。 使用它,您可以将配置对象传递给自定义约定并使用它来应用路由。 有很多方法可以解决这个问题,但这是一个示例实现:

public class RoutingControllerModelConvention : IControllerModelConvention
{
    private readonly IConfiguration _configuration;

    public RoutingControllerModelConvention(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public void Apply(ControllerModel controllerModel)
    {
        const string RouteTemplate = "/api/projects/<id>/[action]";

        var routeId = _configuration["RouteIds:" + controllerModel.ControllerName];
        var firstSelector = controllerModel.Selectors[0];

        if (firstSelector.AttributeRouteModel == null)
            firstSelector.AttributeRouteModel = new AttributeRouteModel();

        firstSelector.AttributeRouteModel.Template = RouteTemplate.Replace("<id>", routeId);
    }
}

在这个例子中,我将一个IConfiguration实例放入构造函数中,该构造函数由以下appsettings.json填充:

{
    "RouteIDs": {
        "Test1": 123,
        "Test2": 234
    }
}

我意识到你可能正在为你的配置使用其他东西,但在这个例子中使用这种方法应该有助于更简单地解释事情。

在为项目中的每个控制器调用的RoutingControllerModelConvention.Apply方法中,我们从IConfiguration实例中查找相应的值,我们使用controllerModel.ControllerName来获取例如Test1 在这个例子中,这给了我们一个值123 接下来,我们抓住第一个选择器(总是至少有一个),最终将其路径模板设置为/api/projects/123/[action]

使用此方法,您无需将[Route]属性应用于控制器本身,也无需在Startup使用MapRoute 添加新控制器时,您需要做的就是创建控制器并相应地添加一个条目(在此示例中为appsettings.json )。

要使用此自定义约定,您需要在Startup.ConfigureServices配置它:

services.AddMvc(options =>
{
    options.Conventions.Add(new RoutingControllerModelConvention(Configuration));
});

有关更多信息,请在此处记录应用程序模型和约定: 使用ASP.NET Core中的应用程序模型


我很欣赏上面的实现并不完美:你想要检查null和配置中找不到的控制器名称等等。这至少应该可以帮助你开始一种方法。相当灵活。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM