API Routes: Multiple operations with path

别等时光非礼了梦想. 提交于 2019-12-10 18:37:17

问题


I am trying to configure my API routes, and I can't seem to get around this error from Swagger:

500 : {"Message":"An error has occurred.","ExceptionMessage":"Not supported by Swagger 2.0: Multiple operations with path 'api/Doors/{OrganizationSys}' and method 'GET'.

I understand why I am getting the error, but I'm not sure how to fix it. Here are the API end points:

public IHttpActionResult Get(int organizationSys)
{
    ....
}

public IHttpActionResult Get(int organizationSys, int id)
{
    ....
}


public IHttpActionResult Post([FromBody]Doors door)
{
    ....
}

public IHttpActionResult Put([FromBody]Doors door)
{
    ....
}

public IHttpActionResult Delete(int organizationSys, int id)
{
    ....
}

And here are my routes, which are clearly not correct:

config.Routes.MapHttpRoute(
    name: "route1",
    routeTemplate: "api/{controller}/{organizationSys}"
);

config.Routes.MapHttpRoute(
    name: "route2",
    routeTemplate: "api/{controller}/{organizationSys}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}"
);

UPDATE:

I now have this, but get the same error:

config.Routes.MapHttpRoute(
    name: "route1",
    routeTemplate: "api/{controller}/{organizationSys}/{id}"
);

config.Routes.MapHttpRoute(
    name: "route2",
    routeTemplate: "api/{controller}/{organizationSys}"
);

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}"
);

UPDATE 2: This is what I have now....

Getting closer, I think.

[Route("api/Doors/{organizaitonSys}")]
public IHttpActionResult Get(int organizationSys)
{
    ....
}

[Route("api/Doors/{organizaitonSys}/{id}")]
public IHttpActionResult Get(int organizationSys, int id)
{
    ....
}

[Route("api/Doors")]
public IHttpActionResult Post([FromBody]Doors door)
{
    ....
}

[Route("api/Doors")]
public IHttpActionResult Post([FromBody]Doors door)
{
    ....
}

[Route("api/Doors/{organizaitonSys}/{id}")]
public IHttpActionResult Delete(int organizationSys, int id)
{
    ....
}

And then the routes:

config.Routes.MapHttpRoute(
name: "route1",
routeTemplate: "api/{controller}/{organizationSys}/{id}"
);

config.Routes.MapHttpRoute(
name: "route2",
routeTemplate: "api/{controller}/{organizationSys}"
);

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}"
);

However, when I try to call

GET: http://localhost:26307/api/Doors/1012

or

GET: http://localhost:26307/api/Doors/1012/23

or

DELETE: http://localhost:26307/api/Doors/1012/23

I get 404 errors. And now in Swagger, the organizationSys parameter shows up twice in the Try It section:


回答1:


route1 and route2 have the same mapping because of the optional {id}. remove the optional parameter and put route2 before route1 as route1 is more general.

You can also provide constraints, which restrict how a URI segment can match a placeholder:

constraints: new { id = @"\d+" }   // Only matches if "id" is one or more digits.

Example

config.Routes.MapHttpRoute(
    name: "route2",
    routeTemplate: "api/{controller}/{organizationSys}/{id}",
    constraints: new { id = @"\d+" }   // Only matches if "id" is one or more 
);

config.Routes.MapHttpRoute(
    name: "route1",
    routeTemplate: "api/{controller}/{organizationSys}"
);

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}"
);

There will also be an issue mapping to

public IHttpActionResult Get(int OrganizationSys, int DoorID) {
    ....
}

because of the DoorID parameter, which does not match that of the route template. rename it to id or update the template to match.

public IHttpActionResult Get(int organizationSys, int id) {
    ....
}

If using attribute routing then make sure it is enabled before convention-based routes

public static class WebApiConfig {
    public static void Register(HttpConfiguration config) {
        // Attribute routing.
        config.MapHttpAttributeRoutes();

        // Convention-based routing.

       //...code removed for brevity
    }
}

Then apply the routes to the controller via attributes.

[RoutePrefix("api/Doors")]
public class DoorsController : ApiController {

    //matches GET api/doors/5
    [HttpGet]
    [Route("{organizationSys:int}")]
    public IHttpActionResult Get(int organizationSys) {
        //....
    }

    //matches GET api/doors/5/1
    [HttpGet]
    [Route("{organizationSys:int}/{id:int}")]
    public IHttpActionResult Get(int organizationSys, int id) {
        ....
    }    

    //matches POST api/doors
    [HttpPost]
    [Route("")]
    public IHttpActionResult Post([FromBody]Doors door) {
        //....
    }

    //matches PUT api/doors
    [HttpPut]
    [Route("")]    
    public IHttpActionResult Put([FromBody]Doors door) {
        //....
    }

    //matches DELETE api/doors/5/1
    [HttpDelete]
    [Route("{organizationSys:int}/{id:int}")]    
    public IHttpActionResult Delete(int organizationSys, int id) {
        //....
    }    
}

Note the use of RoutePrefix attribute to reduce repeated template parts and route constraints.

Reference Attribute Routing in ASP.NET Web API 2



来源:https://stackoverflow.com/questions/49056556/api-routes-multiple-operations-with-path

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!