I am new to c# and web api. I have a WebAPI controller with a Get method as follows:
public class peopleController : ApiController
{
[HttpGet]
public IHttpActionResult getAllPeople(string Name, string Age)
{
//Return something
}
}
My WebApiConfig is like this:
config.Routes.MapHttpRoute(
name: "getAllPeopleApi",
routeTemplate: "people",
defaults: new { controller = "people", action = "getAllPeople" }
);
If I invoke my url like this : http://localhost:xxx/people?Name=&Age=. It working fine.
But when I invoke like all these:
http://localhost:xxx/people,http://localhost:xxx/people?Name=,http://localhost:xxx/people?Age=
I got this error message:
{"Message":"No HTTP resource was found that matches the request URI 'http://localhost:xxxx/......'.","MessageDetail":"No action was found on the controller 'people' that matches the request."}
I try to set my routeTemplate: "people/{Name}/{Age}". Now when I run this web api Error 404.0 Not Found
routeTemplate: "people/{Name}/{Age}"
This part is not a QueryString, this is a dynamic path.
That means that your path becomes Domain/people/SomeName/SomeAge?QueryString=Whatever
Managed to solve this by explicitly set parameter Name and Age to Null.
public class peopleController : ApiController
{
[HttpGet]
public IHttpActionResult getAllPeople(string Name = null, string Age=null)
{
//Return something
}
}
This will made the parameters as an optional parameters. Now you can invoke the controller with or without Query string parameter.
I'm facing the below error while ruing my asp.net website project.
Error:
No type was found that matches the controller named 'XXXX'.
Route Config:
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
// AuthConfig.RegisterOpenAuth();
RouteConfig.RegisterRoutes(RouteTable.Routes);
System.Web.Http.GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = System.Web.Http.RouteParameter.Optional });
}
WebApi Controller:
public class SampleWebController : ApiController
{
public object SampleAction(Dictionary<string, string> jsonResult)
{
}
}
URL: ServiceUrl="../api/SampleWeb"
Please any one provide an idea to over come this error.
Also let me know if i'm doing any think wrong here.
Thanks in advance.
If you have multiple POST actions in the same controller you should make the Route Config like this:
System.Web.Http.GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{action}/{id}",
defaults: new { id = System.Web.Http.RouteParameter.Optional });
Then in your controller you can have multiple GET and POST methods
public class TestController : ApiController
{
[ActionName("PostMe")]
public object PostMe()
{
}
[ActionName("PostMeTwo")]
public object PostMeTwo()
{
}
[HttpGet]
public object TestGet()
{
}
}
Then you can generate a POST request to the action either using Ajax or PostMan like this:
localhost:XXXX/Test/PostMe
Where Test is name of controller and PostMe Name of action - Both Required
localhost:XXXX/Test/PostMeTwo[POST]
localhost:XXXX/Test/TestGet [GET]
You have 2 options.
First option, add an action name to your controller
public class SampleWebController : ApiController
{
[ActionName("SampleAction")]
public object SampleAction(Dictionary<string, string> jsonResult)
{
}
}
And you would call it like "../api/SampleWeb/SampleAction"
This way you don't need to change your route config
Second option, change your route config to
routeTemplate: "api/{controller}/{id}",
and your method to
public class SampleWebController : ApiController
{
[HttpGet]
public object GetSampleAction(Dictionary<string, string> jsonResult)
{
}
}
You can then call '../api/SampleWeb' if you are making a get request.
NOTE: If you are going to have multiple gets, posts, puts, etc in the same controller, go with the first option. If you only plan on a single get, post, put, etc for each controller then option 2 is much cleaner.
EDIT: To test option 1, change your method to
public class SampleWebController : ApiController
{
[ActionName("SampleAction")]
public object SampleAction(int id)
{
return id;
}
}
And call you api like '.../api/SampleWeb/SampleAction/10'. If this works it means the data you are passing to SampleAction can't be converted to Dictionary and thats your issue, not webapi or your routing. Make sure your route config is still
routeTemplate: "api/{controller}/{action}/{id}",
I'm developing an ASP.NET MVC 4 Web Api with C# and .NET Framework 4.0.
I'm having problems with this controller:
public class ASManagementController : ApiController
{
private readonly IExceptionLogHelper m_ExceptionLoggerHelper;
public ASManagementController(IExceptionLogHelper exceptionLoggerHelper)
{
m_ExceptionLoggerHelper = exceptionLoggerHelper;
}
[HttpGet]
public HttpResponseMessage IsConnected()
{
[ ... ]
}
[HttpPut]
public HttpResponseMessage DoConnect()
{
[ ... ]
}
[HttpPut]
public HttpResponseMessage DoReset()
{
[ ... ]
}
}
This is my WebApiConfig class:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// More routes...
config.Routes.MapHttpRoute(
name: "ASActionApi",
routeTemplate: "api/asManagement/{action}",
defaults: new { controller = "ASManagement" });
}
}
When I do https://localhost:44300/api/asManagement/DoConnect I get the following error:
Multiple actions were found that match the request:
"ExceptionMessage":
"System.Net.Http.HttpResponseMessage DoConnect() in type MyPtoject.Web.Api.Controllers.ASManagementController
System.Net.Http.HttpResponseMessage DoReset() in type MyPtoject.Web.Api.Controllers.ASManagementController",
"ExceptionType":"System.InvalidOperationException"
How can I fix this error?
If I remove doConnect method on ASManagementController it works. Do you know why?
A not very clean solution is to move ASActionApi defintion before DefaultApi on WebApiConfig class.
Try putting the ASActionApi before the DefaultApi.
Incoming URLs are compared to route patters in the order the patters appear in the route dictionary (that is what we added the route maps to in our RouteConfig.cs file). The first route which successfully matches a controller, action, and action parameters to either the parameters in the URL or the defaults defined as part of the route map will call into the specified controller and action.
I am using the default routing setup in WebApiConfig (MVC 4) but for some reason I am getting unexpected results.
If I call /api/devices/get/ it hits the Get function but the Id is "get" rather than 1. If I call /api/devices/get/1 I get a 404. I also want to be able to support multiple parameters i.e.
public Device[] Get(int? page, int? pageSize) // for multiple devices
The route
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
}
And my API:
public class DevicesController : ApiController
{
EClient client = new EClient();
// GET api/devices/5
public Device Get(string id)
{
return client.GetDeviceBySerial(id);
}
}
id in the controller parameter should be integer:
public Device Get(int id)
{
return client.GetDeviceBySerial(id);
}
if you need to pass in string, or other prams, just use quesry string:
public Device Get(int id, string pageSize)
{
return client.GetDeviceBySerial(id);
}
the above can be called as:
/api/devices/1
or
/api/devices/?id=1&pageSize=10
Note: you do not need to specify method name. Web API will judge that on the basis of HTTP Verb used. If its a GET request, it will use the Get method, if its a POST request, then it will use Post method ... and so on.
You can change the above behavior, but I guess you mentioned that you want to keep usign the default Routing ... so I am not covering that.
I keep getting this error when I try to have 2 "Get" methods
Multiple actions were found that match the request: webapi
I been looking around at the other similar questions about this on stack but I don't get it.
I have 2 different names and using the "HttpGet" attribute
[HttpGet]
public HttpResponseMessage Summary(MyVm vm)
{
return null;
}
[HttpGet]
public HttpResponseMessage FullDetails()
{
return null;
}
Your route map is probably something like this in WebApiConfig.cs:
routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
But in order to have multiple actions with the same http method you need to provide webapi with more information via the route like so:
routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional });
Notice that the routeTemplate now includes an action. Lots more info here: http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api
Update:
Alright, now that I think I understand what you are after here is another take at this:
Perhaps you don't need the action url parameter and should describe the contents that you are after in another way. Since you are saying that the methods are returning data from the same entity then just let the parameters do the describing for you.
For example your two methods could be turned into:
public HttpResponseMessage Get()
{
return null;
}
public HttpResponseMessage Get(MyVm vm)
{
return null;
}
What kind of data are you passing in the MyVm object? If you are able to just pass variables through the URI, I would suggest going that route. Otherwise, you'll need to send the object in the body of the request and that isn't very HTTP of you when doing a GET (it works though, just use [FromBody] infront of MyVm).
Hopefully this illustrates that you can have multiple GET methods in a single controller without using the action name or even the [HttpGet] attribute.
Update as of Web API 2.
With this API config in your WebApiConfig.cs file:
public static void Register(HttpConfiguration config)
{
//// Web API routes
config.MapHttpAttributeRoutes(); //Don't miss this
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = System.Web.Http.RouteParameter.Optional }
);
}
You can route our controller like this:
[Route("api/ControllerName/Summary")]
[HttpGet]
public HttpResponseMessage Summary(MyVm vm)
{
return null;
}
[Route("api/ControllerName/FullDetails")]
[HttpGet]
public HttpResponseMessage FullDetails()
{
return null;
}
Where ControllerName is the name of your controller (without "controller"). This will allow you to get each action with the route detailed above.
For further reading: http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
In Web API (by default) methods are chosen based on a combination of HTTP method and route values.
MyVm looks like a complex object, read by formatter from the body so you have two identical methods in terms of route data (since neither of them has any parameters from the route) - which makes it impossible for the dispatcher (IHttpActionSelector) to match the appropriate one.
You need to differ them by either querystring or route parameter to resolve ambiguity.
After a lot of searching the web and trying to find the most suitable form for routing map
if have found the following
config.Routes.MapHttpRoute("DefaultApiWithId", "Api/{controller}/{id}", new { id =RouteParameter.Optional }, new { id = #"\d+" });
config.Routes.MapHttpRoute("DefaultApiWithAction", "Api/{controller}/{action}");
These mapping applying to both action name mapping and basic http convention (GET,POST,PUT,DELETE)
This is the answer for everyone who knows everything is correct and has checked 50 times.....
Make sure you are not repeatedly looking at RouteConfig.cs.
The file you want to edit is named WebApiConfig.cs
Also, it should probably look exactly like this:
using System.Web.Http;
namespace My.Epic.Website
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
// api/Country/WithStates
config.Routes.MapHttpRoute(
name: "ControllerAndActionOnly",
routeTemplate: "api/{controller}/{action}",
defaults: new { },
constraints: new { action = #"^[a-zA-Z]+([\s][a-zA-Z]+)*$" });
config.Routes.MapHttpRoute(
name: "DefaultActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
I could have saved myself about 3 hours.
It might be possible that your webmethods are being resolved to the same url. Have a look at the following link :-
http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api
So, you might need to add your methodname to your routing table.
Without using actions the options would be:
move one of the methods to a different controller, so that they don't clash.
use just one method that takes the param, and if it's null call the other method from your code.
This solution worked for me.
Please place Route2 first in WebApiConfig. Also Add HttpGet and HttpPost before each method and include controller name and method name in the url.
WebApiConfig =>
config.Routes.MapHttpRoute(
name: "MapByAction",
routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional });
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
Controller =>
public class ValuesController : ApiController
{
[HttpPost]
public string GetCustomer([FromBody] RequestModel req)
{
return "Customer";
}
[HttpPost]
public string GetCustomerList([FromBody] RequestModel req)
{
return "Customer List";
}
}
Url =>
http://localhost:7050/api/Values/GetCustomer
http://localhost:7050/api/Values/GetCustomerList
I found that that when I have two Get methods, one parameterless and one with a complex type as a parameter that I got the same error. I solved this by adding a dummy parameter of type int, named Id, as my first parameter, followed by my complex type parameter. I then added the complex type parameter to the route template. The following worked for me.
First get:
public IEnumerable<SearchItem> Get()
{
...
}
Second get:
public IEnumerable<SearchItem> Get(int id, [FromUri] List<string> layers)
{
...
}
WebApiConfig:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}/{layers}",
defaults: new { id = RouteParameter.Optional, layers RouteParameter.Optional }
);
It is possible due to using MVC controller instead of Web API controller.
Check the namespace in Web API controller it should be as following
using System.Net;
using System.Net.Http;
using System.Web.Http;
If the namespace are as following then it is give above error in web api controller method calling
using System.Web;
using System.Web.Mvc;
Please check you have two methods which has the different name and same parameters.
If so please delete any of the method and try.
I've stumbled upon this problem while trying to augment my WebAPI controllers with extra actions.
Assume you would have
public IEnumerable<string> Get()
{
return this.Repository.GetAll();
}
[HttpGet]
public void ReSeed()
{
// Your custom action here
}
There are now two methods that satisfy the request for /api/controller which triggers the problem described by TS.
I didn't want to add "dummy" parameters to my additional actions so I looked into default actions and came up with:
[ActionName("builtin")]
public IEnumerable<string> Get()
{
return this.Repository.GetAll();
}
for the first method in combination with the "dual" route binding:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { action = "builtin", id = RouteParameter.Optional },
constraints: new { id = #"\d+" });
config.Routes.MapHttpRoute(
name: "CustomActionApi",
routeTemplate: "api/{controller}/{action}");
Note that even though there is no "action" parameter in the first route template apparently you can still configure a default action allowing us to separate the routing of the "normal" WebAPI calls and the calls to the extra action.
In my Case Everything was right
1) Web Config was configured properly
2) Route prefix and Route attributes were proper
Still i was getting the error. In my Case "Route" attribute (by pressing F12) was point to System.Web.MVc but not System.Web.Http which caused the issue.
You can add [Route("api/[controller]/[action]")] to your controller class.
[Route("api/[controller]/[action]")]
[ApiController]
public class MySuperController : ControllerBase
{
...
}
I know it is an old question, but sometimes, when you use service resources like from AngularJS to connect to WebAPI, make sure you are using the correct route, other wise this error happens.
Make sure you do NOT decorate your Controller methods for the default GET|PUT|POST|DELETE actions with [HttpPost/Put/Get/Delete] attribute. I had added this attibute to my vanilla Post controller action and it caused a 404.
Hope this helps someone as it can be very frustrating and bring progress to a halt.
For example => TestController
[HttpGet]
public string TestMethod(int arg0)
{
return "";
}
[HttpGet]
public string TestMethod2(string arg0)
{
return "";
}
[HttpGet]
public string TestMethod3(int arg0,string arg1)
{
return "";
}
If you can only change WebApiConfig.cs file.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/",
defaults: null
);
Thats it :)
And Result :
Have you tried like:
[HttpGet("Summary")]
public HttpResponseMessage Summary(MyVm vm)
{
return null;
}
[HttpGet("FullDetails")]
public HttpResponseMessage FullDetails()
{
return null;
}