views:

148

answers:

2

In searching I came across http://stackoverflow.com/questions/411054/asp-net-mvc-page-subpage-routing and the wildcard was somewhat of a lifesaver, but presented a new problem.

Consider the following routes, if you will. The goal here is to have the index (http://www.domain.com) use the default route and [domain]/page use the Content route. The strSlug is a wildcard because I plan on splitting the slug to use for subpages. [domain]page/subpage (subpage would be the current slug). With it being a wildcard, it seems like [domain] is matching on the Content route.

What would be the proper way around that?

// Global.asx.cs  
routes.MapRoute(
        "Content", // Route name
        "{*strSlug}", // URL with parameters
        new { controller = "Home", action = "SiteContent", strSlug = UrlParameter.Optional } // Parameter defaults
    );

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}", // URL with parameters
        new { controller = "Home", action = "Index" } // Parameter defaults
    );

    // HomeController.cs
    // Not the best code, feel free to improve.
    public ActionResult SiteContent(string strSlug)
    {
        string[] strSlug_arr = strSlug.Split("/".ToCharArray());
        strSlug = strSlug_arr[(strSlug_arr.Length-1)];

        SiteContent data = DB.SiteContents.Single(c => c.Slug == strSlug);
        return View(data);
    }

EDIT: In doing some more research, I was hoping to use something like this.

public ActionResult Index()
{
    SiteContent data = DB.SiteContents.Single(c => c.Slug == "home-page");
    return View(data);
}

public ActionResult SiteContent(string strSlug)
{
    if (strSlug == null)
    {
        return RedirectToAction("Index");
    }
    else
    {
        string[] strSlug_arr = strSlug.Split("/".ToCharArray());
        strSlug = strSlug_arr[(strSlug_arr.Length - 1)];

        SiteContent data = DB.SiteContents.Single(c => c.Slug == strSlug);
        return View(data);
    }
}

..but this results in a redirect loop for some reason.

EDIT #2 So this solution kind of, sort of, maybe works? I have yet to see a downside.

    // Global.asx.cs
    routes.MapRoute(
        "Content", // Route name
        "{strSlug}/{*strSubSlug}", // URL with parameters
        new { controller = "Home", action = "SiteContent", strSubSlug = UrlParameter.Optional } // Parameter defaults
    );

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/", // URL with parameters
        new { controller = "Home", action = "Index" } // Parameter defaults
    );


    // HomeController.cs
    public ActionResult Index()
    {
        SiteContent data = DB.SiteContents.Single(c => c.Slug == "home-page");
        return View(data);
    }

    public ActionResult SiteContent(string strSlug, string strSubSlug)
    {
        /*
        string[] strSlug_arr = strSlug.Split("/".ToCharArray());
        strSlug = strSlug_arr[(strSlug_arr.Length - 1)];
         */

        if (strSubSlug != null)
        {
            string[] strSubSlug_arr = strSubSlug.Split("/".ToCharArray());
            strSlug = strSubSlug_arr[(strSubSlug_arr.Length - 1)];
        }

        SiteContent data = DB.SiteContents.Single(c => c.Slug == strSlug);
        return View(data);
    }

So [domain]/slug works.. and anything after that it parses off the last slug.. so [domain]slug/sub/sub/sub/content would grab the page matching the content slug.

+2  A: 

Putting the wild card as your first parameter in your url route will route every request to Content route. To achieve what you want, you can use this route.

route.MapRoute(
    "Content",
    "Page/{*strSlug}",
    new { controller = "Home", action = "SiteContent", strSlug = UrlParameter.Optional }
);

By accessing www.domain.com will use the default route and with www.domain.com/Page will use the Content route so as with www.domain.com/Page/subpage.

www.domain.com/Page/subpage1/subpage2

The above url will give your strSlug parameter of your SiteContent ActionResult the value subpage1/subpage2. Then you can parse your strSlug to get your content.

rob waminal
I noticed I could get by with that solution, but I have strict instructions to not have anything else other than the domain and the slug. On top of that, the index page is a different master page than the content/subcontent.
Don Boots
yes, but it is just impossible to get to the index page with your route, since the route the guide of the MVC on which Action to be executed. If you wildcard everything in your route everything will be caught by the wildcard. You must have atleast a call to the controller or a static string in your route so that not all route will be caught by the wildcard.
rob waminal
let me rephrase, You must have atleast a controller and action segment or a static string segment in your Url with Parameters of your MapRoute before your wildcard so that not all call to a page (including index) will not be caught by the wildcard.
rob waminal
A: 

See edit #2. So far this is working perfectly. So far...

Don Boots