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

查看:25
本文介绍了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)

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

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 命名标准说明

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

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

  • 发布
  • 获取
  • 放置
  • 删除
  • 补丁:可选

这不是 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.

第三:你的路线应该有每个自定义名称.同样,坚持我们的方法名称,它们应该只是 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天全站免登陆