I am working on an web ASP.NET MVC, I want all the pages on my web to have a unique URL form that looks like this: WebName/{Title} . This is requirement of my customer.
For example: store.com/chicken-pizza and store.com/how-to-cook-beefsteak, but not: store.com/foods/chicken-pizza and store.com/recipe/how-to-cook-beefsteak
I tried to using RouteConfig:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
/* store.com/foods => This works well */
routes.MapRoute(
name: "List-Foods",
url: "foods",
defaults: new { controller = "Food", action = "ListFoods", id = UrlParameter.Optional }
);
/* store.com/chicken-pizza, store.com/cheese-sandwich,... => This works well */
routes.MapRoute(
name: "Detail-Food",
url: "{title}",
defaults: new { controller = "Food", action = "FoodDetail", id = UrlParameter.Optional }
);
/* store.com/recipes => This works well */
routes.MapRoute(
name: "List-Recipes",
url: "recipes",
defaults: new { controller = "Recipe", action = "ListRecipes", id = UrlParameter.Optional }
);
/* store.com/how-to-make-beefsteak,
store.com/instructions-for-making-cookies,..
=> Conflict occurred... this route can't be touch because it
has the same url form as Details-Food (url:{title}) */
routes.MapRoute(
name: "Detail-Recipe",
url: "{title}",
defaults: new { controller = "Recipe", action = "RecipeDetail", id = UrlParameter.Optional }
);
...............
}
I realized that routes.MapRoute(s) cannot have the same URL form (url:"{title}"). That is not a problem for url:"foods" (to get a list of foods) and url:"recipes" (to get a list of recipes) because I have specified the words(foods and recipes) in routes.Maproute. Also, I can get detailed information of any feed by {title} with Detail-Food route easily. But, the problem occurred at Detail-Recipe route, because it has the same url form (url:{title}) as Detail-Food route, I can't touch Recipe/RecipeDetail to get data.
You're not gonna be able to pull this off using the default route handler you're gonna have to roll out your own custom one to catch the FoodDetail and RecipeDetail urls.
FoodRecipeRouteHandler.cs
public class FoodRecipeRouteHandler : MvcRouteHandler
{
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
{
string title = requestContext.RouteData.Values["title"] as string;
var food = database.GetFoodByTitle(title);
if (food != null)
{
requestContext.RouteData.Values["controller"] = "Food";
requestContext.RouteData.Values["action"] = "FoodDetail";
}
else
{
var recipe = database.GetRecipeByTitle(title);
if (recipe != null)
{
requestContext.RouteData.Values["controller"] = "Recipe";
requestContext.RouteData.Values["action"] = "RecipeDetail";
}
}
return base.GetHttpHandler(requestContext);
}
}
RouteConfig
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
name: "FoodRecipeDetail",
url: "{title}").RouteHandler = new FoodRecipeRouteHandler();
}
What's happening here is we're catching the route with the format {title}
then looking up in a database to try and find a matching food or recipe item and assigning the appropriate action
and controller
values to the RequestContext
. This is just a basic implementation example to set you on the right track.