I'm new to Web API and followed some examples, but I cannot work out where the Controller Name is specified.
I have this in my global.asax:
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.MapHttpRoute(
name: "API Controller",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = System.Web.Http.RouteParameter.Optional }
);
}
I have a Controller called TestAPI.cs
and this is the contents:
namespace Testing
{
public class TestAPI : ApiController
{
// GET api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/<controller>/5
public string Get(int id)
{
string test= "Hello!";
return test
}
}
}
I've only put "return test" in there as an example for Stack Overflow as it contains a lot of code.
So if I am consuming this in jQuery, what path would I use for the controller?
Aside from the naming convention about your Web Api controller name, you also need to change the route configuration. see below:
1) Change your TestAPI controller like below:
public class TestAPIController : ApiController
2) change MapHttpRoute in your Application_Start method like below:
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "API Controller",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Note: Don't forget also change the actual file name form TestAPI.cs to TestAPIController.cs.
Rename your controller to TestApiController and remove the {action} parameter from the route.
That should just be
http://[yourserver]/[yourapp]/api/testapi
or
http://[yourserver]/api/testapi
Depending on how you set up your application
Isn't your controller name supposed to end in "Controller" even if it's a WebApi controller?
I think
public class TestAPI : ApiController
should be
public class TestAPIController : ApiController
Related
So i have setup an ASP.NET WebAPI app and whenever i try to call the API i get this message:
<Error>
<Message>
No HTTP resource was found that matches the request URI
'http://localhost:62834/api/PiDBTest'.
</Message>
<MessageDetail>
No type was found that matches the controller named 'PiDBTest'.
</MessageDetail>
</Error>
I have tried a few different urls to get to call the API but still cant get anywhere with it.
I have been using the following url to call the API
http://localhost:62834/api/PiDBTest
Can't seem to see why I'm not getting any success from the call?
Below is the code for the API controller and the RouteConfig
PiDBTest:
public class PiDBTest : ApiController
{
private pidbEntities db = new pidbEntities();
// GET: api/PiDBTest
public IQueryable<PiData> GetPiDatas()
{
return db.PiDatas;
}
}
RouteConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
With attribute routing enabled, this will work.
[RoutePrefix("api/PiDBTest")]
public class PiDBTest : ApiController
{
private pidbEntities db = new pidbEntities();
// GET: api/PiDBTest
[HttpGet]
[Route("")]
public IQueryable<PiData> GetPiDatas()
{
return db.PiDatas;
}
}
Please try change your API class as follows,
public class PiDBTestController : ApiController
{
private pidbEntities db = new pidbEntities();
// GET: api/PiDBTest
[HttpGet]
[Route("")]
public IQueryable<PiData> GetPiDatas()
{
return db.PiDatas;
}
}
Could you add [HttpGet] on top of your Method
public IQueryable GetPiDatas()
In my case, the controller class name didn't include the word "Controller" in it. I changed the class name from "Vendor" to "VendorController" then it started working.
I have an asp.net mvc controller named product.
public class ProductController : ApiController
{
[HttpGet]
public IHttpActionResult Get()
{
return Ok("product");
}
}
And my route is like this.
config.Routes.MapHttpRoute("DefaultRoute",
"api/{controller}/{id}",
new { id = RouteParameter.Optional });
I can access the product Get method like this url: localhost:2541/api/product
And I need some estra get methots.
public class ProductController : ApiController
{
[HttpGet]
public IHttpActionResult Get()
{
return Ok("product");
}
[HttpGet]
public IHttpActionResult Hello()
{
return Ok("Hello from product");
}
}
And I set new route.
config.Routes.MapHttpRoute("ActionsRoute",
"api/{controller}/{action}/{id}",
new { id = RouteParameter.Optional });
But I can not access to localhost:2541/api/product
Error:
Multiple actions were found that match the request: Get
That is because by including {action} route parameter it is now required to include the name of the action in the request other wise it will not know which action to select. like
localhost:2541/api/product/Get
If the root is still desired then include default when mapping route.
config.Routes.MapHttpRoute("ActionsRoute",
"api/{controller}/{action}/{id}",
new { action = "Get", id = RouteParameter.Optional });
With that done, the calls below will map as followed
GET localhost:2541/api/product --> ProductController.Get
GET localhost:2541/api/product/Get --> ProductController.Get
GET localhost:2541/api/product/Hello --> ProductController.Hello
I'm trying to get this method to work:
public class DocumentenController : ApiController
{
[HttpPost]
[Route("DeleteDocument/{name}/{planId}")]
public IHttpActionResult DeleteDocument(string name, int planId)
{
_documentenProvider.DeleteDocument(planId, name);
return Ok();
}
}
This is the WebApiConfig :
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: UrlPrefix + "/{controller}/{action}/{id}",
defaults: new {id = RouteParameter.Optional}
);
But I get a 404 when I call it like this using a post:
http://localhost/QS-documenten/api/documenten/deletedocument/testing/10600349
What is the proper way do solve this?
The URL in example does not match attribute route on controller.
To get
http://localhost/QS-documenten/api/documenten/deletedocument/testing/10600349
to work, assuming that http://localhost/QS-documenten is the host and root folder, and that api/documenten is the api prefix then add a route prefix to the controller...
[RoutePrefix("api/Documenten")]
public class DocumentenController : ApiController {
//eg POST api/documenten/deletedocument/testing/10600349
[HttpPost]
[Route("DeleteDocument/{name}/{planId}")]
public IHttpActionResult DeleteDocument(string name, int planId) {
_documentenProvider.DeleteDocument(planId, name);
return Ok();
}
}
Source: Attribute Routing in ASP.NET Web API 2 : Route Prefixes
You must send your request as follows:
http://localhost/QS-documenten/deletedocument/testing/10600349
When you use route attribute, the custom route override default api routing configuration.
I have a problem that I want to call a MVC Api method with a custom name.
I changed the WebApi.config as described here
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id="test" }
);
and wrote a class
public class MissingCardBoxModelController : ApiController
{
// GET api/missingcardboxmodel
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/missingcardboxmodel/5
public string Get(string id)
{
return id;
}
public string GetTrackingNumber(string parcelLabelNumber)
{
string trackingNumber = "some number";
return trackingNumber;
}
// POST api/missingcardboxmodel
public void Post([FromBody]string value)
{
}
// PUT api/missingcardboxmodel/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/missingcardboxmodel/5
public void Delete(int id)
{
}
}
But I can't call the method via http://localhost:58528/api/MissingCardBoxModel/GetTrackingNumber/123456
I Get the message
No action was found on the controller 'MissingCardBoxModel' that
matches the request.
Why can't I call the method ?
If your routes are configured to be these (default in the MVC solution template):
url: "{controller}/{action}/{id}"
You should change parcelLabelNumber to id.
You can read more about routes here.
By Default Web API allows Restful conventions that means it will auto map GET, PUT, POST, DELETE etc action names. if you look inside your WebApiConfig in routes it only allows the route below
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
which means it only allows
.../api/yourcontrollername/a parameter that will map to id
.
you basically have 2 options, one to use attribute routing. or you can add a route to your custom method eg:
config.Routes.MapHttpRoute(
name: "custom",
routeTemplate: "api/{controller}/{action}/{parcelLabelNumber}",
defaults: new { parcelLabelNumber = "" }
);
please also notice the parameter name here "parcelLabelNumber", you have to name your parameter same here as in your action. You should be able to reach this action at - http://localhost:23691/api/MissingCardBoxModel/GetTrackingNumber/1245
Also please have a look at Routing in general
I have this class:
[RoutePrefix("api/v2/Foo")]
public class SomeController : BaseController
{
[Route("")]
[HttpGet]
public async Task<HttpResponseMessage> Get(SomeEnum? param)
{
//...
}
}
I want to call it via:
api/v2/Foo?param=Bar
but it doesn't work.
If I change the routing attribute thusly to include something in the RouteAttribute:
[Route("SomeRoute")]
[HttpGet]
public async Task<HttpResponseMessage> Get(SomeEnum? param)
{
//...
}
...then I can call
api/v2/Foo/SomeRoute?param=Bar
, but that isn't what I want.
How do I get the first circumstance to work?
EDIT:
Domas Masiulis steered me toward the answer: the above scenario DOES work, it's just that a default global routing screwed things up. I solved the issue by adding a separate default routing that matched our convention...
public static void RegisterRoutes(RouteCollection routes)
{
//ADDING THIS FIXED MY ISSUE
routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/v2/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
//SOURCE OF THE ORIGINAL PROBLEM
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Administration", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
Any special conditions? Maybe something hidden in BaseController? Any custom configurations in RouteConfig?
Your given example works for me, made a quick test:
Used code:
[RoutePrefix("api/v2/Foo")]
public class SomeController : ApiController
{
[Route("")]
[HttpGet]
public Task<int> Get(int param)
{
return Task.FromResult(2);
}
}
Calling
http://localhost:1910/api/v2/Foo?param=1 works as expected - returns 2.
1) You have to specify [FromUri] attribute for query parameter
2) If you use nullable parameter like SomeEnum? setup a default value for it
[Route("")]
[HttpGet]
public async Task<HttpResponseMessage> Get([FromUri] SomeEnum? param = null)
{
//...
}