Attribute Routing doesn't work [closed] - c#

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm creating a rest api in visual studio express 2013.
I have 2 controllers: one for orders and one for clients.
I've already created the following:
/api/clients GET information about all clients
/api/clients/1 GET information about client with id = 1
/api/orders/10 GET information about order with id = 10
Now, I want to create this:
/api/clients/1/orders - GET information about all orders of client with id 1
I've read about attribute routing, but I can't make it work.
OrdersController.cs
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class OrdersController : ApiController
{
public Order Get(string id)
{
// ...
}
[Route("clients/{id}/orders")]
public List<Order> GetByClient(string id)
{
// ...
}
}
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Enable CORS
config.EnableCors();
//config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
RouteConfig.cs
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
Like this, all of the other requests work properly, but when I try to access /api/clients/1/orders, I get the error HTTP Error 404.0 - Not Found. The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
But as soon as I uncomment config.MapHttpAttributeRoutes();, I'm no longer able to access any of the requests - they all return this:
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
The object has not yet been initialized. Ensure that HttpConfiguration.EnsureInitialized() is called in the application's startup code after all other initialization code.
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace>
at System.Web.Http.Routing.RouteCollectionRoute.get_SubRoutes() at System.Web.Http.Routing.RouteCollectionRoute.GetRouteData(String virtualPathRoot, HttpRequestMessage request) at System.Web.Http.WebHost.Routing.HttpWebRoute.GetRouteData(HttpContextBase httpContext)
</StackTrace>
</Error>
What am I doing wrong here?

With routing attribute [Route("clients/{id}/orders")], you should access action GetByClient() not by /api/clients/1/orders url, but with /clients/1/orders. To have an original url just fix the routing:
[Route("api/clients/{id}/orders")]
public List<Order> GetByClient(string id)

Uncomment your config.MapHttpAttributeRoutes() line, then in your Global.asax file, replace this:
WebApiConfig.Register(GlobalConfiguration.Configuration);
with this:
GlobalConfiguration.Configure(WebApiConfig.Register);
You can read about it here:
Attribute Routing in ASP.NET Web API 2

Related

404 on new asp.net web api, after route config is setup

I have a controller which works perfectly fine:
[Authorize]
[Route("api/Version")]
public class VersionController : ApiController
{
However if I omit the Route attribute in other controllers it doesnt work, when I go to: url/api/User or Users, I get a 404
[Authorize]
public class UserController : ApiController
{
my webappi 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: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Services.Add(typeof(IExceptionLogger), new AiExceptionLogger());
}
}
my routeconfig
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
User Controller GetUsers
[HttpGet]
public async Task<IHttpActionResult> GetUsers()
{
You seem to be defining two different configuration classes that specify different route schemes in their methods:
In WebApiConfig.Register(...), you have routeTemplate: "api/{controller}/{action}/{id}";
In RouteConfig.RegisterRoutes(...), you specified url: "{controller}/{action}/{id}".
Please note that these routes overlap each other, so you have to be careful when employing these configurations in your application.
Regarding the VersionController and UserController, it seems that it is in fact the Route attribute that is defining your route.
In VersionController, if you specify [Route("api/Version")], you are correctly able to access /api/version. If you remove this, you may be able to access /version instead of /api/version, or are you not? (This may help understanding what configuration - WebApiConfig, RouteConfig or any - is used.
Likewise, in UserController, given that you don't specify [Route("api/User")], you may be able to access /user (without the /api prefix). Can you confirm this, please? On the other hand, if you were defining the Route attribute, then you should be able to access api/user.
I am assuming that you are already mapping your controllers to endpoints, since I understood that you are able to access api/version.
This documentation is pretty good on explaining Routing in MVC projects (in this case, for .NET Core), and it explians the multiple routes approach that perhaps you are trying to achieve with WebApiConfig and RouteConfig.

Unable to connect to ASP.NET web api when I add additional parameters

I am trying understand Web Api 2 (MVC project in Visual Studio).
The method is
[HttpPost]
public string Post(int id, string e, bool o)
///code removed
Using Postman, I can query using Post and the path http://localhost:62093/api/Demo/5. This works and returns the expected value.
Now I want to add more parameters and this is where it goes wrong!
I have updated my method to
[HttpPost]
public string Post(int id, string e, bool o)
Now when I attempt to query this using (again) Post and the path http://localhost:62093/api/Demo/5 I see
"Message": "The requested resource does not support http method 'POST'."
I then try to change the URL, so when I use Post and the new path http://localhost:62093/api/Demo/5/a/false I see an HTML file response of
The resource cannot be found
This has been mentioned before on Stackoverflow and from what I've understood is about the URL being 'incorrect'
Thinking this could be an issue with routes I updated mine to
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}/{s}/{o}",
defaults: new { id = RouteParameter.Optional, s = RouteParameter.Optional, o = RouteParameter.Optional }
);
But the same issue persists. I'm not sure what I've done wrong.
This is a routing issue. you have not configured your routes correctly.
First let us update the WebApiConfig.cs file
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
// Attribute routing.
config.MapHttpAttributeRoutes();
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Now with that configured I would suggest using Attribute routing
public class DemoController : ApiController {
[HttpPost]
[Route("api/Demo/{id:int}/{e}/{o:bool}")] //Matches POST api/Demo/5/a/false
public IHttpActionResult Post(int id, string e, bool o) {
return Ok();
}
}
I would finally suggest reading up on Attribute Routing in ASP.NET Web API 2 to get a better understanding on how to properly route to your API controllers

