[RoutePrefix("subscriptions")]
public class SubscriptionsController : ApiController
{
private SubscriptionsService _subscriptionsService;
public SubscriptionsController()
{
_subscriptionsService = new SubscriptionsService();
}
[Route("{email}")]
[HttpGet]
public IHttpActionResult Get(string email)
{
but when I try
http://localhost:51561/api/subscriptions/myEmail
No HTTP resource was found that matches the request URI
'http://localhost:51561/api/subscriptions/myEmail'.
any idea why?
I also set everything in WebApiCOnfig
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 }
);
}
}
You have tried a wrong URL.
Correct URL should be,
http://localhost:51561/subscriptions/myEmail
OR
If you need API prefix, then you need to change the route prefix of the controller as below,
[RoutePrefix("API/subscriptions")]
then this URL will work,
http://localhost:51561/api/subscriptions/myEmail
Note that , here you are using two routing, default routing and attribute routing. if you need to continue with attribute routing , you can comment out the default routing.
//config.Routes.MapHttpRoute(
// name: "DefaultApi",
// routeTemplate: "api/{controller}/{id}",
// defaults: new { id = RouteParameter.Optional }
I Suppose you are creating some webApi service ? Did you register this route in global.asax.cs ? Something like this :
httpConfiguration.Routes.MapHttpRoute(
name: "MyWebApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { controller = "ControllerName", action = "ActionName", id = RouteParameter.Optional },
constraints: null
);
Related
I'm trying to make the API call
http://localhost:56578/v1/reports
to call my GetReports() method.
However I continue to get the error message in the subject.
I'm following the ms docs here via the route prefix:
https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2#route-prefixes
What am I doing wrong?
ReportV1Controller.cs
[Authorize]
[RoutePrefix("v1/reports")]
....
....
[Route("")]
public IHttpActionResult GetReports()
WebApiConfig.cs
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Change from this:
[RoutePrefix("v1/reports")]
to this:
[RoutePrefix("api/v1/reports")]
because of:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
See routeTemplate: "api/{controller}/{action}/{id}", you said prefix for all paths will be api, {controller}/{action}/{id} are placeholders
Conclusion: if you are going to use v1 prefix everywhere, put it instead of api
What you have should work provided that you have enabled attribute routing in the WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Attribute routing.
config.MapHttpAttributeRoutes(); //<-- THIS HERE
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Reference Attribute Routing in ASP.NET Web API 2: Enabling Attribute Routing
And assuming
[Authorize]
[RoutePrefix("v1/reports")]
public class ReportV1Controller : ApiController {
//GET v1/reports
[Route("")]
[HttpGet]
public IHttpActionResult GetReports() {
//...
}
}
This is my web API config:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ReaderTags",
routeTemplate: "Reader/{readerID}/Tags"
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
I want that when I call my URL /Reader/abc/Tags it should call my ReaderController's Tags action and pass abc as the string parameter.
But somehow it is using the DefaultAPI's route and trying to find abc as an action in ReaderController.
What am I missing?
The route mapping is missing defaults that would let the route table know what controller and action to invoke for routes matching the template
config.Routes.MapHttpRoute(
name: "ReaderTags",
routeTemplate: "Reader/{readerID}/Tags",
defaults: new { controller = "Reader", action = "Tags" }
);
The route template also assumes that the string parameter on the action shares the same name: i.e: readerID.
public IHttpActionResult Tags(string readerID) {
//...
}
And since config.MapHttpAttributeRoutes(); is also configured, then the same can be achieved via attribute routing instead of convention-based routing like this
//GET Reader/abc/Tags
[HttpGet]
[Route("Reader/{readerID}/Tags")]
public IHttpActionResult Tags(string readerID) {
//...
}
I am struggling to correctly design a DELETE http request in my ASP Web application.
I have the following route defined:
public const string ControllerOnly = "ApiControllerOnly";
public const string ControllerAndId = "ApiControllerAndIntegerId";
private const string ControllerAction = "ApiControllerAction";
public static void Register(HttpConfiguration config)
{
var routes = config.Routes;
// api/projects
routes.MapHttpRoute(
name: ControllerOnly,
routeTemplate: "api/{controller}"
);
//api/projects/1
routes.MapHttpRoute(
name: ControllerAndId,
routeTemplate: "api/{controller}/{id}",
defaults: null,
constraints: new { id = #"^\d+$" } // id must be all digits
);
routes.MapHttpRoute(
name: ControllerAction,
routeTemplate: "api/{controller}/{action}"
);
}
I am expecting it to hit the following action:
public HttpResponseMessage Delete(int i)
{
//content remove for brevity
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
In fiddler I try to test using the following: DELETE http://localhost:port/api/controller/1
but that method never gets hit. Instead, the following method is hit:
public HttpResponseMessage Delete()
{
//content remove for brevity
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
I have a basic understanding of routing but shouldn't that only route I defined ensured that the previous test is successful?
Note that I have no problem with GET and POST verbs
Any help appreciated
I guess you need to add the action part in your route as below :-
routes.MapHttpRoute(
name: ControllerAndId,
routeTemplate: "api/{controller}/{action}/{id}",
defaults: null,
constraints: new { id = #"^\d+$" } // id must be all digits);
Add/Register other route-path before default route. It takes always first prior one. So, in your case you need to register one more path in WebApiConfig as below.
routes.MapHttpRoute(
name: "WithActionApi",
routeTemplate: "api/{controller}/{action}/{Id}",
defaults: new { Id = RouteParameter.Optional
});
Note : You must register this route before your default route.
i.e, It should be as below.
public static void Register(HttpConfiguration config)
{
routes.MapHttpRoute(
name: "WithActionApi",
routeTemplate: "api/{controller}/{action}/{Id}",
defaults: new { Id = RouteParameter.Optional
});
routes.MapHttpRoute(
name: ControllerAndId,
routeTemplate: "api/{controller}/{id}",
defaults: null,
constraints: new { id = #"^\d+$" } // id must be all digits
);
}
I have these two routes defined:
routes.MapRoute(
name: "GetVoucherTypesForPartner",
url: "api/Partner/{partnerId}/VoucherType",
defaults: new { controller = "Partner", action = "GetVoucherTypesForPartner"}
);
routes.MapRoute(
name: "Default",
url: "api/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional}
);
In my PartnerProfile controller, I have 2 methods:
public Partner Get(string id)
{ }
public IEnumerable<string> GetVoucherTypesForPartner(string id)
{ }
If I hit the url ~/api/Partner/1234 then, as expected, the Get method is called.
However, if I hit the url ~/api/Partner/1234/VoucherType then the same Get method is called. I am expecting my GetVoucherTypesForPartner to be called instead.
I'm pretty sure something in my route setup is wrong...
You seem to have mapped standard MVC routes, not Web API routes. There's a big difference. The standard routes are used by controllers deriving from the Controller class, but if you are using the ASP.NET Web API and your controllers are deriving from the ApiController type then you should define HTTP routes.
You should do that in your ~/App_Start/WebApiConfig.cs and not inside your ~/App_Start/RouteConfig.cs.
So go ahead:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "GetVoucherTypesForPartner",
routeTemplate: "api/Partner/{partnerId}/VoucherType",
defaults: new { controller = "Partner", action = "GetVoucherTypesForPartner" }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
and then:
public class PartnerController : ApiController
{
public Partner Get(string id)
{
...
}
public IEnumerable<string> GetVoucherTypesForPartner(string partnerId)
{
...
}
}
Things to notice:
We have defined HTTP routes not standard MVC routes
The parameter that the GetVoucherTypesForPartner action takes must be called partnerId instead of id in order to respect your route definition and avoid any confusions
Here is the routing configuration in WebApiConfig.cs:
config.Routes.MapHttpRoute(
name: "DefaultApiPut",
routeTemplate: "api/{controller}",
defaults: new { httpMethod = new HttpMethodConstraint(HttpMethod.Put) }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { httpMethod = new HttpMethodConstraint(HttpMethod.Get, HttpMethod.Post, HttpMethod.Delete) }
);
Here is my controller:
public class MyController : ApiController {
[HttpPut]
public void Put()
{
//blah
}
}
Somehow when the client sents the PUT request with the URL /api/myController/12345, it still maps to the Put method in MyController, I am expecting an error like resource not found.
How to force the Put method only accept the request without a parameter?
Thanks in advance!
This works to constrain http method on routes:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "LocationApiPOST",
routeTemplate: "api/{orgname}/{fleetname}/vehicle/location",
defaults: new { controller = "location" }
constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) }
);
config.Routes.MapHttpRoute(
name: "LocationApiGET",
routeTemplate: "api/{orgname}/{fleetname}/{vehiclename}/location/{start}",
defaults: new { controller = "location", start = RouteParameter.Optional }
constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) }
);
...
}
You're putting your httpMethod constraint into defaults, but it should be in constraints.
defaults just says what the default values will be if the request doesn't include some or all of them as routing parameters (which in the case of the verb, is meaningless, since every HTTP request always has a verb as part of the protocol). constraints limit the combination of route values that will activate the route, which is what you're actually trying to do.
FYI, for this simple/standard routing, you don't need the [HttpPut] attribute in an API controller either. That's already handled by the HTTP routing which maps the verb to the controller method.