ASP.Net Web API custom route not working - asp.net-web-api

I have the following function in a PersonController class
[HttpGet]
[ActionName("GetBloggersNotFollowed")]
public IQueryable<object> GetBloggersNotFollowed(int companyId)
{
return Uow.People.GetPeople().Select(p => new { p.Email, p.FirstName, p.LastName, p.PhoneNumber, p.Type, p.UserName, p.Country, p.Id });
}
It is used to retrieve a list of people.
I call the function as so
$.ajax({
url: "/api/person/GetBloggersNotFollowed/1"
}).success(function (people) {
PersonModule.GetPeople(people);
});
And i have declared a route in my WebApiConfig.cs
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
When I try to call the route in the browser i get an error
<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://localhost:1045/api/person/GetBloggersNotFollowed/1'.
</Message>
<MessageDetail>
No action was found on the controller 'Person' that matches the request.
</MessageDetail>
</Error>
I don't know here I went wrong. Can anyone see the problem?

The name of the parameter is important to the route matching.
You have named the parameter id in the route yet the method has it as companyId.
Either change {id} in the route to {companyId} or change companyId parameter to id.

Replace your your route to this one:
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{companyId}",
defaults: new { id = RouteParameter.Optional }
);
This answer complements Mark Jones' answer.

Related

Easy Route Configuration

How do you use Web Api 2 use a route like this : " testdomain.de/Az809Aj " . When someone calls this URL , is a method to be called , in which I can process id behind the slash . How do I configure the route for it?
Found the answer:
config.Routes.MapHttpRoute(
name: "API Default2",
routeTemplate: "{id}",
defaults: new { controller = "Default", action = "Index", id = RouteParameter.Optional });

config.Routes.MapHttpRoute getting overridden Web API 2.0

Why my AccessManagement route template not visible in MVC Web API 2.
// Web API routes
//config.MapHttpAttributeRoutes();
//Just exclude the users controllers from need to provide valid token, so they could authenticate
config.Routes.MapHttpRoute(
name: "Authentication",
routeTemplate: "AccessManagement/",
defaults: new { controller = "AccessManagement" }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: null,
//Create and instance of TokenInspector setting the default inner handler
handler: new TokenInspector() {
InnerHandler = new HttpControllerDispatcher(config)
}
);
I need to protect all my routes having template api/{controller}/{action} by ensuring token is present in header and only one route is exposed without header which is AccessManagement/
As it is, your first route will only match the URL "/AccessManagement" and it won't accept anything else.
So, given the URL http://localhost:49531/AccessManagement/Authenticate and assuming your AccessManagement controller has an action named Authenticate, this route will match the URL:
config.Routes.MapHttpRoute(
name: "Authentication",
routeTemplate: "AccessManagement/{action}",
defaults: new { controller = "AccessManagement" }
);

Web API 1 and routing

I made a project using web api 2, but then found out that the server is running 2003. So I am now recreating the project using web api 1 (.net 4).
I am placing the routing in App_Start\WebApiConfig
config.Routes.MapHttpRoute(
name: "ContactApi",
routeTemplate: "api/{controller}/{email}/{firstname}/{lastname}/{source}"
);
The url I use is
http://localhost:64470/api/Contacts/GetId?email=user5#company.com&firstname=joe&lastname=user&source=wer
This worked fine in web api 2, but I get the following error
The resource cannot be found
Here are some pieces of the controller class
public class ContactsController : ApiController
public string GetId(string email, string firstname, string lastname, string source)
Any idea what I am missing?
Your route template requires that the parameters {email}, {firstName}, {lastName} and {source} be in the URI path. Replace your route with the code below
config.Routes.MapHttpRoute(
name: "ContactApi",
routeTemplate: "api/{controller}"
);
And it should reach your GetId method - the query string parameters don't need to be specified in the route.
To call the action with the url you are using you will need to have a route of:
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}"
);
Personally I wouldn't do this. I would just use the default route:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
and then call the APi using the following url:
http://localhost:64470/api/Contacts?email=user5#company.com&firstname=joe&lastname=user&source=wer

ASP.NET Web API custom message handler per route and global

I have 3 ASP.NET Web API message handlers:
Handler1
Handler2
AuthorizeHandler
Handler1 and Handler2 are global (applying to all routes) and one single handler (AuthorizeHandler) applies to one single route.
However I have some issues in implementing this:
public static void Register(HttpConfiguration config)
{
config.MessageHandlers.Add(new Handler1()); //this will apply to all routes
config.MessageHandlers.Add(new Handler2()); //this will apply to all routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "FreeAPI",
routeTemplate: "api/free/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "SecretAPI",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: null,
handler: new AuthorizeHandler() // this will apply just to this route
{
InnerHandler = new HttpControllerDispatcher(config)
}
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Basically what I try to do is create an anonymous route where anybody can call without authentication and one single route that needs authentication in order to access it.
However this implementation I did it doesn't work.
For example I want to have this endpoint: api/free/someanonymouscontroller/someanonymousaction/someanonymousid as anonymous and this endpoint api/somesecurecontroller/somesecureaction/somesecureid as secure that needs authentication.
If I use fiddler to test it, on this endpoint: api/somesecurecontroller/somesecureaction/somesecureid I cannot access it without credentials instead if I use this ednpoint: api/free/somesecurecontroller/somesecureaction/somesecureid (notice the free path) I can access a secure endpoint without the handler to trigger ...
Hmm,
I made the following changes and seams to work. I removed from template {controller} and added to defaults controller="free". Now all requests are going to the right place ...
Is this the correct way?
config.Routes.MapHttpRoute(
name: "FreeAPI",
routeTemplate: "api/free/{action}/{id}",
defaults: new { controller="free", id = RouteParameter.Optional }
);

Why is my message handler running even when it is not defined in WebAPI?

I have the following set-up in my config:
routes.MapHttpRoute("NoAuthRequiredApi", "api/auth/", new { id = RouteParameter.Optional } );
routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional }, null, new WebApiAuthenticationHandler());
If I post anything to the url on api/auth the message handler still runs and checks for an Auth-Token header. Is there any reason why this is happening? Is there something I should change in the configuration of the WebApi routes? I obviously don't want any auth token on the header when making requests to the auth controller because at that point I'm trying to retrieve the token for use on other controllers.
Your topmost route is never being matched as there is no indication of which controller is required. Add the controller name in as a default. (And remove the ID optional if this is not required).
So:
routes.MapHttpRoute(
name: "NoAuthRequiredApi",
routeTemplate: "api/auth/",
defaults: new { Controller = "Auth" }
);

Resources