ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – MVC 6中的路由

2019-05-28 09:54:25  阅读:252  来源: 互联网

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


我有一个超级简单的控制器,有两种方法:

public IActionResult Users(long id)
{
    return Json(new { name = "Example User" });
}

public IActionResult Users()
{
    return Json(new { list = new List<User>() });
}

一个选择所有用户,另一个返回所有用户.在web api 2中,我可以使用以下路由,一切正常:

config.Routes.MapHttpRoute(
                name: "Users",
                routeTemplate: "v1/Users",
                defaults: new { action = "Users", controller = "Users" },
                constraints: null,
                handler: new TokenValidationHandler() { InnerHandler = new HttpControllerDispatcher(config) }
            );

我在startup.cs中设置了以下路由:

app.UseMvc(routes =>
            {
                routes.MapRoute(name: "User_Default", template: "v1/{controller=Users}/{action=Users}/{id?}");
            });

但是这给了我一个AmbiguousActionException:匹配多个动作.以下操作匹配路由数据并满足所有约束

我究竟做错了什么?

解决方法:

在原始的webapi代码中,您使用的是Routes.MapHttpRoute,它添加了特定于webapi的路由.这与MVC路由不同,MVC路由不考虑动作中的参数,例如,如果使用Routes.MapRoute,则在MVC 5中会遇到相同的问题.

您的MVC 6代码也会发生同样的事情,因为您正在使用routes.MapRoute添加标准MVC路由.在这两种情况下,框架都找到了匹配相同路由的2个控制器动作,没有其他约束.它需要一些帮助才能选择其中一个动作.

消除api操作歧义的最简单方法是使用属性路由而不是定义路由,如this example所示:

[Route("v1/[controller]")]
public class UsersController : Controller
{
    [HttpGet("{id:int}")]
    public IActionResult Users(long id)
    {
        return Json(new { name = "Example User" });
    }

    public IActionResult Users()
    {
        return Json(new { list = new[] { "a", "b" } });
    }
}

还有其他选项可以让您更改MVC 6中MVC路由的行为.您可以创建自己的IActionConstraint属性以强制执行是否具有给定参数.这样,其中一个动作需要路由中的id参数,而另一个动作需要没有id参数(警告,未经测试的代码):

public class UsersController : Controller
{
    [RouteParameterConstraint("id", ShouldAppear=true)]
    public IActionResult Users(long id)
    {
        return Json(new { name = "Example User" });
    }

    [RouteParameterConstraint("id", ShouldNotAppear=true)]
    public IActionResult Users()
    {
        return Json(new { list = new[] { "a", "b" } });
    }
}

public class RouteParameterConstraintAttribute : Attribute, IActionConstraint
{
    private routeParameterName;

    public RouteParameterConstraintAttribute(string routeParameterName)
    {
        this.routerParamterName = routerParameterName;
    }

    public int Order => 0;
    public bool ShouldAppear {get; set;}
    public bool ShouldNotAppear {get; set;}

    public bool Accept(ActionConstraintContext context)
    {
        if(ShouldAppear) return context.RouteContext.RouteData.Values["country"] != null;
        if(ShouldNotAppear) return context.RouteContext.RouteData.Values["country"] == null;

        return true;
    }
}

处理webapi 2样式控制器的更好选择是在MVC管道中添加约定.这正是Microsoft.AspNet.Mvc.WebApiCompatShim为帮助迁移webapi 2控制器所做的工作.您可以看到添加的约定here.检查this guide以快速了解此包.

标签:c,asp-net-core,asp-net-core-mvc,asp-net-core-routing
来源: https://codeday.me/bug/20190528/1170064.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有