I have a web api controller that has two actions, but only one of them can receive requests.
public class ApiBase : ApiController
{
}
[RoutePrefix("api/Test")]
public class TestController : ApiBase
{
[HttpGet]
[Route("")]
public IHttpActionResult Get() {} // I only want this action to handle http://blah/api/Test but it's also handling http://blah/api/Test?id=1
[HttpGet]
[Route("{id}")]
public IHttpActionResult Get([FromUri] int id){} // http://blah/api/Test?id=1 couldn't reach here
}
I realized the problem is with base class. If TestController doesn't inherit from base class, it works as expected. What's missing from my base class?
Your attribute routing definition has a routing pattern api/Test/{id} mapped to the second Get method. So you should be accessing it like /api/test/34
When using attribute routing , the default routing with the querystrings and ? won't work. You should use the pattern defined in the attribute route definition.
/api/test/34 will work for Get([FromUri] int id){}
/api/test/ will work for Get() {}
Related
I have a fairly simple controller for my API. One method returns all devices, and another method returns information on just one. Both of them are HttpGet.
My route definition:
[Route("api/device/list/{Id}")]
[ApiController]
public class DeviceController : ControllerBase
This method is always called when I pass in an ID:
[HttpGet]
public ActionResult<poiDevices> GetDeviceList()
The PostMan URL looks like this:
https://localhost:5001/api/device/list/mycoolid
When the call above is made I want it to call this method below, defined as such with an Id parameter:
public ActionResult<DeviceDto> GetDeviceDetails(
[FromRoute] string Id)
The code above has a placeholder for an Id, so my expectation is for this method to be called, instead the generic method is called which returns all. If I take the Id out of the URL the API returns 404 not found, meaning I messed up the routing piece of this.
What am I missing here?
You should change your controller like this.
[Route("api/device")]
[ApiController]
public class DeviceController : ControllerBase
{
[HttpGet]
[Route("list")]
public ActionResult<poiDevices> GetDeviceList() {
}
[Route("list/{id}")]
public ActionResult<DeviceDto> GetDeviceDetails(
[FromRoute] string Id) {
}
}
I'm trying create an additional Get method on a web api but the return is 404 ( method not found ).
At my APIs before Core I was creating such methods like :
[HttpGet]
[Route("api/MyNewMethodName")]
public object MyNewMethodName(string parameter1)
{}
And for call :
myURL/api/MyNewMethodName?parameter1=somestring
At my controller definition I have :
[Produces("application/json")]
[Route("api/MyController")]
public class MyController : Controller
For the exactly some code I receive the 404 error.
What is wrong please ?
Your controller has a route defined. So for your action method, it will be the route prefix defined for the controller + the route pattern for the action method. That means, with your current code, it will work for the below request
yourBaseUrl/api/MyController/api/MyNewMethodName?parameter1=somestring
Here api/MyController part is from the route definition on the controller level and the api/MyNewMethodName part is from the action method level.
Fix the route prefix at controller or method level as needed. For instance if you want your action method to respond to /api/MyNewMethodName?parameter1=somestring. Just remove the Route decorator on the controller level.
[Produces("application/json")]
public class MyController : Controller
{
[HttpGet]
[Route("api/MyNewMethodName")]
public object MyNewMethodName(string parameter1)
{
return "Sample dummy response : "+parameter1;
}
}
Keep in mind that, removing the controller level routing might break routes to other action methods in that controller. If you want to keep the existing routes as it is (with the controller level route attributes), You may update your action method level route pattern to start with a /
[Produces("application/json")]
[Route("api/MyController")]
public class MyController : Controller
{
[HttpGet]
[Route("/api/MyNewMethodName")]
public object MyNewMethodName(string parameter1)
{
return "Some test"+parameter1;
}
[HttpGet]
[Route("SecondMethod")]
public object SecondMethod(string parameter1)
{
return "SecondMethod : "+parameter1;
}
}
[HttpGet]
[Route("api/[controller]/MyNewMethodName")]
public object MyNewMethodName(string parameter1)
{
}
Try declaring the above format, this worked for me.
I was wondering that if we use RoutePrefix attribute in our web api controller with a different name from controller's actual name. So would it work or not?
As far as i did
[RouterPrefix("quotation")]
public class SaleOrderController : ApiController { ... }
if we define RoutePrefix like above we can't access it via /quotation but we can access it using saleorder.
So what is RoutePrefix for or am i doing something wrong ?
To use default route use Route("")
[RoutePrefix("quotation")]
public class SaleOrderController : ApiController {
//GET quotation
[Route("")]
[HttpGet]
public IHttpActionResult GetAll() { ... }
}
Source: Attribute Routing in ASP.NET Web API 2 : Route Prefix
In order for it to work, you need to call the code below inside your WebApiConfig.Register() method:
config.MapHttpAttributeRoutes();
So your RoutePrefix works as exptected:
[RoutePrefix("quotation")]
public class SaleOrderController : ApiController
{
[Route("example")]
[HttpGet]
public IHttpActionResult Example()
{
return Ok();
}
[Route("another")]
[HttpGet]
public IHttpActionResult Another()
{
return Ok();
}
}
So your could access your apis like this:
quotation/example
quotation/another
I just have one quick question about what seems to have been a limitation with ASP.NET Web API Attribute Routing, but hoping I just suck at research. In my controller, I'm trying to do something like this:
public class OrdersController : ApiController
{
[HttpGet]
[Route("{apiRoot}/customers/{id:int}/orders")]
public IHttpActionResult GetCustomerOrders(int id) {...}
}
Where {apiRoot} is defined in either a configuration file.
This may not actually be necessary, but I'd like to know how to put a specific path in the route attribute without having to code a static path. Is the general idea here supposed to be that you only put text into the route path, except for your parameters which go in {}?
How about switching to using a RoutePrefix:
[MyRoutePrefix]
public class OrdersController : ApiController
{
[HttpGet]
[Route("customers/{id:int}/orders")]
public IHttpActionResult GetCustomerOrders(int id) {...}
}
public class MyRoutePrefixAttribute : RoutePrefixAttribute
{
public MyRoutePrefixAttribute()
{
Prefix = "the route prefix";
}
}
RoutePrefixAttribute isn't sealed like RouteAttribute so extending it should allow you do what you need. Assuming, of course, that all of the controllers in a single class using the same root path.
Note: I haven't had a chance to try this but given what I know of attribute routing, I don't see why it shouldn't work.
I have two controllers for my User model. One is a regular MVC controller which handles the views and inherits from Controller. Then I have an API controller which inherits from ApiController. Their names are UsersController and UsersApiController respectively. I wish to remove from "Api" from the API controller's URL so I can type:
www.mywebsite.com/api/Users
rather than:
www.mywebsite.com/api/UsersApi
which contains a redundant "api".
I have tried applying the attribute [Route("Users")] and [Route("api/Users")] to the entire controller but neither work and they seem to just break it. My WebApiConfig.cs has the default route config.
How can I do this?
You should be able to use Attribute routing.
[RoutePrefix("api/users")]
public class UsersApiController : ApiController
{
[Route("")]
public HttpResponseMessage Get()
{
}
}
You should be able to customize it per action methods as well
public class UsersApiController : ApiController
{
[Route("api/users")]
public HttpResponseMessage Get()
{
}
}