AmbiguousActionException:多个动作匹配.以下动作与路线数据相匹配,并且满足所有约束条件 [英] AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied

查看:752
本文介绍了AmbiguousActionException:多个动作匹配.以下动作与路线数据相匹配,并且满足所有约束条件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用ASP.NET Core MVC创建一个网站.当我单击一个动作时,出现此错误:

I am creating a website using ASP.NET Core MVC. When I click on an action I get this error:

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)

这是我在ProductsController的index.cshtmlm中定义我的操作的方式:

This is how I defined my action in the index.cshtmlm for my ProductsController:

<a asp-controller="ChangeEvents" asp-action="Create" asp-route-id="@item.Id">Create Change Event</a>

这是我的路线:

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });

这是我定义动作的方式:

Here is how I defined the actions:

// ChangeEventsController
[HttpGet("{id}")]
public IActionResult Create(Guid id)

// ProductsController
[HttpGet("{id}")]
public IActionResult CreateChangeEvent(Guid id)

我做错了什么?

更新

感谢@MegaTron的回复,但是我想知道为什么我不能为不同的控制器使用相同的动作路径.我觉得如果我有很多控制器每个都创建实体,那么您建议的解决方案将无法很好地扩展.

Thanks @MegaTron for your response, however I would like to know why I can't have the same action path for different controllers. I feel like the solution you proposed won't scale well if I have many controllers that each create entities.

推荐答案

虽然投票最多的答案确实可以解决问题,但正如@ B12Toaster所提到的那样,这将违反REST规则.有了我的回答,我将尝试在保持RESTful的同时解决问题.

While the most up-voted answer does solve the issue, as mentioned by @B12Toaster it would violate the rules of REST. With my answer I will try to solve the problem while remaining RESTful.

TLDR :将Name属性添加到您的HTTP谓词属性(获取GET或其他方式)

TLDR: Add the Name property to your HTTP verb attribute (GET or otherwise)

为了使两个GET在两个控制器中都能工作,请执行以下操作:

In order to get both GET to work in both controllers do this:

// 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)

此答案解释了为什么在Web API中的两个不同的控制器上不能有两个具有相同名称的路径.您可以实施答案中讨论的解决方案来避免此问题,也可以使用我个人推荐的 ServiceStack .

This answer explains why you can't have two paths with the same name on two different controllers in Web API. You can implement the solution discussed in the answer to avoid this problem, or you can use ServiceStack which I personally would recommend.

长答案:介绍如何在Web API中实现RESTful

Long answer: Explaining how to be RESTful within Web API

首先:让我们集中讨论控制器名称.控制器名称应为复数形式且只能为名词.这将导致这两个控制器:

First: let's focus on the controller names. The controller names should be plural and nouns only. That would result in these two controllers:

  • 事件:代替ChangeEvents.更改可以在PUT中发生,而不是作为控制器名称发生.
  • 产品

解释RESTful命名标准

第二:相对于RESTful标准,控制器内的端点应命名为CRUD操作.

Second: The endpoints within a controller should be named as CRUD operations in respect to RESTful standards.

  • 开机自检
  • 获取
  • 放置
  • 删除
  • PATCH:可选

这代替Create和CreateChangeEvent.这可以帮助您找到要调用的动词.不需要为操作自定义命名,因为在每个控制器中首先应该没有太多.

This is instead of Create and CreateChangeEvent. This helps you locate which verbs you're invoking. There is no need for custom naming for the operations, as there shouldn't be too many in the first place to begin with in each controller.

第三条:您的路由应 not 都具有自定义名称.同样,坚持我们的方法名称,它们应该仅是CRUD操作.

Third: Your routes should not have custom names for each. Again, sticking to our method names, they should be CRUD operations only.

在这种情况下:

// 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)

这将导致:

  • 获取/events/{id}
  • 获取/products/{id}

最后:对于GET HTTP调用,您应该通过查询而不是正文发送输入.仅PUT/POST/PATCH应该通过正文发送表示.这是REST中Roy Fieldings约束的一部分.如果您想进一步了解,请在此处

Last: For GET HTTP calls, you should send your input via query rather than body. Only PUT/POST/PATCH should send a representation via body. This is part of the Roy Fieldings constraints in REST. If you want to know further, look here and here.

您可以通过在每个参数之前添加[FromQuery]属性来实现此目的.

You can do this by adding the [FromQuery] attribute before each of the parameters.

// 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)

我希望这会对以后的读者有所帮助.

I hope this would be helpful to future readers.

这篇关于AmbiguousActionException:多个动作匹配.以下动作与路线数据相匹配,并且满足所有约束条件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