Zeu*_*s82 19 c# asp.net-core-mvc asp.net-core asp.net-core-routing
我正在使用ASP.NET Core MVC创建一个网站.当我点击某个动作时,我收到此错误:
AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied:
Web.Controllers.ChangeEventsController.Create (Web)
Web.Controllers.ProductsController.CreateChangeEvent (Web)
Run Code Online (Sandbox Code Playgroud)
这就是我在我的ProductsController的index.cshtmlm中定义我的动作的方法:
<a asp-controller="ChangeEvents" asp-action="Create" asp-route-id="@item.Id">Create Change Event</a>
Run Code Online (Sandbox Code Playgroud)
这是我的路线:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
Run Code Online (Sandbox Code Playgroud)
以下是我定义操作的方式:
// ChangeEventsController
[HttpGet("{id}")]
public IActionResult Create(Guid id)
// ProductsController
[HttpGet("{id}")]
public IActionResult CreateChangeEvent(Guid id)
Run Code Online (Sandbox Code Playgroud)
我做错了什么?
更新
感谢@MegaTron的回复,但是我想知道为什么我不能为不同的控制器提供相同的操作路径.如果我有许多控制器,每个创建实体,我觉得你提出的解决方案不会很好地扩展.
Rom*_*syk 30
尝试:
// ChangeEventsController
[HttpGet("Create/{id}")]
public IActionResult Create(Guid id)
// ProductsController
[HttpGet("CreateChangeEvent/{id}")]
public IActionResult CreateChangeEvent(Guid id)
Run Code Online (Sandbox Code Playgroud)
Azz*_*ziz 10
虽然投票最多的答案确实可以解决问题,但正如@ B12Toaster所提到的那样,它会违反REST规则。通过我的回答,我将尝试在保持RESTful的同时解决问题。
TLDR:将Name属性添加到HTTP动词属性(GET或其他方式)
为了使两个GET在两个控制器中都能工作,请执行以下操作:
// ChangeEventsController
[HttpGet(Name = "Get an event")]
[Route("{id}")]
public IActionResult Create(Guid id)
// ProductsController
[HttpGet(Name = "Get a product")]
[Route("{id}")]
public IActionResult CreateChangeEvent(Guid id)
Run Code Online (Sandbox Code Playgroud)
此答案说明了为什么在Web API中的两个不同控制器上不能有两个具有相同名称的路径。您可以实施答案中讨论的解决方案来避免此问题,或者可以使用我个人推荐的ServiceStack。
长答案:解释如何在Web API中实现RESTful
首先:让我们关注控制器名称。控制器名称应为复数形式且只能为名词。这将导致以下两个控制器:
第二:就RESTful标准而言,控制器内的端点应命名为CRUD操作。
这代替Create和CreateChangeEvent。这可以帮助您找到要调用的动词。不需要为操作自定义命名,因为在每个控制器中首先应该没有太多的名称。
第三:你的路线应该不为每个自定义名称。同样,坚持我们的方法名称,它们应该仅是CRUD操作。
在这种情况下:
// EventsController
[HttpGet(Name = "Get an event")]
[Route("events/{id}")]
public IActionResult Get(Guid id)
// ProductsController
[HttpGet(Name = "Get a product")]
[Route("products/{id}")]
public IActionResult Get(Guid id)
Run Code Online (Sandbox Code Playgroud)
这将导致:
最后:对于GET HTTP调用,您应该通过查询而不是正文发送输入。只有PUT / POST / PATCH应该通过主体发送表示。这是REST中Roy Fieldings约束的一部分。如果您想进一步了解,请在这里和这里。
您可以通过在每个参数之前添加[FromQuery]属性来实现。
// EventsController
[HttpGet(Name = "Get an event")]
[Route("events/{id}")]
public IActionResult Get([FromQuery] Guid id)
// ProductsController
[HttpGet(Name = "Get a product")]
[Route("products/{id}")]
public IActionResult Get([FromQuery] Guid id)
Run Code Online (Sandbox Code Playgroud)
我希望这对将来的读者有帮助。
| 归档时间: |
|
| 查看次数: |
33026 次 |
| 最近记录: |