Reputation: 610
I am running into a problem with my routes in MVC4.
I have a few actions that live outside of a specific product and many more that live within the user chosen product. In order to accommodate the actions I have mapped two routes
context.MapRoute(
"CMS_product",
"CMS/{productId}/{controller}/{action}/{id}",
new { controller = MVC.CMS.Home.Name, action = MVC.CMS.Home.ActionNames.Index, productId = default(Guid).ToString(), id = UrlParameter.Optional },
new string[] { "Areas.CMS.Controllers" }
);
context.MapRoute(
"CMS_default",
"CMS/{controller}/{action}/{id}",
new { controller = MVC.CMS.Home.Name, action = MVC.CMS.Home.ActionNames.Index, id = UrlParameter.Optional },
new string[] { "Areas.CMS.Controllers" }
);
So while this works in a generic since, none of my routes will match the default route any longer and instead of getting a URL like
~/CMS/Product/List
When operating outside of a product I get urls like this.
~/CMS/00000000-0000-0000-0000-000000000000/Product/List
Another note: I have tried to hard code the Prodcut/List in as a route, and have placed it before CMS_product in the hopes that it would match prior to the other url. I feel like I must be overlooking something simple.
Upvotes: 0
Views: 73
Reputation: 610
For completeness, should anyone else run into a similar issue here is the solution.
// used to match ~/CMS/00000000-0000-0000-0000-000000000000/Product/List
// prevents the GUID.Empty from showing when there is no product value
// in the segment
context.MapRoute(
name: "CMS_nullproduct",
url: "CMS/{controller}/{action}/{id}",
defaults: new { controller = MVC.CMS.Home.Name, action = MVC.CMS.Home.ActionNames.Index, id = UrlParameter.Optional },
constraints: new { productId = Guid.Empty.ToString() },
namespaces: new string[] { "Areas.CMS.Controllers" }
);
// matches any route with a productId segment value of anything aside from
// GUID.Empty
context.MapRoute(
name: "CMS_product",
url: "CMS/{productId}/{controller}/{action}/{id}",
defaults: new { controller = MVC.CMS.Home.Name, action = MVC.CMS.Home.ActionNames.Index, id = UrlParameter.Optional },
constraints: new { productId = @"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$" },
namespaces: new string[] { "Areas.CMS.Controllers" }
);
context.MapRoute(
name: "CMS_default",
url: "CMS/{controller}/{action}/{id}",
defaults: new { controller = MVC.CMS.Home.Name, action = MVC.CMS.Home.ActionNames.Index, id = UrlParameter.Optional },
namespaces: new string[] { "Areas.CMS.Controllers" }
);
Upvotes: 1
Reputation: 4073
In my opinion you should remove default value for productId
.
context.MapRoute(
"CMS_product",
"CMS/{productId}/{controller}/{action}/{id}",
new { controller = MVC.CMS.Home.Name, action = MVC.CMS.Home.ActionNames.Index, id = UrlParameter.Optional },
new string[] { "Areas.CMS.Controllers" }
);
If you not provide productId you routing engine should match second route and generate ~/CMS/Product/List but if you provide productId it match first rule.
Additionaly you can write custom IRouteConstraint or use regex to limit productId values.
context.MapRoute(
"CMS_product",
"CMS/{productId}/{controller}/{action}/{id}",
new { controller = MVC.CMS.Home.Name, action = MVC.CMS.Home.ActionNames.Index, id = UrlParameter.Optional },
new { productId = @"^\d{8}\-\d{4}\-\d{4}\-\d{4}\-\d{12}$" }
new string[] { "Areas.CMS.Controllers" }
);
Upvotes: 0