C# 如何在URL路由中映射模型数据?

C# 如何在URL路由中映射模型数据?,c#,asp.net-mvc,C#,Asp.net Mvc,我有一个索引页面,其中显示类别(具有属性:id和name),URL请求:http://localhost:62745/home/index 当我点击一个类别时,我被带到http://localhost:62745/Home/Products/6 我想使URL更详细,并用刚刚单击的类别的name属性替换上一个URL中的类别Id属性6 我的路线配置如下所示: public class RouteConfig { public static void RegisterRoute

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

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

我想使URL更详细,并用刚刚单击的类别的
name
属性替换上一个URL中的类别Id属性
6

我的路线配置如下所示:

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 });
}
//获取:产品
公共异步任务索引(int?id,字符串categoryName)
{
var products=(等待db.Categories.Where(c=>c.Id==Id)
.SelectMany(p=>p.Products.Select(x=>newproductviewmodel{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();
如果(产品==null)
{
返回HttpNotFound();
}
返回视图(新ProductIndexViewModel{Products=Products,CategoryId=id});
}

您的两条路线在解释方式上都是相同的-它们接受2段和可选的第3段,因此
Home/Products/6
Home/Products/CategoryName
都与第一条
默认
路线匹配(第二条
路线没有唯一的区别,因此它永远不会被击中

您的问题涉及第二个url中的
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
    ....
}
或者,如果希望参数为
字符串名称
而不是
字符串id
,则可以定义特定路由并将其放置在
默认
路由之前

routes.MapRoute(
    name: "ProductDetails",
    url: "Home/Products/{name}",
    defaults: new { controller = "Home", action = "Products", name = UrlParameter.Optional }
);
因此,该方法成为

public ActionResult Products(string name)


旁注:事实上您在
索引()中有一个查询
获取类别名称的方法表明,您可能还需要一条“slug”路线,在这种情况下,请参阅。

我认为
id
类别
名称的数字标识符?如果是这种情况,我也会假设
id
是唯一的,而
类别
没有唯一的约束在它上面。尝试使用人类可读的
类别
作为您尝试键入的值将导致问题。您试图完成的是什么?这仅仅是为了在查询字符串中有一个可读的值吗?需要注意的一点是,当映射路由时,您总是希望从顶部最具体的路由到t处最一般的路由他位于底部。因此,默认路由需要是列表中的最后一个路由,而不是当前的第一个路由。否则,其他路由将无法获得机会来解释为什么会发生这种情况以及如何修复。