Reputation: 13616
I work on my web api project.
I have two get action methods in controller.
Here the controller:
namespace Playground.Web.Controllers.API
{
[RoutePrefix("api/DamageEvent/{actionType}")]
public class DamageEventController : ApiController
{
#region API methods
[HttpGet]
public async Task<IHttpActionResult> GetDamageEvent(int damageEventId = 0)
{
//some logic
}
[HttpGet]
[Route("{ddd:int}")]
public async Task<IHttpActionResult> GetDamageEvent2(int ddd = 0)
{
//some logic
}
#endregion
}
}
Here WebApiConfig defenition:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.JsonFormatter.SerializerSettings.DateFormatString = "dd/MM/yyyy";
}
}
Here the example of URL in fiddler compose to trigger web api action:
http://localhost/playground/api/DamageEvent/GetDamageEvent2/?ddd=22
I expect that for the URL above the GetDamageEvent2 web api action will be fired. But instead GetDamageEvent
action method is fired.
Why GetDamageEvent2 not fired? Any idea what do I am missing?
==============================Update================================
After I red answer from Nkosi
I made some changes to my code, I added to class WebApiConfig new route:
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
And here the changes in action type:
namespace Playground.Web.Controllers.API
{
[RoutePrefix("api/DamageEvent")]
public class DamageEventController : ApiController
{
#region API methods
[HttpGet]
[Route("GetDamageEvent/{damageEventId}")]
public async Task<IHttpActionResult> GetDamageEvent(int damageEventId = 0)
{
//some logic
}
[HttpGet]
[Route("GetDamageEvent2/{ddd}")]
public async Task<IHttpActionResult> GetDamageEvent2(int ddd = 0)
{
//some logic
}
#endregion
}
}
After I make the changes above the I tryed to fire the both actions and it worked.
But the problem now is when I try to call another actions in another controllers, For example:
http://localhost/playground/api/Contracts/1
I get 404 error.
So I guess the error occures because of the new route template.
So my question how can I fix the error above and to take the new route template into consideration only when the URI try to access to DamageEventController?
Upvotes: 1
Views: 942
Reputation: 247123
You are mixing attribute routing and convention based routing.
Nothing matches your RoutePrefix
because there are no actions in the controller that has both a {actionType}
and {ddd}
templates.
But your stated URL...
api/DamageEvent/GetDamageEvent2/?ddd=22
...matches the DefaultApi
convention based route for GetDamageEvent
in the route table because it does not have a [RouteAttribute]
and it defaults back the convention where...
api/{controller=DamageEvent}/{id=GetDamageEvent2/?ddd=22}
Take a look at Routing in ASP.NET Web API to understand the convention based routing.
and also Attribute Routing in ASP.NET Web API 2
Each entry in the routing table contains a route template. The default route template for Web API is "api/{controller}/{id}". In this template, "api" is a literal path segment, and {controller} and {id} are placeholder variables.
When the Web API framework receives an HTTP request, it tries to match the URI against one of the route templates in the routing table. If no route matches, the client receives a 404 error. For example, the following URIs match the default route:
/api/DamageEvent
/api/DamageEvent/1
/api/DamageEvent/GetDamageEvent2/?ddd=22
Once a matching route is found, Web API selects the controller and the action:
- To find the controller, Web API adds "Controller" to the value of the {controller} variable.
- To find the action, Web API looks at the HTTP method, and then looks for an action whose name begins with that HTTP method name. For example, with a GET request, Web API looks for an action that starts with "Get...", such as "GetDamageEvent". This convention applies only to GET, POST, PUT, and DELETE methods. You can enable other HTTP methods by using attributes on your controller. We’ll see an example of that later.
- Other placeholder variables in the route template, such as {id}, are mapped to action parameters.
To get your stated route to work you need to update your route templates. Either the attribute route or add a new convention route to the route table
Upvotes: 1