简体   繁体   中英

Custom route and action names in asp.net core mvc

I'm working on an Asp.Net Core 3.1 MVC project and want to change some controllers and actions name in url. Almost all of answers is related to .net core API or mvc (without .net core) but I want to do it in Asp.Net Core Mvc application.

For example, The controller:

public class ProductCategoriesController : Controller
{

    private readonly DBContext _context;

    public async Task<IActionResult> Details(int? id)
    {
        // Some Codes ...
    }
}

What I want to do is when I call the action "Details", the url goes to be like (http://domain/product-category/power-tools) which "power tools" is one of categories but as common in Asp.Net Core MVC it is (http://domain/ProductCategories/Details/1).

I tried to change controller prefix name and Action name but it doesn't work. I also tried to define new route endpoint in startup such as below but neither it works.

endpoints.MapControllerRoute(
    name: "category",
    pattern: "product-category/{*title}",
    defaults: new { controller = "ProductCategories", action = "Details" });

Is it possible to change action names and controller name without using Api controllers? How do I do that? Thanks

You should add the id parameter in the pattern too because of your action have a nullable parameter.

endpoints.MapControllerRoute(
                name: "category",
                pattern: "product-category/{title}/{id?}",
                defaults: new { controller = "ProductCategories", action = "Details" });

UPDATE: added a simple test screen

在此处输入图像描述

The best solution for what I wanted to do was not depends on changing routes in startup. With special thanks to author of this article https://rehansaeed.com/seo-friendly-urls-asp-net-core/ , I changed my action like this and it's done.

    [HttpGet("ProductCategory/{id}/{title}", Name = "ProductsRelatedToCategory")]
    public async Task<IActionResult> ProductsRelatedToCategory(int? id, string title)
    {
        if (id == null || !await _productCategoryRepo.IsExists((int)id))
        {
            return NotFound();
        }

        var langId = _languageRepository.GetByCode(LanguageCode).Result.Id;

        var productsRelatedToThisCategory = await _productRepo.GetByCategoryId((int)id, langId);
        var productCategory = await _productCategoryRepo.GetById((int)id);
        var allCategories = await _productCategoryRepo.GetAll(2);

        ViewData["ProductCategory"] = productCategory;
        ViewData["AllProductCategories"] = allCategories.ToList();

        string friendlyTitle = FriendlyUrlHelper.GetFriendlyTitle(productCategory.Title);

        if (!string.Equals(friendlyTitle, title, StringComparison.Ordinal))
        {
            return this.RedirectToRoutePermanent("ProductsRelatedToCategory", new { id = id, title = friendlyTitle });
        }

        return View("~/Views/Products/ProductsRelatedToCategory.cshtml", productsRelatedToThisCategory.ToList());
    }

And to call the action:

<a asp-action="ProductsRelatedToCategory" asp-controller="ProductCategories" asp-route-id="14" asp-route-title="Power Tools"><b>Power tools</b></a>

Net.Core have a bit different style, try this, you may need also to update your Startup.cs

[Route("/productcategories/")]
public class ProductCategoriesController : Controller
{

    private readonly DBContext _context;

    [HttpGet("details/{id}")] // here the id is not optional but you can set it to be
    public async Task<IActionResult> Details(int id) // id
    {
        // Some Codes ...
    }
}

and add to Startup.cs

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<TodoContext>(opt =>
           opt.UseInMemoryDatabase("TodoList"));
        services.AddControllers();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

Read more about Asp.Net Core 3.1 MVC conventions

https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-3.1&tabs=visual-studio

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