Catch-all route fails to find route with WebApi2 ApiController

I am creating a WebApi2 service, and one of the methods I want to implement represents an HTTP GET from an object within an internal tree structure - so the request would be along the lines of:
GET /values/path/path/to/object/in/tree
So I would want my method to receive "path/to/object/in/tree".
However, I just get a 404 when I run this, and it's interesting that I get a 404 that is different looking to the standard IIS 404. It's titled 'Server Error in '/' Application.', whereas the one for a completely invalid resource is titled 'HTTP Error 404.0 - Not Found'.
I am playing around with the default template to try and see if I can get this to work, hence the similarity.
I have this for my RouteConfig
public static void RegisterRoutes(RouteCollection routes)
{
var route = routes.MapRoute(
name: "CatchAllRoute",
url: "values/path/{*pathValue}",
defaults: new { controller = "Values", action = "GetPath" });
}
And this is my ValuesController:
[System.Web.Mvc.AuthorizeAttribute]
[RoutePrefix("values")]
public class ValuesController : ApiController
{
[Route("test/{value}")]
[HttpGet]
public string Test(string value)
{
return value;
}
[HttpGet]
public string GetPath(string pathValue)
{
return pathValue;
}
}
Interestingly, if I derive from Controller rather than ApiController it works OK, but then the normal attribute routing doesn't work.
I tried following the methodology in this post (http://www.tugberkugurlu.com/archive/asp-net-web-api-catch-all-route-parameter-binding) but I couldn't get it to work.
I'm sure I'm missing something stupidly easy, but having spent a few hours on it I thought it prudent to ask what I'm doing wrong.
Thanks
M
Web api routing is not the same as routing MVC. instead of
route.MapRoute
try
public static void Register(HttpConfiguration config) {
config.MapHttpAttributeRoutes
config.Routes.MapHttpRoute(
name: "CatchAll", routeTemplate: "values/path/{*pathvalue}",
defaults: new {id = RouteParameter.Optional });
}
The reason it works from controller is that MapRoute is the correct format for routing an MVC controller, while MapHttpRoute is designed for API controllers.

The requested resource does not support HTTP method 'GET'

My route is correctly configured, and my methods have the decorated tag. I still get "The requested resource does not support HTTP method 'GET'" message?
[System.Web.Mvc.AcceptVerbs("GET", "POST")]
[System.Web.Mvc.HttpGet]
public string Auth(string username, string password)
{
// Décoder les paramètres reçue.
string decodedUsername = username.DecodeFromBase64();
string decodedPassword = password.DecodeFromBase64();
return "value";
}
Here are my routes:
config.Routes.MapHttpRoute(
name: "AuthentificateRoute",
routeTemplate: "api/game/authentificate;{username};{password}",
defaults: new { controller = "Game",
action = "Auth",
username = RouteParameter.Optional,
password = RouteParameter.Optional },
constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { controller = "Home", id = RouteParameter.Optional }
);
Please use the attributes from the System.Web.Http namespace on your WebAPI actions:
[System.Web.Http.AcceptVerbs("GET", "POST")]
[System.Web.Http.HttpGet]
public string Auth(string username, string password)
{...}
The reason why it doesn't work is because you were using the attributes that are from the MVC namespace System.Web.Mvc. The classes in the System.Web.Http namespace are for WebAPI.
In my case, the route signature was different from the method parameter. I had id, but I was accepting documentId as parameter, that caused the problem.
[Route("Documents/{id}")] <--- caused the webapi error
[Route("Documents/{documentId}")] <-- solved
public Document Get(string documentId)
{
..
}
Resolved this issue by using http(s) when accessing the endpoint. The route I was accessing was not available over http. So I would say verify the protocols for which the route is available.
just use this attribute
[System.Web.Http.HttpGet]
not need this line of code:
[System.Web.Http.AcceptVerbs("GET", "POST")]
I was experiencing the same issue.. I already had 4 controllers going and working just fine but when I added this one it returned "The requested resource does not support HTTP method 'GET'".
I tried everything here and in a couple other relevant articles but was indifferent to the solution since, as Dan B. mentioned in response to the answer, I already had others working fine.
I walked away for a while, came back, and immediately realized that when I added the Controller it was nested under the "Controller" class and not "ApiController" class that my other Controllers were under. I'm assuming I chose the wrong scaffolding option to build the .cs file in Visual Studio. So I included the System.Web.Http namespace, changed the parent class, and everything works without the additional attributes or routing.

Web API multiple GET action with different query strings [duplicate]

This question already has answers here:
Routing based on query string parameter name
(4 answers)
Closed 7 years ago.
In my ApiController I need to handle this requests:
GET: api/User?role=theRole
GET: api/User?division=?theDivision
...
GET: api/User?other=stringValue
All these requests could be handled via a method like:
public HttpResponseMessage Get(String stringParam)
but obviously I cannot use overloading...
How can I solve this situation? Should I use a single method with optional parameters?
According to this answer: https://stackoverflow.com/a/12620238/632604 you can write your methods like this:
public class UsersController : ApiController
{
// GET api/values/5
public string GetUsersByRole(string role)
{
return "Role: " + role;
}
public string GetUsersByDivision(string division)
{
return "Division: " + division;
}
}
And Web API will route the requests just like you required:
One thing that you could consider doing would be modifying the default routes in your WebApiConfig file, you'll see how the default route is set as
routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Change this to
routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
You could then tag each web API action with the correct HTTP action such as [HttpGet]. To learn more about routing and handling multiple HTTP actions in Web API take a look at http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

Categories

Resources