views:

299

answers:

2

Hi,

i'm new to ASP.NET MVC and i'm facing some structural design problems.

I can't figure out how to setup routing.

I want the following:

http://website/                          > HomeController     Action=Index

Public:
http://website/{controller}              > SectionController  Action=Index
http://website/products/id               > ProductsController Action=Details
http://website/products/category/id      > ProductsController Action=ListByCatId
http://website/products/categories/      > ProductsController Action=ListCategories
http://website/products/categories/id    > ProductsController Action=DetailsCategories

Admin:
http://website/admin/                    > AdminController    Action=Index
http://website/admin/{controller}        > SectionController  Action=Index

The default mapRoute is fine for most of the parts:

routes.MapRoute("Default", "{controller}/{action}/{id}", _
                New With {.controller = "Home", .action = "Index", .id = ""})

When I start putting 'category' instead of the id of the product the problems start...
Should I 'hardcode' the routeUrls, e.g. "products/category/{id}"?

For the Admin part:
I'd like to put all controllers belonging to the Admin section of the website in: /Controllers/Admin/XxxController.vb. Is it possible to Namespace them and let them have the same name as in the public section? e.q.
- Website.ProductsController class for public parts and
- Website.Admin.ProductsController for the Admin section? How should I setup this?

+3  A: 

This is how I would do it :

routes.MapRoute("ProductDetail", "Products/{id}", _
    New With {.controller = "Products", .action = "Details", .id = ""},
    New With {.id = @"\d+"})
    //constraint, so this route will not catch a category name
    //or the URL below

routes.MapRoute("ProductList", "Products/category/{id}", _
    New With {.controller = "Products", .action = "ListByCatId", .id = ""})

routes.MapRoute("Category", "Products/categories/{id}", _
    New With {.controller = "Products", .action= "ListCategories", .id = ""})
    //for the route above, let it fall to the ListCategories action
    //and in that action take a nullable of int as a parameter.
    //if the id parameter has a value, 
    //    return DetailsCategories(id)
    //else list the categories.


routes.MapRoute("Default", "{controller}/{action}/{id}", _
    New With {.controller = "Home", .action = "Index", .id = ""})

As for having two controllers with the same name, yes, you can do it with having different namespaces and specifying them in the mapRoute method. There's an overload that takes string[] namespaces. Just make sure you specify the namespaces for the controllers with the same name while routing.

çağdaş
+1  A: 

Yes, if you need to add additional routes that don't correspond to the default, go ahead and do so. You will want to add your additional custom routes above the default route, and use a narrow to broad ordering when adding the routes (so that narrow matches first). I would suggest making your controller actions match the default naming that you want visible first and foremost as much as possible.

instead of:

http://website/products/id               > ProductsController Action=Details
http://website/products/category/id      > ProductsController Action=ListByCatId
http://website/products/categories/      > ProductsController Action=ListCategories
http://website/products/categories/id    > ProductsController Action=DetailsCategories

using:

http://website/product/id               > ProductsController Action=Index
http://website/product/category/id      > ProductsController Action=category
http://website/product/      > ProductsController Action=Index
http://website/product/categories/id    > ProductsController Action=categories

Your Index method can take a nullable int (int? Id) where the Id corresponds to the product defined. If Id.HasValue is false, you return your ListCategories result.


public ActionResult Index(int? Id)
{
  if (Id.HasValue) return Details(Id.Value);
  return ListCategories();
}

This can keep your additional routing cleaner.

Tracker1