【问题标题】:How can I implement slug-based routing in ASP .NET Core?如何在 ASP .NET Core 中实现基于 slug 的路由?
【发布时间】:2021-01-23 14:42:45
【问题描述】:

我正在开发各种学科的教育平台。在 Entity Framework Core 的帮助下,我设计了这样的数据库架构:

每个主题都属于一个类别,一个类别可以有一个或多个子类别(见附图)。

有了这些,我想实现如下路由:

/数学/积分/替代
/programming/paradigms/oop
/经济学/宏观/失业
例如。
/{类别}/{子类别}/{主题}

地点:

/mathematics(就像编程和经济学一样)是一个根类别(例如,没有父类别。它列出了所有与数学相关的子类别)
/integration 是一个子类别(其中还列出了所有与集成相关的主题)
/substitution 是一个主题


我尝试同时使用属性和常规路由以及区域,但在文件结构/复杂性中迷失了看似简单的任务...


到目前为止我的路线:

endpoints.MapAreaControllerRoute(
   name: "mathematics",
   areaName: "mathematics",
   pattern: "mathematics/{controller=Home}/{action=Index}/{slug?}"
);

您将如何解决这个问题?我需要哪些控制器和操作?

请参阅https://isibalo.com 以供参考。它是捷克语,但你明白了。只需查看 URL 路由。他是怎么做到的?

【问题讨论】:

  • 使用属性路由,将它们全部设为Route参数,但在前面添加一个段如'Article'或'Page'即为控制器。所以PageController 带有路由“page”,带有 HttpGet 属性的方法,路由“{a}/{b}/{c}”。
  • 您还可以使用 IIS Url Rewrite 或 NGINX 等 URL 重写器在 URL 到达您的应用程序之前对其进行转换,例如将 knowna/b/c 映射到 foo?a=knowna&b=b&c=c
  • @IanMercer 您的第一个建议帮助我摆脱困境并继续前进。足以消除混乱的信息。谢谢!

标签: c# asp.net-core entity-framework-core


【解决方案1】:

我使用区域和属性路由解决了这个问题。

Startup.cs

endpoints.MapAreaControllerRoute(
    "mathematics",
    "mathematics",
    "mathematics/{controller=Home}/{action=Index}/{slug?}"
);

MathematicsController.cs

[Area("Mathematics")]
[Route("[controller]")]
public class MathematicsController : Controller
{
    private readonly ApplicationDbContext _context;

    public MathematicsController(ApplicationDbContext context) => _context = context;

    [HttpGet("{slug}")]
    public async Task<IActionResult> Index(string slug)
    {
        var category = await _context.Categories
            .FirstOrDefaultAsync(s => s.Slug == slug);

        if (category == null)
            return View("Errors/NotFound", Response.StatusCode = 404);

        var subjects = await _context.Subjects
            .Include(c => c.Category)
            .Where(s => category.Slug == slug)
            .ToListAsync();

        return View("Index", new SubjectListViewModel { Subjects = subjects });
    }
    
    [HttpGet("{category}/{slug}")]
    public async Task<IActionResult> Show(string category, string slug)
    {
        var subject = await _context.Subjects.FirstOrDefaultAsync(s => s.Slug == slug);

        return subject == null
            ? View("Errors/NotFound", Response.StatusCode = 404)
            : View("Show", subject);
    }
}

最后,提供类别(也可以是子类别)和主题。

数学\Index.cshtml

<a
   asp-area="Mathematics"
   asp-controller="Mathematics"
   asp-action="Show"
   asp-route-department="@subject.Category.Slug"
   asp-route-slug="@subject.Slug"
>
   @subject.Title
</a>

【讨论】:

    【解决方案2】:

    我使用this slug 代码生成器来创建我保存在数据库中的 slug。然后我把这个蛞蝓拿来发给 View。在动作控制器的链接中,我有两个 asp-routes,一个用于 ID,一个用于 Slug。

    Index.cshtml

    <a asp-controller="Home" asp-action="Details" asp-route-id="@Model.Restaurants[i].Id" asp-route-slug="@Model.Restaurants[i].Slug">@Model.Restaurants[i].Name</a>
    

    在控制器中我有这个动作方法(我不关心方法内部的slug值,我只使用id值):

    HomeController.cs

    [HttpGet("Home/Details/{id}/{slug}")]
    public async Task<IActionResult> Details(int id, string slug)
    {
        var restaurant = await _unitOfWork.RestaurantRepository.GetAsync(id);
        var viewModel = new HomeDetailsVM 
        {
            Address = restaurant.Address,
            ...
        }; 
    
        return View(viewModel);       
    }
    

    Startup.cs

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider)
    {
        if (env.EnvironmentName == "Development")
        {
            app.UseDeveloperExceptionPage();
            app.UseShowAllServicesMiddleware();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
    
        app.UseStaticFiles();
        app.UseCookiePolicy();
    
        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();
    
        // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"));
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
            endpoints.MapRazorPages();
        });
    }
    

    这是它在浏览器中的样子:

    【讨论】:

      猜你喜欢
      • 2021-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-06
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      相关资源
      最近更新 更多