I have built a controller. For some unknown reason the end point is not reached. Unfortunately I do not understand why.
[Route("api/realestates")]
[ApiController]
public class RealEstateController : CustomControllerBase<RealEstateController>
{
[HttpGet] // not reached
public async Task<IResult<List<RealEstateListDTO>>> GetAll()
{
//[...]
}
}
If i change the route from controller to api/realestate or from Get-method to [HttpGet("all")] it works. In the CustomControllerBase are no routes defined.
I used autogenerated Swagger to test the route. I have intentionally overwritten the route. The route works, if i don't start with debugger. If i uses the Debbuger, Swagger shows the route but i get the index.html-Fallback.
check your endpoint in postman or browser
and check your startup has something like this
services.AddControllersWithViews
or
services.AddControllers
and your customecontroller must inherits ControllerBase
You’re calling ‘api/realestate’
But in the attribute you’ve defined ‘api/realestates’
So try with the ‘s’ at the end
If you want the route to match the controller name (minus “Controller”). You should change your route attribute to -
[Route("api/[controller]")]
Related
I have the following controller which I wanted to use as an Web API Controller for ajax posts to retrieve data from my user table.
namespace MyProjectName.Controllers.API
{
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
private readonly myContext _context;
public UsersController(myContext context)
{
_context = context;
}
[HttpGet]
public List<string> GetInstitutionNamesById(int id)
{
// returns desired list
}
}
}
Now I'd expect the routing of this Function to be like this: /api/users/getinstitutionnamesbyid but apparently it seems to be just /api/users which I find really confusing (what if I add additional HttpGet Functions?).
Can anyone explain me what I am doing wrong? Am I using Web Api Controllers not the Intended way? Is my routing wrong?
Thanks in Advance.
[Route("api/[controller]")]
With this template, you're explicitly stating that you only care about the name of the controller. In your example, GetInstitutionNamesById is the name of the action, which isn't being considered by the template.
There are a few options for achieving what you're asking for here:
Change your [Route] template to include the action name:
[Route("api/[controller]/[action]")]
This option applies to all actions within your controller.
Change the HttpGet constraint attribute to specify the action implicitly:
[HttpGet("[action]")]
This option ensures that the name of your action method will always be used as the route
segment.
Change the HttpGet constraint attribute to specify the action explicitly:
[HttpGet("GetInstitutionNamesById")]
This option allows you to use a route segment that differs from the name of the action method itself.
In terms of whether you're using routing in the correct way here - that's somewhat opinion-based. Generally, you'll see that APIs are attempting to be RESTful, using route templates that match resources, etc. With this approach, you might have something more like the following:
/api/Users/{userId}/InstitutionNames
In this case, you might have a separate InstitutionNames controller or you might bundle it up into the Users controller. There really are many ways to do this, but I won't go into any more on that here as it's a little off-topic and opinion-based.
You just need to name it this way
[HttpGet("[action]/{id}")]
public List<string> GetInstitutionNamesById(int id)
{
// returns desired list
}
and from ajax call /api/users/GetInstitutionNamesById/1
Inside my application I appear to have an issue with my route. I cannot determine why the route would be failing. The solution contains a controller that derives from the [ApiController] to adhere to Web Api standards.
Area > > > Devices > > > Sampler (Controller)
/api/Devices/Sampler/GetSamples/1
{area:exists}/{controller}/{action}/{id?}
My notion that the third line template would correlate representing the first and second line when MapAreaRoute is utilized.
application.UseMvc(routes =>
{
routes.MapAreaRoute(
name: "Device Route",
areaName: "Devices",
template: "api/{area:exists}/{controller}/{action}/{id?}
);
}
Even if I remove api from template, specify the area, controller, and action I still receive a 404.
[ApiController]
[Area("Devices")]
[Route("api/[controller]")]
public class SamplerController : ControllerBase
{
[HttpGet("{id}")]
public JsonResult GetSamples(Guid id) => new JsonResult("...");
}
Could someone elaborate on why the area does not work? If I create a directory called Controllers, then use MapRoute with the same above code the route works as intended.
You need to define the area this controller belongs in by using an attribute per the docs.
[Area("Products")]
public class ManageController : Controller
Update:
Also you defined api/{area:exists}/{controller}/{action}/{id?} as your route and per your comment you are trying api/devices/sampler/8. So using your route as a guide your URL should be api/devices/sampler/GetSamples/8. You need to include the action name in the url since that is how its laid out in your route: api/{area:exists}/{controller}/{action}/{id?}
I am using WebAPI 2 with EF and scaffolding webapi controllers from visual studio.
Each controller is created with 4 default verbs (GET,PUT,DELETE,POST) and 5 actions. while there are two versions of GET action.
IQueryable<entity> GetEntities ()
Task<IHttpActionResult> GetEntity(GUID key) // default is int id but I changed to guid.
I am using attribute routing and route prefix for the controller. just some fancy keywords for better management of url. [RoutePrefix("api/v3/Company")]
Problem :
Ideally when a wrong parameter is sent in url, it should return error, but it is not raising error, instead it fall back to the action without parameter.while if I send a wrong GUID, it shows error.
Like if I call :
http://localhost:8080/api/v3/Company/1f7dc74f-af14-428d-aa31-147628e965b2
it shows the right result.
when I call :
http://localhost:8080/api/v3/Company/1f7dc74f-af14-428d-aa31-147628e96500 (wrong key)
it set back to GetEntity() function and shows all records
when I call:
http://localhost:8080/api/v3/Company/1 (not a GUID length parameter)
it do the same and shows all records.
I am using attribute [Route("{id:guid}")]
Really appreciate if I can get some guidance on this!
It is most likely that the route is defaulting back to the convention-based mapping.
You need to explicitly make apply the route attribute on actions to let the routing know that it is the default route got GET
[RoutePrefix("api/v3/Company")]
public class CompanyController : ApiController {
//GET api/v3/Company
[HttpGet]
[Route("")] //Default Get
public IQueryable GetEntities() { ... }
//GET api/v3/Company/1f7dc74f-af14-428d-aa31-147628e965b2
[HttpGet]
[Route("{id:guid}")] // ALSO NOTE THAT THE PARAMETER NAMES HAVE TO MATCH
public Task<IHttpActionResult> GetEntity(Guid id) { ... }
//...other code removed for brevity
}
Make sure that attribute routing is enabled in the web api config
config.MapHttpAttributeRoutes();
I'm presently working on a project that has been upgraded to Webapi2 from Webapi. Part of the conversion includes the switch to using attribute based routing.
I've appropriately setup my routes in the Global.asax (as follows)
GlobalConfiguration.Configure(config => config.MapHttpAttributeRoutes());
and removed the previous routing configuration.
I have decorated all of my API controllers with the appropriate System.Web.Http.RouteAttribute and System.Web.Http.RoutePrefixAttribute attributes.
If I inspect System.Web.Http.GlobalConfiguration.Configuration.Routes with the debugger I can see that all my expected routes are registered in the collection. Likewise the appropriate routes are available within the included generated Webapi Help Page documentation as expected.
Even though all appears to be setup properly a good number of my REST calls result in a 404 not found response from the server.
I've found some notable similarities specific to GET methods (this is all I've tested so far)
If a method accepts 0 parameters it will fail
If a route overrides the prefix it will fail
If a method takes a string parameter it is likely to succeed
return type seems to have no affect
Naming a route seems to have no affect
Ordering a route seems to have no affect
Renaming the underlying method seems to have no affect
Worth noting is that my API controllers appear in a separate area, but given that some routes do work I don't expect this to be the issue at hand.
Example of non-functional method call
[RoutePrefix("api/postman")]
public class PostmanApiController : ApiController
{
...
[HttpGet]
[Route("all", Name = "GetPostmanCollection")]
[ResponseType(typeof (PostmanCollectionGet))]
public IHttpActionResult GetPostmanCollection()
{
return Ok(...);
}
...
}
I expect this to be available via http://[application-root]/api/postman/all
Interestingly enough a call to
Url.Link("GetPostmanCollection", null)
will return the above expected url
A very similar example of method calls within the same controller where some work and some do not.
[RoutePrefix("api/machine")]
public class MachineApiController : ApiController
{
...
[HttpGet]
[Route("byowner/{owner}", Name = "GetPostmanCollection")]
public IEnumerable<string> GetByOwner([FromUri] string owner)
{
...
}
...
[HttpGet]
[Route("~/api/oses/{osType}")]
public IEnumerable<OsAndVersionGet> GetOSes([FromUri] string osType)
{
...
}
...
}
Where a call to http://[application-root]/api/machineby/ownername succeeds and http://[application-root]/api/oses/osType does not.
I've been poking at this far too long, any idea as to what the issue may be?
Check that you configure your HttpConfiguration via the MapHttpAttributeRoutes method before any ASP.NET MVC routing registration.
In accordance to Microsoft's CodePlex entry on Attribute Routing in MVC and Web API the Design section states:
In most cases, MapHttpAttributeRoutes or MapMvcAttributeRoutes will be
called first so that attribute routes are registered before the global
routes (and therefore get a chance to supersede global routes).
Requests to attribute routed controllers would also be filtered to
only those that originated from an attribute route.
Therefore, within the Global.asax (or where registering routes) it is appropriate to call:
GlobalConfiguration.Configure(c => c.MapHttpAttributeRoutes()); // http routes
RouteTable.Routes.MapRoute(...); // mvc routes
In my case it was a stupid mistake, I am posting this so people behind me making the same mistake may read this before they check everything else at quantum level.
My mistake was, my controller's name did not end with the word Controller.
Happy new year
I'm using WebApi and attribute routing.
I have a customer controller that has a method to get all the animals for that customer. This method & route work great. However, I also want a method that just returns a list of all the customers, and I can't get that one to work.
Here is my controller:
[RoutePrefix("api/customer")]
public class CustomerController : ApiController
{
[HttpGet("{customerId}/animals")]
public PagedHorse Get(int customerId)
{
Console.WriteLine("Get");
}
[HttpGet("")]
public PagedCustomer List()
{
Console.WriteLine("List");
}
}
If I change the List route to be "{customerId}/List" and ignore the parameter passed in, it works. What am I doing wrong with these routes? I'd really like to just have api/customer return a list of all customers.
It appears there was some amount of interference between the Hot Towel SPA project type and my project. I didn't start from scratch with Hot Towel, but added it to an existing project, so I believe there were some routing issues.
I deleted the HotTowel specific Configs (e.g. HotTowelRouteConfig) because everything that was done there I was already doing in my ASAX file.
After that everything worked fine.