Can't hit my end point with 2 post methods - asp.net-core

I'm really struggling with trying to hit a single end point in my ASP.NET Core Web API app
The relevant parts of the Controller are
[Route("api/[controller]")]
[ApiController]
public class PlanController : BaseApi
{
[HttpPost]
[Route("api/{controller}/Clear/")]
public async Task<ActionResult> Clear() //always returns 404
{ //some code in here
}
[HttpPost]
public async Task<ActionResult> Post([FromBody] PlanPoco model) //works as expected
{//more code
}
and the relevant part of my Startup.cs file
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
name: "api",
pattern: "{api}/{controller}/{id?}");
endpoints.MapControllers();
endpoints.MapRazorPages();
});
In postman, I would expect to type in https://localhost:12345/api/plan/clear/ and for this to match the end point. It does not. It always returns a 404
Can anyone give me some advice here please?

Based on your code, you apply attribute routing [Route("api/[controller]")] on your controller and [Route("api/{controller}/Clear/")] on clear action, to make request to clear action method, you should use below URL.
https://localhost:port/api/plan/api/plan/clear
I would expect to type in https://localhost:12345/api/plan/clear/ and for this to match the end point.
To achieve your requirement, you can try to apply [HttpPost("Clear")] to your Clear action method.
[Route("api/[controller]")]
[ApiController]
public class PlanController : ControllerBase
{
[HttpPost("Clear")]
public async Task<ActionResult> Clear()
{ //some code in here
return Ok("Clear Action");
}
[HttpPost]
public async Task<ActionResult> Post([FromBody] PlanPoco model) //works as expected
{//more code
return Ok("Post Action");
}
}
Or modify the code like below.
[HttpPost]
[Route("Clear")]
public async Task<ActionResult> Clear() //always returns 404
{
Test Result

Could you try like and make same request ;
[Route("api/[controller]/[action]")]
[ApiController]
public class PlanController : BaseApi
{
[HttpPost]
public async Task<ActionResult> Clear() //always returns 404
{ //some code in here
}
[HttpPost]
public async Task<ActionResult> Post([FromBody] PlanPoco model) //works as expected
{//more code
}

Related

Asp.Net Core Http failure response for http://localhost:5000/company/getCompanyById/3: 404 Not Found

I'm new to C# and Asp.Net and I m getting a 404 error on getting or deleting a company by Id .The Api for getting all Companies works fine.
API for allCompanies : http://localhost:5000/company/getcompaniesTest(which works)
for GetById: http://localhost:5000/company/getCompanyById/3 (not working)
Here is my Controller:
[Authorize(AuthenticationSchemes = "Bearer")]
[ApiController]
[Route("company")]
public class CompanyController : ControllerBase
{
private readonly IMediator _mediator;
public CompanyController(IMediator mediator)
{
this._mediator = mediator;
}
[HttpGet]
[Route("getcompanies")]
public async Task<IActionResult> GetCompanies()
=> new JsonResult(await _mediator.Send(new GetCompanies.Query()));
[HttpGet("{id}")]
[Route("getCompanyById")]
public async Task<IActionResult> GetCompanyById([FromQuery] GetCompanyById.Query query)
=> new JsonResult(await _mediator.Send(query));
[HttpDelete("{id}")]
[Route("deleteCompany")]
public async Task<IActionResult> DeleteCompanyTest([FromQuery] DeleteCompany.Command command)
=> new JsonResult(await _mediator.Send(command));
Or you use the route in protocol decorator [Http(your route)], Or in Route decorator [Route(your route)].
Not in both! Try this:
[HttpGet("getCompanyById/{id}")]
public async Task<IActionResult> GetCompanyById(int id) // your id type
=> new JsonResult(await _mediator.Send(id));
But this is bad practice.
The most suitable would be just host/company/id
by the get 1 company.

ASP.NET Core custom route not working with web api 2.1

I'm new to ASP.NET Core Web API and trying to implement a custom route.
Here is my controller:
using ...
namespace FoodDeliveryServer.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class MenusController : ControllerBase
{
private readonly FoodDeliveryContext _context;
public MenusController(FoodDeliveryContext context)
{
_context = context;
}
// GET: api/Menus
[HttpGet]
public IEnumerable<Menu> GetMenu_1()
{
return _context.Menu;
}
// rest of the methods
// POST: api/Menus
[HttpPost]
public async Task<IActionResult> PostMenu([FromBody] Menu menu)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_context.Menu.Add(menu);
await _context.SaveChangesAsync();
return CreatedAtAction("GetMenu", new { id = menu.Id }, menu);
}
// POST: api/Menus/filter
[HttpPost("filter", Name = "Filtermenu")]
public async Task<IActionResult> FilterMenu([FromBody] bool isActive)
{
return Ok(_context.Menu.Where(m => m.IsActive == isActive));
}
private bool MenuExists(long id)
{
return _context.Menu.Any(e => e.Id == id);
}
}
}
Now, I'm trying to hit the filter route from POSTMAN and getting 404. Other standard routes are working fine.
POST
http://localhost:5000/api/Menus/filter
Body -> raw -> JSON
{
"isActive": true
}
Headers -> Accept -> application/json
Headers -> Content-Type -> application/json
What am I doing wrong here?
I looked at this link also but still having problems:
ASP.Net Core Web API custom route not working
You can use the [Route("")] decorator on your actions too. Otherwise it will create routes upon what you defined in StartUp.Configure.
// POST: api/Menus/filter
[Route("filter")]
[HttpPost("filter", Name = "Filtermenu")]
public async Task<IActionResult> FilterMenu([FromBody] bool isActive)
{
return Ok(_context.Menu.Where(m => m.IsActive == isActive));
}
Should work for you.
The '/api/Menus/' part will be inherited from your [Route("api/[controller]")] definition on controller level
I resolved the issue with the help of #Marius. Here is what I did:
// POST: api/Menus/filter
[HttpPost]
[Route("filter", Name = "Filtermenu")]
public async Task<IActionResult> FilterMenu([FromBody] Menu menu)
{
return Ok(_context.Menu.Where(m => m.IsActive == menu.IsActive));
}
Looks like, we need to provide a class to read FromBody

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";
}
}

