简体   繁体   中英

Controller with HttpGet(...) gives error 404

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();
            });
        }

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();
    }
}

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM