ASP.NET Core WebApi : AmbiguousMatchException: The request matched multiple endpoints - asp.net-web-api

I've this controller code in a standard .NET Core WebApi project:
[ApiController]
[Route("[controller]")]
public class MessageController : ControllerBase
{
[HttpGet]
public string GetByTransactionId([FromRoute(Name = "transactionId")] string transactionId)
{
return "transactionId";
}
[HttpGet]
public string GetByNumber([FromRoute(Name = "number")] string number)
{
return "number";
}
}
And I want to access the api like:
https://localhost:44316/Message?transactionId=abc
https://localhost:44316/Message?number=foobar
When accessing the endpoint-url like: https://localhost:44316/Message?transactionId=abc, I get error like:
AmbiguousMatchException: The request matched multiple endpoints. Matches:
Server.Controllers.MessageController.GetByTransactionId (Server)
Server.Controllers.MessageController.GetByNumber (Server)
Can this be solved by using the correct with [HttpGet] or [Route] attributes?

[ApiController]
[Route("[Message]")]
public class MessageController : ControllerBase
{
[HttpGet]
[Route("transactionId")]
public string GetByTransactionId([FromRoute(Name = "transactionId")] string transactionId)
{
return "transactionId";
}
[HttpGet]
[Route("number")]
public string GetByNumber([FromRoute(Name = "number")] string number)
{
return "number";
}
}
Try with Route-attribute . this will sort out your problem

Related

How do you add a variable prefix to ASP.Net Core API route?

I have a ASP.Net Core API web application.
The controller is defined like this:
[Route("/api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
}
I want to be able to call the API with a variable path which denotes the customer. For example, I'd like to do something like this:
[Route("/[customername]/api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
// TODO: Somehow get the value of [customername]?
return new string[] { "value1", "value2" };
}
}
Is this possible?
Just use a route param:
[Route("{customername}/api/[controller]")]

How can I inject #PathVariable into a field?

Let's say I have following controller.
#RestController()
#RequestMapping("/my/{path}")
public class MyController {
public void some1(#PathVariable("path") String path) {
}
public void some2(#PathVariable("path") String path) {
}
public void some3(#PathVariable("path") String path) {
}
}
Now I want the path be injected into a field.
// I usually do this with JAX-RS
#RequestScope // I added this!
#RestController()
#RequestMapping("/my/{path}")
public class MyController {
public void some1() {
}
public void some2() {
}
public void some3() {
}
// single declaration for all methods
// I know ElementType.FIELD is not one of #PathVariable's target
// Is there any equivalent way to do this with Spring?
#PathVariable("path")
String path
}
Not compiles.
How can I do this?
request url : /a/b/c
#RequestMapping(value = "/a/{some}/c")
public void some(#PathVariable("some") String some) {
}
#PathVariable Annotation which indicates that a method parameter should be bound to a URI template variable.
Examples :
#ResponseBody
RequestMapping(value="/myapp/{id}")
public String method(#PathVariable("id") int id){
return "id="+id;
}
#ResponseBody
#RequestMapping(value="/myapp/{id:[\\d]+}/{name}")
public String method(#PathVariable("id") long id, #PathVariable("name") String name){
return "id= "+id+" and name="+name;
}
Refer more for below links :
Spring mvc #PathVariable
https://www.journaldev.com/3358/spring-requestmapping-requestparam-pathvariable-example

ASP.NET Core WebAPI 404 error

I create a Web Api in asp.net core this the content of Api:
[Route("api/[controller]")]
public class BlogController : Controller
{
public IContext _context { get; set; }
public BlogController(IContext ctx)
{
_context = ctx;
}
[HttpGet]
[Route("api/Blog/GetAllBlog")]
public List<Blog> GetAllBlog()
{
return _context.Blogs.ToList();
}
}
as i know in ASp.net Core (WebApi Template) we don't need any configuration like registration Route, which we need in Asp.net Mvc 5.3 and older.
So when i try to call the GetAllBlog by browser or Postman, by this url http://localhost:14742/api/Blog/GetAllBlog , it gets me 404 error, what is problem?
You have already included the api/[controller] route at the top of the controller class so you don't need to include it again while defining route for accessing method.
In essence, change the Route to api/Blog/GetAllBlog to GetAllBlog. Your code should look like this:
[Route("api/[controller]")]
public class BlogController : Controller
{
public IContext _context { get; set; }
public BlogController(IContext ctx)
{
_context = ctx;
}
[HttpGet]
[Route("GetAllBlog")]
public List<Blog> GetAllBlog()
{
return _context.Blogs.ToList();
}
[HttpGet]
[Route("GetOldBlogs")]
public List<Blog> GetOldBlogs()
{
return _context.Blogs.Where(x => x.CreationDate <= DateTime.Now.AddYears(-2)).ToList();
}
}
You also need to have different route names for methods.
Hope this helps.

WebApi: method to return a simple string

One of my methods need to return just a simple string of text. What should be the return type of the method? Do I still declare it in a subclass of ApiController?
I tried the following but it does not work:
public class TestController : ApiController
{
public string Announcements()
{
return "Testing abc";
}
}
By default, Web API will send the string as a JSON. However, you can manually force it to return just the text itself and accompany it with the appropriate content type:
public class TestController : ApiController
{
public HttpResponseMessage Announcements()
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StringContent("Testing abc");
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
return response;
}
}

