Why does my default action method return a 404? - asp.net-core

I have the following .NET Core 2.2 API controller
public class TestController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok(1);
}
[HttpGet]
[ExactMatch("id")]
public IActionResult Get([FromRoute]int id)
{
return Ok(id);
}
}
And this is my route definition:
app.UseMvc(
routes =>
{
routes.MapRoute("default", "api/{controller}/{action=Get}/{id?}");
}
);
}
The following URLs work fine:
https://localhost:44305/api/test
https://localhost:44305/api/test/get/5
but not this one
https://localhost:44305/api/test/5 /* Notice the missing action method*/
It returns a 404 error
Could anybody help me figure out what I am missing?

Try the public class TestController inherited from Controller, not from ControllerBase and in the Route, you should specify which controller you are calling, like:
routes.MapRoute("default", "{controller=Test}/{action=Get}/{id?}");

First Replace
[ExactMatch("id")]
to
[HttpGet("id")]
Secondly replace
app.UseMvc(
routes =>
{
routes.MapRoute("default", "api/{controller}/{action=Get}/{id?}");
}
);
}
to
app.UseMvc(
routes =>
{
routes.MapRoute("default", "api/{controller}/{action}/{id?}");
}
);
}

Related

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 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 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

asp.net core maproute template with string concatenate to action

I have a HelloController
When i input URL with http://localhost/Hello/1234
How Could i link to the W1234
I try to modify maproute template like
template: {controller}/W{action}
But it didn't work
app.UseMvc(routes =>
{
routes.MapRoute(
name: "Hello",
template: "{controller}/{action}/{id?}");
});
public partial class HelloController : Controller
{
public IActionResult W1234()
{
return View();
}
}
You could try to use Attribute routing uses a set of attributes to map actions directly to route templates.
[[Route("Hello/1234")]
public IActionResult W1234()
{
return View();
}
Attribute routing can also make use of the Http[Verb] attributes such as HttpPostAttribute. All of these attributes can accept a route template.
[HttpGet("/Hello/1234")]
public IActionResult W1234()
{
return View();
}
Reference : Routing to controller actions in ASP.NET Core

Attribute routing - every method, class or as needed?

Let's say you have an API controller. Some methods of this controller use the same routes:
[HttpPost] // /api/entities
public IHttpActionResult Add(Entity entity)
{
...
}
[HttpGet] // /api/entities
public IHttpActionResult FindAll()
{
...
}
[HttpGet] // /api/entities
public IHttpActionResult Find(String name)
{
...
}
[HttpGet] // /api/entities/id
public IHttpActionResult Find(Int32 id)
{
...
}
[HttpDelete] /api/entities/id
public IHttpActionResult Remove(Int32 id)
{
...
}
Do I apply RouteAttribute to all methods or only to two methods to cover for "api/entities" and "api/entities/id"? Or is it better to apply two RouteAttribute to the class itself?
If you have default routes specified in the configuration, that is:
routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
You don't have to apply routing attributes, don't forget that requests will be mapped to the actions not only by HTTP method, but by parameter type also, so there should be no problem.
Take a look at the "Action" section of the documentation.