【问题标题】:How to map model data in URL route?如何在 URL 路由中映射模型数据?
【发布时间】:2017-01-22 08:57:30
【问题描述】:

我有一个索引页面,它显示类别(具有属性:id 和名称)和 URL 请求:http://localhost:62745/home/index

当我点击一个类别时,我被带到http://localhost:62745/Home/Products/6

我想让 URL 更详细,并将之前 URL 中的 Category Id 属性 6 替换为刚刚单击的 Category 的 name 属性。

我的路线配置如下所示:

public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

            routes.MapRoute(
                name: "Categories",
                url: "{controller}/{action}/{categoryName}",
                defaults: new { controller = "Category", action = "Index", categoryName = UrlParameter.Optional }
            );

        }
    }

第一个MapRoute() 方法已经实现。我添加了第二个希望解决我的问题,但它没有。

这是我对产品的控制器操作:

// GET: Product
public async Task<ActionResult> Index(int? id, string categoryName)
{

    var products = (await db.Categories.Where(c => c.Id == id)
                                    .SelectMany(p => p.Products.Select(x => new ProductViewModel { Id = x.Id, Name = x.Name, ByteImage = x.Image, Price = x.Price}))
                                    .ToListAsync());

    categoryName = db.Categories.Where(c => c.Id == id).Select(c => c.Name).ToString();

    if (products == null)
    {
        return HttpNotFound();
    }

    return View(new ProductIndexViewModel{ Products = products, CategoryId = id });
}

【问题讨论】:

  • 我认为idCategory 名称的数字标识符?如果是这种情况,我还假设 id 是唯一的,而 Category 没有唯一约束。尝试使用人类可读的Category 作为您尝试关闭的值会导致问题。你想要完成什么?这仅仅是为了在您的查询字符串中有一个可读的值吗?
  • 需要注意的一点是,在映射路线时,您总是希望从顶部的最具体到底部的最一般。所以默认路由需要在列表中的最后一个,而不是你目前拥有的第一个。否则其他路线将没有机会
  • 请参阅Why map special routes first before common routes in asp.net mvc?,了解为什么会发生这种情况以及如何解决。

标签: c# asp.net-mvc


【解决方案1】:

您的两条路线在解释方式上是相同的 - 它们接受 2 个段和一个可选的第 3 段,因此 Home/Products/6Home/Products/CategoryName 都匹配第一个 Default 路线(没有什么独特之处可以区分第二个Categories route 所以它永远不会被击中。

您的问题是指第二个网址中的Products()方法,但您没有显示该方法,因此不清楚您指的是产品名称还是类别名称,但主体是相同的。

假设您希望 url 为 Home/Products/ProductName 以显示特定产品,然后在视图中

@foreach(var item in Model.Products)
{
    // link for each product
    @Html.ActionLink("Details", "Products", "Home", new { id = item.Name }, null)

那你就可以简单的制作方法了

public ActionResult Products(string id)
{
    // the value of id is the the the product name
    ....
}

或者,如果您希望参数是string name 而不是string id,那么您可以定义一个特定的路由并将其放在Default 路由之前。

routes.MapRoute(
    name: "ProductDetails",
    url: "Home/Products/{name}",
    defaults: new { controller = "Home", action = "Products", name = UrlParameter.Optional }
);

这样方法就变成了

public ActionResult Products(string name)

旁注:您在Index() 方法中查询以获取类别名称的事实表明您可能还需要“slug”路线,在这种情况下,请参阅how to implement url rewriting similar to SO

【讨论】:

    猜你喜欢
    • 2016-08-08
    • 1970-01-01
    • 2017-03-25
    • 2019-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-26
    • 2013-07-26
    相关资源
    最近更新 更多