Resolve routes by named parameters - asp.net-core

I have ASP Core 2.2 app. I defined controller:
using Microsoft.AspNetCore.Mvc;
namespace Web.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok();
}
[HttpGet("{id}")]
public IActionResult GetById(int id)
{
return Ok();
}
}
}
When I request with url /api/users/3 everything works fine, method GetById is called. But if I try to request /api/users?id=3 method Get is called and I don't know how to fix that. Moreover I would like to create two similar method different only by parameter name. For example public IActionResult GetById(int id) and public IActionResult GetByAge(int age) so I need strict routing by named parameters if possible. I don't want to implement custom middleware to resolve routes myself I wanna try to find ASP feature for that.

The url /api/users/3 : "3" is used as part of the route value .
The url /api/users?id=3: "3" is used as a query string in the url .
Attribute routing with Http[Verb] attributes is the value of which is part of the route value
You could change the Route attribute above the controller to specify action name like below :
[Route("api/[controller]/[action]")]
[ApiController]
public class UsersController : ControllerBase
{
// Get api/users/get
[HttpGet]
public IActionResult Get()
{
return Ok();
}
//Get api/users/GetById/3
[HttpGet("{id}")]
public IActionResult GetById(int id)
{
return Ok();
}
}
Reference :https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-2.2

Related

ASP.NET Core Web API - AmbiguousMatchException: The request matched multiple endpoints

I've been looking at this, but still cannot find a solution, here goes:
To return all players, I will pass in something similar to:
http://localhost:7777/api/teams/34fe3b6f-ba23-4657-820a-6c59dd49173a/players
To return a specific player on a specific team, I will pass in somethign similar to:
http://localhost:7777/api/teams/34fe3b6f-ba23-4657-820a-6c59dd49173a/players/f7de7974-9cbb-4c2c-884e-29036d6c2d76
I keep getting the following error:
System.ArgumentException: 'The route parameter name 'id' appears more than one time in the route template. '
Could someone please advise how to fix this?
[Route("api/Teams/{Id}/Players}")]
[ApiController]
public class PlayersController : ControllerBase
{
[HttpGet]
public IActionResult GetAllTeamPlayers(Guid id)
{
return Ok();
}
[HttpGet]
public IActionResult GetTeamPlayer(Guid id, Guid id2)
{
return Ok();
}
}
You should define the route parameters like this:
[Route("api/Teams/{teamId}/}")]
[ApiController]
public class PlayersController : ControllerBase
{
[HttpGet("players")]
public IActionResult GetAllTeamPlayers([FromRoute] Guid teamId)
{
return Ok();
}
[HttpGet("players/{playerId}")]
public IActionResult GetTeamPlayer([FromRoute] Guid teamId, [FromRoute] Guid playerId)
{
return Ok();
}
}

Asp.net core 2.2 api routing

In asp.net core 2.2 i have test api controller class and i have 2 get methods :
[Route("api/[controller]")]
[ApiController]
public class testController : Controller
{
// GET: api/test
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/test/5
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}
....
}
How to use this route api/test?id=1 for get method by id ?
How to use this route api/test?id=1 for get method by id ?
Use Route Attribute.
Route templates applied to an action that begin with / or ~/ don't get combined with route templates applied to the controller.
[FromQuery] - Gets values from the query string.
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
//test url: /api/test?id=7
[HttpGet("/api/test")] // will ignore "api/[controller]" with "/"
public int Test([FromQuery]int id)
{
return id;
}
.....
}
Test of result in .Net Core 2.2 API

Asp.Net Core Api Default Routing

I have a very basic Asp.Net Core Api; my controller looks like this:
[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
[HttpGet("{id}")]
public IEnumerable<Resource> Test(string id)
{
// Breakpoint here
}
I would expect the following URL to invoke the method, and fire the breakpoint:
https://localhost:5012/test/test/1
However, it doesn't. In fact, the following URL does:
https://localhost:5012/test/1
I was under the impression that the format for the URL was as follows (from startup):
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
So, unless that action is Index:
https://localhost:5012/controller/action/id
But it appears that the accepted format is:
https://localhost:5012/controller/id
My question is, why is this?
In addition to pwrigshihanomoronimo answer,
you can just change this
[HttpGet("{id}")]
public IEnumerable<Resource> Test(string id)
to
[HttpGet("[action]/{id}")]
public IEnumerable<Resource> Test(string id)
Actually it is ApiController attribute, who breaks your routing. Looks like app.UseEndpoints configures routes just for MVC. So the solution is to remove all attributes to have the following code
public class TestController : ControllerBase
{
public string Test(string id)
{
return "OK";
}
}
Or, if you want to keep ApiController attribute, you would need to adjust Route value as well. You can remove app.UseEndpoints, if you don't use MVC in your project
[ApiController]
[Route("[controller]/[action]")]
public class TestController : ControllerBase
{
[HttpGet("{id}")]
public string Test(string id)
{
return "OK";
}
}

Web Api Routing : Multiple controller types were found that match the URL

I'm getting,"Multiple controller types were found that match the URL", Error while performing postman operation for the below API Calls.
Can someone help me figuring out the attribute mapping for the same.
What I think is resolver considering the "respond" as the name of the Book.
Thanks In Advance
Code Snippet :
public class BookApiController : ApiController
{
[HttpGet]
[Route("api/v1/books/{bookName}")]
public async Task<HttpResponseMessage> Get(string bookName){
/* Code Here */
}
}
public class ProcessApiController : ApiController
{
[HttpGet]
[Route("api/v1/books/respond")]
public async Task<IHttpActionResult> Respond(string values){
/* Code Here */
}
}

How to add web API to an existing MVC Hottowel project

I have one Hottowel project created using it's template from Visual Studio. I want to add the Web API feature in that project. I have created a Web Api controller to the controller folder and tries to access like "http://localhost:53397/api/Values" But I get an error saying The resource cannot be found error.
My controller code looks like below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace MvcApplication8.Controllers
{
public class ValuesController : ApiController
{
// GET api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/<controller>/5
public string Get(int id)
{
return "value";
}
// POST api/<controller>
public void Post([FromBody]string value)
{
}
// PUT api/<controller>/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/<controller>/5
public void Delete(int id)
{
}
}
}
I have the cs file in APP_start folder called BreezeWebApiConfig.cs which contains the logic to map the route like below.
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "BreezeApi",
routeTemplate: "api/{controller}/{action}"
);
Let me know If I am missing any configuration setting for Web APi.
Try to decorate your ApiController like bellow :
[BreezeController]
public class NorthwindIBModelController : System.Web.Http.ApiController {
readonly EFContextProvider<NorthwindIBContext> ContextProvider =
new EFContextProvider<NorthwindIBContext>();
[HttpGet]
public String Metadata() {
return ContextProvider.Metadata();
}
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle) {
return ContextProvider.SaveChanges(saveBundle);
}
[HttpGet]
public IQueryable<Customer> Customers() {
return ContextProvider.Context.Customers;
}
For more information have a look to breeze documentation here.
Its seems like you are making a wrong Url Request. Look at your breeze route configuration for WebApi. You need to Pass like that http://localhost:53397/api/Values/Get as breeze is using Controller action based routing.
Hope this will help.