Gaz*_*Gaz 4 c# asp.net-core-mvc asp.net-core 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>() });
}
Run Code Online (Sandbox Code Playgroud)
一个选择所有用户,另一个返回所有用户.在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) }
);
Run Code Online (Sandbox Code Playgroud)
我在startup.cs中设置了以下路由:
app.UseMvc(routes =>
{
routes.MapRoute(name: "User_Default", template: "v1/{controller=Users}/{action=Users}/{id?}");
});
Run Code Online (Sandbox Code Playgroud)
然而,这给了我一个 AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied
我究竟做错了什么?
在您使用的原始webapi代码Routes.MapHttpRoute中添加了webapi特定路由.这与MVC路由不同,MVC路由不会考虑操作中的参数,例如,如果您使用的话,MVC 5中会出现相同的问题Routes.MapRoute.
您的MVC 6代码也会发生同样的事情,因为您正在使用添加标准MVC路由routes.MapRoute.在这两种情况下,框架都找到了匹配相同路由的2个控制器动作,没有其他约束.它需要一些帮助才能选择其中一个动作.
消除api操作歧义的最简单方法是使用属性路由而不是定义路由,如下例所示:
[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" } });
}
}
Run Code Online (Sandbox Code Playgroud)
还有其他选项可以让您更改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;
}
}
Run Code Online (Sandbox Code Playgroud)
处理webapi 2样式控制器的更好选择是在MVC管道中添加约定.这正是Microsoft.AspNet.Mvc.WebApiCompatShim帮助迁移webapi 2控制器所做的工作.您可以在此处查看约定.请查看本指南以快速了解此软件包.
| 归档时间: |
|
| 查看次数: |
7798 次 |
| 最近记录: |