public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
in global.asax.cs i do:
WebApiConfig.Register(System.Web.Http.GlobalConfiguration.Configuration);
Break point confirms that the route is being registered.
In the App_Data folder i place a folder WebApi and put in a BlogPosts.cs with the following content:
public class BlogPosts : ApiController
{
public string Get()
{
return "Hello World";
}
}
What more do I have to do to get the website to use the WebAPI ?
http://localhost:49396/api/BlogPosts gives me:
<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://localhost:49396/api/BlogPosts'.
</Message>
<MessageDetail>
No type was found that matches the controller named 'BlogPosts'.
</MessageDetail>
</Error>
Therefore the WebAPI have been registed correct but it just dont find the ApiController in App_Data folder. I properly am missing something. (Its not a MVC4 project, but a website that i try to add a api to).
App_Data is not normally used for this type of scenario. It could very well be that you BlogPosts.cs file is not set to Compile but something like Content. So, in solution explorer click on BlogPosts.cs, go to properties and change Build Action settings to Compile.
Another problem is that your BlogPosts is missing Controller suffix. Rename your class to BlogPostsController.
It would probably be better if you create a special folder where you would keep your Web API controllers, like ApiControllers.
Related
I'm having an issue with getting urls to resolve to my controllers properly by getting the id from the url rather than a querystring parameter. I have a .net webapi project set up with the following folder structure.
Root
Controllers
v1
Partner
CompaniesController
PersonController
QuoteController
So as you can see the CompaniesController is in the Partner folder while the other controllers are in the v1 folder. I'm also using a RoutePrefix on my CompaniesController such as...
[EnableCors("*", "*", "*")]
[RoutePrefix("api/v1/partner/companies")]
public class CompaniesController : BaseApiController{
[Route("contact")]
[HttpPost]
public IHttpActionResult Contact(string id)
{
}
}
The issue I'm running into is that the following url returns a 404.
https://localhost:44322/api/v1/partner/companies/contact/9da093ef-57a5-4da0-bd0e-5ac97cf304e2
But the following url works fine and calls the find method
https://localhost:44322/api/v1/partner/companies/contact?id=9da093ef-57a5-4da0-bd0e-5ac97cf304e2
I thought it might be my routeconfig file, so I added this to it but still doesn't act as expected.
routes.MapRoute(
name: "Partner",
url: "api/v1/partner/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Any idea what I need to change to get this working with the id as part of the url rather than a querystring parameter?
In case anyone else runs into this, I solved this by changing the route attribute on the method. So what used to look like [Route("contact")] now is [Route("contact/{id}")].
I have a Web API 2 project hosted through an OWIN middleware. Everything worked perfectly fine and I am able to call my APIs as expected. But, my WebApiConfig defines the default route as follows:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Accordingly, I have to call my APIs using URLs similar to: /api/values/dosomething
This worked for me until I decided to document my API. For that, I first tried using the WebAPI Help Page package which did not work. Then I thought I should try Swashbuckle Swagger and see if that helps me avoid the problem altogether, but unfortunately, in both cases I got the same error:
The route template separator character '/' cannot appear
consecutively. It must be separated by either a parameter or a literal
value. Parameter name: routeTemplate
After trying a few things, it turned out that when change the route template and remove the {action} part, the error is gone. But, I cannot really do that because the whole project assumes that URLs include the action method name in them.
So anyway, I would like to know the following:
Why is this happening in the first place?
Is there a way to modify this behavior?
Thanks in advance!
I fetch the same problem. Below is my working code.
[RoutePrefix("api/User")]
public class UserController : ApiController
{
[Route("login")]
public IHttpActionResult Get()
{ }
}
when I change Route before methods from
[Route("login")]
public IHttpActionResult Get()
{ }
to
[Route("/login")]
public IHttpActionResult Get()
{ }
I got same error.
It will generate if you add an extra / before any methods of your controller(if it is not called at first time).
I am not sure about your condition. I share my situation if anyone gets help.
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?
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
I'm trying to call a webapi hosted within the same project as an umbraco website.
I'm using the default webapi routing and calling it in on application start:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
...and set up a controller in an api folder under the controllers folder:
public class ServiceContactFormController : UmbracoApiController
{
[HttpGet]
public HttpResponseMessage Get()
{
return Request.CreateResponse(HttpStatusCode.Accepted);
}
}
When I call the webapi using http://localhost:[port]/api/ServiceContactForm I receive a 404.
Are there any additional steps required specifically for Umbraco?
Regards
Never mind - for anyone else out there, Umbraco kindly take over the routing and add 'umbraco' to the route, plus you need the action due to the default get, post, etc methods not being recognised...more info here https://our.umbraco.org/forum/developers/api-questions/39075-Web-API-routing-not-working.
Working example was:
http://localhost:[port]/umbraco/api/ServiceContactForm/get
I have visual studio 2012 installed with mvc4 using .net framework 4.5. Now I want to use webapi2 with attribute writing and i want my hlep page show all the endpoints properly.
In my solution i added a new mvc4 base emtpy project and using nuget i upgraded to mvc5 and then i have installed webapi2 packages. lastly i have installed help package for webapi2.
now when i use routeprefix I cant see any content on help page and when i try to access my webapi endpoint in browsers it throws following error.
http://expressiis.com/api/v1/
<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://expressiis.com/api/v1/'.
</Message>
<MessageDetail>
No type was found that matches the controller named 'v1'.
</MessageDetail>
</Error>
namespace WebApi.Controllers
{
[RoutePrefix("api/v1")]
public class SubscribersController : ApiController
{
// GET api/<controller>
[Route("")]
[HttpGet]
public IQueryable<string> Get()
{
return new string[] { "value1", "value2" }.AsQueryable();
}
}
}
Based on your information, it looks like you are not calling the httpConfig.MapHttpAttributeRoutes() (Make sure to call this before any traditional routing registrations)
Since you haven't called MapHttpAttributeRoutes, your request seems to be matching a traditional route, for example, like api/{controller}. This will not work because routes matching traditional routes will never see controllers/actions decorated with attribute routes.
A problem I ran into was related to the ordering in Application_Start(). Note the order of Web API configuraton below:
This does NOT work
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfiguration.Configure(WebApiConfig.Register);
}
This does work
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
I had this problem too and after a long search I realized that I was using System.Web.Mvc.RouteAttribute instead of System.Web.Http.RouteAttribute
After correcting this and using config.MapHttpAttributeRoutes() everything worked fine.
This was not your case (as is apparent from your sample code), but please do remember to end the Controller class name with Controller.
Else it won't be picked up by config.MapHttpAttributeRoutes();.
This question already has a selected answer. But I had a different solution for myself and think it would be helpful to reply if the selected answer doesn't help.
For me it was a silly mistake. I had two controllers but only one was working. The solutions was that my controller class was named improperly!
My working controller-
public class FooController : ApiController { }
My non-working controller-
public class BarControllers : ApiController { }
Be sure your controller class ends in Controller. The trailing s got me!
Make sure you don't have two controllers with the same name! I was moving some controllers from one assembly I was throwing away into the website... whilst the website no longer had references to the old assembly other assemblies did which meant it was copied in to the WebSite bin folder. The route discovery process then seemed to fail silently when it came across two occurrences of the same controller!
In my case, VS create my controller with the name
TestController1
I dont know why he put this number "one" in the end of name, but remove and will work.
In my case, I was missing full custom path in attributes. I was writing only custom action name without 'api/'. So that was my mistake. My scenario was,
WebApiConfig template code:
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
my incorrect way of route
[RoutePrefix("myapps")] // wrong code
public class AppsController : BaseRestAPIController
{
[HttpPost]
[Route("getapps")]
public ResponseData GetAppList()
{
Correct way
[RoutePrefix("api/myapps")] // correct way. full path start from 'api/'
public class AppsController : BaseRestAPIController
{
[HttpPost]
[Route("getapps")]
[Route("api/myapps/getapps")] // you can use full path here, if you dont want controller level route
public ResponseData GetAppList()
{
In my case following line was creating problem, just commented it and everything start working
config.MapHttpAttributeRoutes();
Comment it in WebApiConfig.cs file