I am working on extending the example at: https://docs.asp.net/en/latest/tutorials/first-web-api.html
They have a ToDo apis: /api/todo and /api/todo/{id}.
I want to extend it to ToDoGroups /api/ToDoGroup.
Under ToDoGroup, I want to reach a ToDo by the follwoing:
/api/ToDoGroup/{id}/ToDo/{id}.
How can I make it point to the same controller action? For example the following action below will also have another route like [HttpGet("ToDoGroup/{ToDoGroupid}/ToDo/{ToDoid}", Name = "GetTodo")]
[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(string id)
{
var item = TodoItems.Find(id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
first change the controller's route prefix:
[Route("api/todogroup/{groupId:int}")]
public class TodoController : Controller
then change your action's route:
[HttpGet("todo/{id}", Name = "GetTodo")]
public IActionResult GetById(int groupId, string id)
edit:
to get both routes, you can do this:
[Route("api")]
public class TodoController : Controller
[HttpGet("todo/{id}", Name = "GetTodo")]//api/todo/43
public IActionResult GetById(string id)
[HttpGet("todogroup/{groupdId:int}/todo/{id}", Name = "GetGroupTodo")]//api/todogroup/100/todo/43
public IActionResult GetById(int groupId, string id)
Asp.Net Web Api has a way of negating a route prefix (the route specified on the controller), but I cant find an equivalent in Asp.Net Core.
Related
I have an issue with Delete Method in WebApi. It's not hitting from controller.
This is a Web Api Code having attribute routing and Get and Delete Method accepting same parameter.
When debugger goes to controller it does not go from DeleteAsync() to Delete Method in Web Api.
WebApi Code:
[Route("api/Products/{id}")]
public IHttpActionResult Get(int id)
{
List<ProductModel> showProductById = dbOperations.ShowProductById(id);
return Ok(showProductById);
}
[Route("api/Products/{id}")]
public IHttpActionResult Delete(int id)
{
int rowId = dbOperations.DeleteProduct(id);
return Ok(rowId);
}
Controller Code:
public ActionResult DeleteProduct(int id)
{
productApiClient.BaseAddress = new Uri(ConfigurationManager.AppSettings["BaseAddress"]);
var response = productApiClient.DeleteAsync("Products/" + id).Result;
return RedirectToAction("Index");
}
You need to mark what HTTP verb can be used to access that methods. You can do this by setting the corresponding attribute:
[HttpGet("api/Products/{id}")]
public IHttpActionResult Get(int id)
...
[HttpDelete("api/Products/{id}")]
public IHttpActionResult Delete(int id)
...
Edit: using AspNetCore Version 5.0.0
How do I implement following method?
I have two HttpGet Methods with following parameter value:-
[HttpGet("{id}")] int value for route
[HttpGet("{slug}")] string value for route
Route looks like this on controller:-
[Route("api/[controller]")
Route configuration:-
app.UseMvc(routes =>
{
routes.MapRoute(
name: "defaultRoute",
template: "{controller=Posts}/{action=GetAsync}/{id?}");
});
How to make sure that specific HttpGet Method gets triggered based on route value. In the above case only HttpGet with {id} route is working. Latter only works if former does not exist/remove. How can I direct my route to a method with specific header value.
Thanks!
Use route constraints
[Route("api/[controller]")
public class ValuesController : Controller {
//GET api/values/1
[HttpGet("{id:int}")] //int value for route
public IActionResult GetById(int id) {
//...
}
//GET api/values/something-else
[HttpGet("{slug}")] //string value for route
public IActionResult Get(string slug) {
//...
}
}
Reference Routing in ASP.NET Core
Reference Routing to controller actions in ASP.NET Core
You can configure routes using attributes in your controller and actions.
[Route("api/[controller]")]
public class HomeController : BaseController
{
[HttpGet("[action]")]
public IActionResult Index() => View();
[HttpGet("[action]")]
public IActionResult Error() => View();
[HttpGet("[action]/{name}")]
public IActionResult Detail(string name)
{
return RedirectToAction(nameof(Index));
}
}
You can see the two tokens [controller] and [action] indicate that we have to refer to the controller and action name that has been declared. In this case, “Home” is the name of the controller, and “Detail” the name of the action, therefore it the name of the route.
I develop a WebApi RESTful in ASP.NET Core 2.0.
From an action method in a controller A I want to create the URL address for an action method located in a different controller B:
[Route("api/applications/{idbcon}/bcontrollers")]
public class BController : Controller{
[HttpGet({idbcon}), Name = "ActionB"]
public IActionResult ActionB(int idbcon, [FromHeader(Name = "Accept")] string mediatype){
return OK();
}
}
[Route("api/applications/{idapp}/bcontrollers/{idbcon}/acontrollers")]
public class AController: Controller{
[HttpGet(), Name = "GetURLBController"]
public IActionResult GetURLBController()
{
var url = /* Here I would like to get the link to "ActionB" that belong to a Controller "BController" */;
return Ok(url);
}
}
Any advice ???
Use the IUrlHelper.Action overload that takes action and controller parameters:
public class AController : Controller
{
[HttpGet]
public IActionResult GetURLBController()
{
var url = Url.Action("ActionB", "BController");
return Ok(url);
}
}
IUrlHelper is something you inherit from the Controller base class, exposed as the Url property.
How to create prefixed routing for MVC CRUD operation. I am working on an application that requires admin and front-end. For the admin I want all route to point to localhost:5000/admin/....
I have different Controllers
public class RoomsController : Controller
{
// GET: Rooms
public async Task<IActionResult> Index()
{
return View(await _context.Rooms.ToListAsync());
}
//...
}
and
public class SlidersController : Controller
{
private readonly ApplicationDbContext _context;
public SlidersController(ApplicationDbContext context)
{
_context = context;
}
// GET: Sliders
public async Task<IActionResult> Index()
{
return View(await _context.Sliders.ToListAsync());
}
//...
}
Now I want the admin route to be
localhost:5000/admin/rooms
localhost:5000/admin/slider
while other routes remain
localhost:5000/
localhost:5000/about
localhost:5000/...
You can also use Attribute Routing for this. Till ASP.Net Web API we have the attribute named [RoutePrefix], but in ASP.Net Core 2 we can use [Route] attribute for the same purpose.
[Route("api/[controller]/[action]")]
public class DistrictController : ControllerBase
{
[Route("{id:int:min(1)}")] // i.e. GET /api/District/GetDetails/10
public IActionResult GetDetails(int id)
{
}
// i.e. GET /api/District/GetPage/?id=10
public IActionResult GetPage(int page)
{
}
[HttpDelete]
[Route("{id:int:min(1)}")] // i.e. Delete /api/District/Delete/10
public IActionResult Delete(int id)
{
}
[HttpGet]
[Route("~/api/States/GetAllState")] // i.e. GET /api/States/GetAllState
public IActionResult GetStates()
{
}
}
I solve the Problem by using MVC Area
docs
I have a web Api that has several methods. I have problem with routing. I have 1 method that is returning products by yearId and another method that is returning product by product id. Here are 2 routes I came up with:
/api/records/products?yearId=10
/api/records/products/15
These are my 2 methods:
[HttpGet]
[Route("getbyyearid")]
public async Task<Product> GetByYearid(int yearId)
{
.....
}
[HttpGet]
[Route("getbyid")]
public async Task<IEnumerable<Product>> GetByid(int productId)
{
......
}
what route mapping should I have so I can access my Web API with these 2 routes:
/api/records/products?yearId=10
/api/records/products/15
You could look into using Attribute Routing to customize how you want the routes to be used.
Here is an example of how you can achieve the routes you wanted:
[RoutePrefix("api/records")]
public class RecordsController: ApiController {
// GET api/records/products?yearid=10
[HttpGet]
[Route("products")]
public async Task<Product> GetByYearid(int yearId) {
.....
}
// GET api/records/products/15
[HttpGet]
[Route("products/{productId:int}")]
public async Task<IEnumerable<Product>> GetByid(int productId) {
......
}
}