3
votes

I think I have made my routes more advanced than they need to be. I have a few products that are in a few different 3-level categories, but most of my products are in 2-level categories. No products are in a 1-level category.

So its like this:
* cat/subCat/subSubCat/products
* cat/subCat/products

And I'd like to have my URLs like defined in my routes.
2 Index: ../Shop/Sortiment/cat/subCat
2 Details: ../Shop/Sortiment/cat/subCat/product/1/name
3 Index: ../Shop/Sortiment/cat/subCat/subSubCat
3 Details: ../Shop/Sortiment/cat/subCat/subSubCat/product/2/name

routes.MapRoute(
    name: "CategoryIndex",
    url: "Shop/Sortiment/{category}/{subCategory}/{subSubCategory}",
    defaults: new { controller = "Sortiment", action = "Index", subCategory= UrlParameter.Optional, subSubCategory = UrlParameter.Optional }
);
routes.MapRoute(
    name: "ProductDetails",
    url: "Shop/Sortiment/{category}/{subCategory}/{subSubCategory}/product/{id}/{productName}",
    defaults: new { controller = "Sortiment", action = "Details", subSubCategory = UrlParameter.Optional, productName = UrlParameter.Optional }
);

My products class have a Category Category property. Each Category Have a virtual Category ParentCategory property that is either null (first level category) or populated with it's parent category.

With 2-level products I can write links like this (with no subSubCategory in my routes):

@Url.RouteUrl("ProductDetails", new
{
    category = item.Category.ParentCategory.Name,
    subCategory = item.Category.Name,
    id = item.ID,
    productName = item.Name
})

But now If I have products that are either 2 or 3-levels I want to write this below, but ofcourse I get nullrefexception on the 2-level products since they don't have 2 ParentCategory.

@Url.RouteUrl("ProductDetails", new
{
    category = item.Category.ParentCategory.ParentCategory.Name,
    subCategory = item.Category.ParentCategory.Name,
    subSubCategory = item.Category.Name,
    id = item.ID,
    productName = item.Name
})

So what do I need to do to get my URLs the way I want to? Maybe it's best for me to redo my routes? Hopefully I gave you enough information.

4
I never liked that form of routing. Take a look at attribute routing if you're using MVC 5 (blogs.msdn.com/b/webdev/archive/2013/10/17/…). Much easier!Gary McGill

4 Answers

0
votes

It looks like you are using the wrong rout name for the 2-level url. Change to:

@Url.RouteUrl("CategoryIndex", new
{
category = item.Category.ParentCategory.Name,
subCategory = item.Category.Name,
id = item.ID,
productName = item.Name
})
0
votes

Rob,

This is the first thing that you should do for your nested routing.

For such nested url, I think you should configures your routes as below:-

 routes.MapRoute(
            name: "ProductDetails",
            url: "shop/{*subCategory }",
            defaults: new { controller = "Sortiment", action = "Details", subCategory = UrlParameter.Optional }
        );
0
votes

You could just inherit RouteBase, which will give you full control over your URLs. One option is just to make them database-driven based on a primary key as in this answer so you only need to keep track of the primary key to URL mapping in order to pull up your product/category information.

Then, when you specify a URL, you just need to include its primary key as the id route value, controller, and action - that is all.

@Html.Action("Details", "CustomPage", new { id = 1234 })

Note that you could have a single route for product and a single route for category.

0
votes
 routes.MapRoute(
           name: "SubCategoryAction",
           url: "{action}/{id}/{pid}",
           defaults: new { controller = "ControllerName", action = "ActionName", id = UrlParameter.Optional ,pid= UrlParameter.Optional }
           );

//or use traditional AttributeRouting as

[AttributeRouting.Web.Mvc.Route("{action}/{id}/{pid}")]    
public ActionResult ActionName(string id,string pid){}