ASP.NET core Web API routing

Route using "UseMvc" but not able to call the controller
In startup page have added service.AddMvc method & in configure section it's app.useMvc()
I am not able to route and can't figure out what the problem is
The controller code is here and have route : the action method is Get with parameter start of DateTime type
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CurrencyContext>(cfg => {
cfg.UseSqlServer(_config.GetConnectionString("BitCoinIndexConnectionString"));
});
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
app.UseNodeModules(env);
app.UseMvc(routes =>
{
routes.MapRoute(name: "default",
template: "api/{controller}/{action}/{start:DateTime}",
defaults: new {
controller = "Currency",
action = "Get",
start = DateTime.Now.AddDays(-14)});
});
}
}
[Route("api/[Controller]")]
public class CurrencyController : Controller
{
private BitCoinRepository<BitCoinIndex> _repository;
public CurrencyController(BitCoinRepository<BitCoinIndex> repository)
{
_repository = repository;
}
// GET: api/<controller>
[HttpGet("{start}",Name ="Get")]
public IActionResult Get(DateTime start)
{
// var bci = _repository.GetByDates(start).ToDictionary(t => t.Date.ToString(), t => t.Rate);
return View();
}
}
I faced the same issue and resolved it using attribute routing. This is what I did. If you are not using .Net Core 3, ignore point 1.
1st disable endpoint routing by adding this in your ConfigureServices:
services.AddMvc(options => options.EnableEndpointRouting = false);
You can now use this in Configure method
app.UseMvc();
Next, just define your routes inside the controller (bear in mind I generally prefer routing by adding routes to the routing table, but encountered unnecassary issues going this 'route', attribute routing was the easiest 'route' to take).
[Route("api/myctrl")]
[ApiController]
public class MyControllerController : ControllerBase
{
[HttpGet]
[Route("getsomething")]
public async Task<JsonResult> DoStuff()
{
}
}
Access this by either using #Url.Action("DoStuff", "MyController"); or /api/myctrl/getsomething

Resolve routes by named parameters

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