WebAPI Routing Assistance

Learning a lot about MapRouting and have spent WAY too much time trying to get what I need done, so I'm hoping someone can help out. :)
I'm looking to do the following:
/api/Entities/1 <- Views the details entity with id of 1 (this is a string, not int)
/api/Entities/1/Action <- Calls a particular action on the entity with the id of 1.
/api/Entities <- Views the entities set.
/api/Entities/Action <- Calls the particular action on the entities set.
The problem I'm encountering is the last one. That is currently being intercepted by the first case, as the id is a string.
Any assistance would be greatly appreciated!
A very good reference is here
Without using Attribute based routing the answer is somewhat long winded as the RPC style (Action) and Rest methods do not co-exist nicely if you are matching to the same verb. As you have noticed the GET() and DOSOMETHING() are seen as duplicate method signatures on the same controller. To get around this you could try use two controllers:
So I would recommend using attribute based routing; however, it is possible with normal methods:
Using standard routing...
Set your routes like so
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "ActionDefaultApi",
routeTemplate: "api/entities/{action}/{actionId}",
defaults: new
{
//Add more as needed
action = "(|dosomething|dosomethingelse)",
actionId = RouteParameter.Optional,
controller = "EntitiesRpc"
});
Controller 1:
public class EntitiesController : ApiController
{
public string Get()
{
return "http://server/api/Entities";
}
public string Get(string id)
{
return string.Format("http://server/api/Entities/{0}", id);
}
}
Controller 2:
public class EntitiesRpcController : ApiController
{
[HttpGet]
public string DoSomething()
{
return "http://server/api/Entities/doSomething";
}
[HttpGet]
public string DoSomething(string actionId)
{
return string.Format("http://server/api/Entities/doSomething/{0}", actionId);
}
[HttpGet]
public string DoSomethingElse()
{
return "http://server/api/Entities/doSomethingelse";
}
[HttpGet]
public string DoSomethingElse(string actionId)
{
return string.Format("http://server/api/Entities/doSomethingelse/{0}", actionId);
}
}
Now assumming you used attribute based routing you could go back to one controller and use something like this:
public class EntitiesController : ApiController
{
[Get("Entities")]
public string Get()
{
return "http://server/api/Entities";
}
[Get("Entities/{id}")]
public string Get(string id)
{
return string.Format("http://server/api/Entities/{0}", id);
}
[Get("Entities/doSomething")]
public string DoSomething()
{
return "http://server/api/Entities/doSomething";
}
[Get("Entities/doSomething/{actionId}")]
public string DoSomething(string actionId)
{
return string.Format("http://server/api/Entities/doSomething/{0}", actionId);
}
[Get("Entities/doSomethingelse")]
public string DoSomethingElse()
{
return "http://server/api/Entities/doSomethingelse";
}
[Get("Entities/doSomethingelse/{actionId}")]
public string DoSomethingElse(string actionId)
{
return string.Format("http://server/api/Entities/doSomethingelse/{0}", actionId);
}
}

Resources