【问题标题】:Define MVC Route by name in .net Core在 .net Core 中按名称定义 MVC 路由
【发布时间】:2020-06-29 15:49:17
【问题描述】:

我定义了 2 条路线:

app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapControllerRoute("api", "{controller=Home}/api/v1/{action=Index}/{id?}");
        });

在控制器中,如果我没有在控制器中指定路由,它将使用任何一个。两个网址都有效:

https://myapp/mymodel/api/v1/id/123

https://myapp/mymodel/id/123

我希望它仅适用于第一个 url,但如果将例如 [Route("api")] 添加到控制器,则上述路由都不起作用。

[Route("api")] //with this line it returns 404
public mymodel ID(int? id)
{
  //some code
 }

【问题讨论】:

  • 我已经读过,所以添加路由名称似乎应该可行。我一定是错过了什么。
  • 您不是在添加路由名称,而是在为基于属性的路由添加路由模板。 UseEndpoints 用于基于约定的路由。两个独立的概念
  • 如果我将路由直接添加到控制器,它会按我的意愿工作 [Route("[controller]/api/v1/id/{id?}")],但我想成为能够从启动类中选择模板,而不是在控制器中编写整个路由。

标签: asp.net-mvc asp.net-core routes


【解决方案1】:

来自official doc

路由名称可用于根据特定路由生成 URL。路由名称对路由的 URL 匹配行为没有影响,仅用于 URL 生成。路由名称在应用程序范围内必须是唯一的。

这里是自定义一个 actionfilter 属性的解决方法,该属性检查 url 是否与 api 的路由模板匹配,您可以参考:

ApiRouteTemplateAttribute

 public class ApiRouteTemplateAttribute:ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var routeTemplate = "{controller=Home}/api/v1/{action=Index}/{id?}";
        var template = TemplateParser.Parse(routeTemplate);

        var matcher = new TemplateMatcher(template, GetDefaults(template));
        var routeValues = new RouteValueDictionary();
        string LocalPath = context.HttpContext.Request.Path;

        var result = matcher.TryMatch(LocalPath, routeValues);
        //if the match is false ,return a exception information.
        if (!result)
        {
            context.Result = new BadRequestObjectResult(new Exception("The url is incorrect!"));
        }
    }

    private RouteValueDictionary GetDefaults(RouteTemplate parsedTemplate)
    {
        var result = new RouteValueDictionary();

        foreach (var parameter in parsedTemplate.Parameters)
        {
            if (parameter.DefaultValue != null)
            {
                result.Add(parameter.Name, parameter.DefaultValue);
            }
        }

        return result;
    }
}

控制器

    [ApiRouteTemplate]
    public Exam ID(int? id)
    {
        return _context.Exams.Find(id);
    }

结果

【讨论】:

    猜你喜欢
    • 2020-04-17
    • 2020-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多