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:
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