P.T. Nghĩa
P.T. Nghĩa

Reputation: 13

How do the URLs of all pages of my site look like: WebName/{title}

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.

Upvotes: 1

Views: 96

Answers (3)

dom
dom

Reputation: 6832

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.

Upvotes: 0

Wexx
Wexx

Reputation: 13

It looks like you're trying to map the same method signature to different controllers. You'd need to have another distinct piece of the Url to have them route to different controllers. With your current configuration it will not know which controller to route to (I'm not actually sure of the behavior, but you will most likely get an error message here).

I would think if you want to keep with the naming convention you have, maybe use /how-to-cook-{title} for the url for Recipes pages. (this could get dicey, in the event you have some weirdness in the title parameter).

Upvotes: 0

Rajan Mishra
Rajan Mishra

Reputation: 1178

Instead of this you can use [Route] attribute.

[HttpGet]
[Route("chicken-pizza")]
public ActionResult chickenPizza(){
 // Code Here
}

Read more: Web API Route and Route Prefix: Part 2 by Jasminder Singh.

Upvotes: 0

Related Questions