I have the following routes mapped in my WebApiConfig:
config.Routes.MapHttpRoute(name: "WithActionApi", routeTemplate: "api/{controller}/{action}/{id}");
config.Routes.MapHttpRoute(name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { action = "DefaultAction", id = RouteParameter.Optional });
An in my controller I have:
[HttpGet]
public ProspectAddressResult Addresses(int id)
{
...
return result;
}
[ActionName("DefaultAction")]
public ProspectDetail Get(int id)
{
...
return prospect;
}
I'm finding that i'm getting the Get route mapped twice once as api/prospect/1 and api/prospect/Get/1. What am I doing wrong as I would expect the route to only be mapped once i.e. api/prospect/1 or is that not possible (or relevant)?
Why not just install web api 2 through nuget. Then you can use the Route and RoutePrefix properties on your actions/controllers to specify your routes.
You should then never get duplicate mapping
Here's an example of how your api controller would be set up:
[RoutePrefix("api/prospect")]
public class ProspectController: ApiController
{
[Route("{id}")]
public ProspectDetail Get(int id)
{
...
return prospect;
}
}
Your route for that would then be api/prospect/1
Related
Added a second controller in my WebAPI project and it is nor working completely but the first controller is working as expected
The default URI works for the first controller to return all records:
http://localhost:59654/api/TidalBatch
The second controller does not work and returns the error in question:
http://localhost:59654/api/TidalBatchConsolidated
However, if I pass in {id} for it, it does work for when I use the id (example shown):
http://localhost:59654/api/TidalBatchConsolidated/BAM
Tried modifying the routing addresses
WebAPI config:
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "TidalBatchApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "TidalBatchConsolidatedApi",
routeTemplate: "api/TidalBatchConsolidated/{id}",
defaults: new { id = RouteParameter.Optional }
);
I have 2 controllers, TidalBatchController.cs and TidalBatchConsolidatedController.cs. Both inherit from ApiController class.
Here's an example of my second controller that is not working as expected:
public class TidalBatchConsolidatedController : ApiController
{
public TidalBatchConsolidated GetAll(string id)
{
using (BDW_ProcessingEntities_TidalBatch entities = new BDW_ProcessingEntities_TidalBatch())
{
return entities.TidalBatchConsolidateds.FirstOrDefault(e => e.CompanyAbbr == id);
}
}
}
When I navigate to the base controller in the address it should return the List results in JSON format based on which entity data model is being passed in.
First, the order you register routes is important where more generic routes need to be registered after more specific routes. Secondly you more specific route needs controller in order for it to match.
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "TidalBatchConsolidatedApi",
routeTemplate: "api/TidalBatchConsolidated/{id}",
defaults: new { controller ="TidalBatchConsolidated", id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "TidalBatchApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
The controller also needs to ensure that there is a matching action
For example
public class TidalBatchConsolidatedController: ApiController {
[HttpGet]
public IHttpActionResult Get() {
//...
}
[HttpGet]
public IHttpActionResult Get(string id) {
//...
}
}
Since you have attribute routing enabled with config.MapHttpAttributeRoutes();, you could forego convention based route and use attribute routing on the controller instead
[RoutePrefix("api/TidalBatchConsolidated")]
public class TidalBatchConsolidatedController: ApiController {
//GET api/TidalBatchConsolidated
[Route("")] //Default route
[HttpGet]
public IHttpActionResult GetAll() {
//...
}
//GET api/TidalBatchConsolidated/BAM
[Route("{id}")]
[HttpGet]
public IHttpActionResult Get(string id) {
//...
}
}
Reference Attribute Routing in ASP.NET Web API 2
Working in ASP.NET 4.6 here.
I have a controller:
public class ComputerController : ApiController
{
...
[HttpGet]
[Route("api/computer/ping")]
public IHttpActionResult Ping(int id)
{
return Ok("hello");
}
...
}
Going mostly from this answer (look at MSTdev's answer), I have this in my WebApiConfig.cs:
// So I can use [Route]?
config.MapHttpAttributeRoutes();
// handle the defaults.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
The route doesn't work. I always get
No HTTP resource was found that matches the request URI
'http://localhost:29365/api/computer/ping'.
This seems like such a simple problem, yet I remain stumped. Any help?
Your route is missing the {id} parameter.
Ex.
[Route("api/category/{categoryId}")]
public IEnumerable<Order> GetCategoryId(int categoryId) { ... }
Your controller should look like this:
public class ComputerController : ApiController
{
...
[HttpGet]
[Route("api/computer/ping/{id}")]
public IHttpActionResult Ping(int id)
{
return Ok("hello");
}
...
}
I'm currently building an API using Web API 2.2
I have the RESTful part of it working but now I need one non-RESTful controller:
public class PremisesController : ApiController
{
private PremiseService _service;
public PremisesController()
{
_service = new PremiseService();
}
[HttpGet]
public IHttpActionResult Premise(string id)
{
id = id.Replace(" ", String.Empty).ToUpper();
List<Premise> premises = _service.GetPremisesForPostcode(id);
return Ok(premises);
}
[HttpGet]
public IHttpActionResult Building(string id)
{
double premise = Convert.ToDouble(id);
Building building = _service.GetBuildingsForPremise(premise);
return Ok(building);
}
}
The routing config is as follows:
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Im getting the error that it can't distinguish between the two methods when I initiate a GET action:
Multiple actions were found that match the request
So my question is Do I need to specify the Route attribute on top of each method and if yes, why? Doesn't the second route (ActionApi) deals with that situation?
EDIT:
I just tested you're code and it works the way it is... maybe just it is unclear.
/api/Premises/Premise/8 --> will take you to your first action
/api/Premises/Building/8 --> will take you to your second action
/api/Premises/8 --> will cause error because the routing will go to the first rule api/{controller}/{id} with a GET request, then he can't distinguish which of the actions you want because they both match the first route: (api/Premises/{id})
You could also use the RoutePrefix attribute on your controller.
[RoutePrefix("api/premises")]
public class PremisesController : ApiController
That combined with the route attribute would mean you shouldn't get multiple actions with the same route
Weird stuff is going on when I try to add extension mapping features to my api. Some things work but I cant get anything to properly return JSON. These related questions haven't gotten me where I need to go:
UriPathExtensionMapping to control response format in WebAPI
UriPathExtensionMapping in MVC 4
My project has both HttpRoutes and HttpAttributeRoutes enabled. Not sure if that matters - I am just using the default WebApi project template. I've got the following routes:
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "Api UriPathExtension",
routeTemplate: "api/{controller}.{ext}",
defaults: new { }
);
config.Routes.MapHttpRoute(
name: "Api UriPathExtension ID 1",
routeTemplate: "api/{controller}.{ext}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "Api UriPathExtension ID 2",
routeTemplate: "api/{controller}/{id}.{ext}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Here's my controller:
[RoutePrefix("api/roundTypes")]
public class RoundTypesController : ApiController
{
// GET api/roundTypes
[Route("")][HttpGet]
public IQueryable<Vcijis.RoundType> GetAllRoundTypes()
When I test it:
http://localhost/api/roundTypes **works** but is XML
http://localhost/api/roundTypes/ **works** (also XML)
http://localhost/api/roundTypes.json returns **404**
http://localhost/api/roundTypes.json/ returns a **JSON formatted error**
The JSON error message I get is:
{"message":"No HTTP resource was found that matches the request URI
'http://localhost/api/roundTypes.json/'.",
"messageDetail":"No action was found on the controller 'RoundTypes'
that matches the request."}
I've also tried with an id parameter and get similar results. I can't seem to get {ext} working in HttpAttributeRoutes at all. Help?
Attributed controllers/actions cannot be reached from routes matched to conventional ones. So you would need to use attribute routing to specify the {ext} in your route templates.
One example:
[RoutePrefix("api/customers")]
public class CustomersController : ApiController
{
[Route("~/api/customers.{ext}")]
[Route]
public string Get()
{
return "Get All Customers";
}
[Route("{id}.{ext}")]
[Route("{id}")]
public string Get(int id)
{
return "Get Single Customer";
}
[Route]
public string Post(Customer customer)
{
return "Created Customer";
}
[Route("{id}")]
public string Put(int id, Customer customer)
{
return "Updated Customer";
}
[Route("{id}")]
public string Delete(int id)
{
return "Deleted Customer";
}
}
I want to setup routing for my WEBAPI to have few methods with paramater and few without parameters. I want to use my function names in the controller in the actual urls to be used for actions. To explain it more, here is my routing mapping:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
Here are the two functions I add:
[HttpGet]
public List<Category> FunctionWithParam(long param)
{
//return something
}
[HttpGet]
public List<Category> FunctionWithoutParam()
{
//return something
}
When I hit:
root/api/controller name/FunctionWithoutParam
it does call the appropriate function. But I cannot call FunctionWithParam. I tried
root/api/controller name/FunctionWithParam/10
But this does not seem to work. I put a breakpoint and the function with parmater is just not called. What am I doing wrong, How can I get this to work?
Change your function parameter name to match the route:
[HttpGet]
public List<Category> FunctionWithParam(long id)
{
//return something
}