Reputation: 323
I am struggling to understand why I'm getting a Error 404 error when I use [HttpGet("/add-brand")] but without [HttpGet("/add-brand")] it works fine?
Here is my Controller:
public class BrandController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpGet("/add-brand")]
public async Task<IActionResult> AddBrand()
{
return View();
}
}
It works if the path is /brand/addbrand (without [HttpGet("/add-brand")]) but I would like to use [HttpGet("/add-brand")] instead.
What am I doing wrong?
EDIT: Here is my Startup.cs Configure method:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
Upvotes: 0
Views: 1671
Reputation: 387775
The route is: localhost:5001/brand/add-brand
So you expect the action to be callable within the /brand
that’s coming from your BrandController. But that’s not how attribute routing works.
By default, ASP.NET Core uses conventional routing for controllers. The default template it uses is /{controller}/{action}
. That is why accessing /brand/addbrand
works if you don’t use attribute-based routing.
But as soon you specify the route via an attribute (either [Route(…)]
or a method-specific attribute like [HttpGet(…)]
) you are basically disabling the convention based routing. So that action’s route will only be determined by the route attributes. And since you only have the single [HttpGet("/add-brand")]
, the actual route for your action will be https://localhost:5001/add-brand
without an additional path segment for the controller.
You can put that back in if you like using [HttpGet("/{controller}/add-brand")]
. An alternative would be to add a separate [Route("{controller}")]
on the controller which will then cause all action routes to be concatenated to this. Note that this will disable conventional routing for all routes though, requiring you to specify it for every action.
Upvotes: 2
Reputation: 16
When you try /brand/addbrand (without [HttpGet("/add-brand")]):
MVC used routing template "{controller}/{action} It matches brand with BrandController and addbrand with your action name
I'm curious why '/' is needed in [HttpGet("/add-brand")]. If you try [HttpGet("add-brand")] it should work fine.
Upvotes: 0
Reputation: 1430
Camilo is correct, you don't need the leading / in the route string, the /brand/ is implied by the controller.
public class BrandController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpGet("add-brand")]
public async Task<IActionResult> AddBrand()
{
return View();
}
}
Upvotes: 0