solicitud route recurso que ningĂșn mvc encontrado con coincida apicontroller c# asp.net-web-api asp.net-web-api-routing attributerouting

route - web api rest c#



Varios tipos de controladores con el mismo prefijo de ruta ASP.NET Web Api (2)

La API web (1.x-2.x) no admite varias rutas de atributos con la misma ruta en diferentes controladores. El resultado es un 404, porque todas las rutas coinciden con más de un controlador y en ese punto la API web considerará el resultado ambiguo.

Tenga en cuenta que MVC Core admite esta nota de escenario: MVC Core funciona como API de MVC y web.

Si elige usar la API web 2.11 (o más reciente), puede crear una restricción de ruta para el método http por controlador y usarla en lugar del atributo de ruta incorporado. El siguiente ejemplo muestra que puede usar RoutePrefix o directamente Rutas (como la respuesta de kmacdonald).

using System.Collections.Generic; using System.Net.Http; using System.Web.Http; using System.Web.Http.Routing; public class BooksWriteController : ApiController { [PostRoute("api/Books")] public void Post() { } } [RoutePrefix("api/books")] public class BooksReadController : ApiController { [GetRoute] public void Get() { } [GetRoute("{id:int}")] public void Get(int id) { } }

Estas dos clases simplifican el uso del atributo de ruta de restricción

class GetRouteAttribute : MethodConstraintedRouteAttribute { public GetRouteAttribute(string template) : base(template ?? "", HttpMethod.Get) { } } class PostRouteAttribute : MethodConstraintedRouteAttribute { public PostRouteAttribute(string template) : base(template ?? "", HttpMethod.Post) { } }

Esta clase permite agregar restricciones a la ruta generada.

class MethodConstraintedRouteAttribute : RouteFactoryAttribute { public MethodConstraintedRouteAttribute(string template, HttpMethod method) : base(template) { Method = method; } public HttpMethod Method { get; private set; } public override IDictionary<string, object> Constraints { get { var constraints = new HttpRouteValueDictionary(); constraints.Add("method", new MethodConstraint(Method)); return constraints; } } }

Esto es solo una restricción de ruta estándar, nit: es posible que desee almacenar en caché el objeto de restricciones para reducir las asignaciones.

class MethodConstraint : IHttpRouteConstraint { public HttpMethod Method { get; private set; } public MethodConstraint(HttpMethod method) { Method = method; } public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection) { return request.Method == Method; } }

¿Es posible separar GET y POST en tipos de Controladores API separados y acceder a ellos usando el mismo Prefijo de Ruta?

Aquí están mis controladores:

[RoutePrefix("api/Books")] public class BooksWriteController : EventStoreApiController { [Route("")] public void Post([FromBody] CommandWrapper commandWrapper){...} } [RoutePrefix("api/Books")] public class BooksReadController : MongoDbApiController { [Route("")] public Book[] Get() {...} [Route("{id:int}")] public Book Get(int id) {...} }


No siempre es necesario especificar un RoutePrefix en su controlador. Simplemente puedes poner la ruta directamente en los métodos web:

public class BooksWriteController : EventStoreApiController { [Route("api/Books")] public void Post([FromBody] CommandWrapper commandWrapper){...} } public class BooksReadController : MongoDbApiController { [Route("api/Books")] public TaskTypeInfo[] Get() {...} [Route("api/Books/{id:int}")] public TaskTypeInfo Get(int id) {...} }

Sin embargo, me imagino que su RoutePrefix funcionaría bien en ambos controladores. Creo que el atributo RoutePrefix se usa junto con el atributo Route que realmente define la ruta. Esto significa que mientras no tengas rutas en conflicto (esto es un problema), deberías estar bien.