it-swarm.dev

AmbiguousActionException : 여러 작업이 일치했습니다. 다음 작업은 경로 데이터와 일치하고 모든 제약 조건이 충족되었습니다.

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)

이것이 내 ProductsController에 대한 index.cshtmlm에서 내 작업을 정의한 방법입니다.

<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?}");
        });

다음은 작업을 정의한 방법입니다.

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

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

내가 뭘 잘못 했니?

업데이트

귀하의 답변에 대한 @MegaTron에게 감사드립니다. 그러나 다른 컨트롤러에 대해 동일한 동작 경로를 가질 수없는 이유를 알고 싶습니다. 엔터티를 만드는 컨트롤러가 많으면 제안한 솔루션이 제대로 확장되지 않는 것 같습니다.

18
Zeus82

시험:

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

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

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

이 답변 Web API에서 서로 다른 두 컨트롤러에 동일한 이름을 가진 두 개의 경로를 가질 수없는 이유를 설명합니다. 이 문제를 피하기 위해 답변에 설명 된 솔루션을 구현하거나 개인적으로 권장하는 ServiceStack 을 사용할 수 있습니다.


긴 답변 : 웹 API 내에서 RESTful하는 방법 설명

먼저 컨트롤러 이름에 초점을 맞추겠습니다. 제어기 이름은 복수형이며 명사 만 사용해야합니다. 결과적으로이 두 컨트롤러는 다음과 같습니다.

  • 이벤트 : ChangeEvents 대신. 컨트롤러 이름이 아닌 PUT 내에서 변경이 발생할 수 있습니다.
  • 제품

RESTful 명명 표준에 대한 설명


둘째 : 컨트롤러 내의 엔드 포인트는 RESTful 표준과 관련하여 CRUD 조작으로 이름을 지정해야합니다.

  • POST
  • GET
  • 놓다
  • 지우다
  • 패치 : 옵션

이것은 Create 및 CreateChangeEvent 대신에 사용됩니다. 이것은 당신이 호출하는 동사를 찾는 데 도움이됩니다. 처음에는 각 컨트롤러에서 시작하기에 너무 많지 않아야하므로 작업에 대한 사용자 지정 이름을 지정할 필요가 없습니다.


셋째 : 경로는 not 각각에 대한 사용자 지정 이름을 가져야합니다. 다시 말하지만, 메소드 이름을 고수하는 것은 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)

결과는 다음과 같습니다.

  • / events/{id}에 대한 GET
  • / products/{id}에 대한 GET

마지막 : GET HTTP 호출의 경우 본문이 아닌 쿼리를 통해 입력을 보내야합니다. PUT/POST/PATCH 만 본문을 통해 표현을 보내야합니다. 이것은 REST의 Roy Fieldings 제약 조건의 일부입니다. 더 알고 싶다면 herehere 를보십시오.

각 매개 변수 앞에 [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)

나는 이것이 미래 독자들에게 도움이되기를 바랍니다.

8
AzzamAziz

기본 라우팅을 사용하려면 blew instrument를 따르십시오.

  1. 'ChangeEvents'컨트롤러 (있는 경우)에서 [Route("[controller]")]을 제거하십시오.
  2. HttpGet에서 라우팅 패턴 제거

여름철, 이것을 시도하십시오 :

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

// ProductsController
[HttpGet]
public IActionResult CreateChangeEvent(Guid id)
0
D.L.MAN

ASP.NET에서 모호한 메서드를 피하려면 route를 사용하십시오. 이 코드를 변경하십시오

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

// ProductsController
[HttpGet]
[Route("[action]/{id}")]
public IActionResult CreateChangeEvent(Guid id)
0
Rohan Shenoy

각 컨트롤러 위에 [Route("api/[controller]")] 속성을 추가하여 다른 경로에 작업 경로를 설정하면 각 컨트롤러에서 동일한 [HttpGet("{id}")]을 사용할 수 있습니다. 이것은 꽤 잘 확장되어야합니다. Microsoft 문서의 this 예를 참조하십시오.

[Route] 주석을 사용하여 각 컨트롤러에 대한 경로를 지정하지 않으면 ASP.NET Core MVC는 요청을 처리하기 위해 어떤 동작을 선택해야하는지 알 수 없습니다.

0
B12Toaster