views:

46

answers:

1

I am looking to produce an MVC site which has complete control of the url structure using routing.

The specific requirements are:

www.mysite.com/ = homepage (home controller)

www.mysite.com/common/about = content page (common controller)

www.mysite.com/common/contact = content page (common controller)

www.mysite.com/john = twitter style user page (dynamic controller)

www.mysite.com/sarah = twitter style user page (dynamic controller)

www.mysite.com/me = premium style user page (premium controller)

www.mysite.com/oldpage.html = 301 redirect to new page

www.mysite.com/oldpage.asp?id=3333 = 301 redirect to new page

My routes look as follows:

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Common",
            "common/{action}/{id}",
            new { controller = "common", action = "Index", id = "" }
        );

        routes.MapRoute(
            "Home",
            "",
            new { controller = "Home", action = "Index", id = "" }
            );



        routes.MapRoute(
            "Dynamic",
            "{id}",
            new { controller = "dynamic", action = "Index", id = "" }
            );

In order to handle the 301 rredirct, I have a database defining the old pages and their new page urls and a stored procdure to handle the lookup. The code (handler) looks like this:

public class AspxCatchHandler : IHttpHandler, IRequiresSessionState {

    #region IHttpHandler Members

    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        if (context.Request.Url.AbsolutePath.Contains("aspx") && !context.Request.Url.AbsolutePath.ToLower().Contains("default.aspx"))
        {
            string strurl = context.Request.Url.PathAndQuery.ToString();
            string chrAction = "";
            string chrDest = "";

            try
            {

                DataTable dtRedirect = SqlFactory.Execute(
                    ConfigurationManager.ConnectionStrings["emptum"].ConnectionString,
                    "spGetRedirectAction",
                    new SqlParameter[] { 
                        new SqlParameter("@chrURL", strurl)
                    },
                    true);

                chrAction = dtRedirect.Rows[0]["chrAction"].ToString();
                chrDest = dtRedirect.Rows[0]["chrDest"].ToString();

                chrDest = context.Request.Url.Host.ToString() + "/" + chrDest;
                chrDest = "http://" + chrDest;


                if (string.IsNullOrEmpty(strurl))
                    context.Response.Redirect("~/");
            }
            catch
            {
                chrDest = "/";// context.Request.Url.Host.ToString();
            }

            context.Response.Clear();
            context.Response.Status = "301 Moved Permanently";
            context.Response.AddHeader("Location", chrDest);
            context.Response.End();

        }
        else
        {
            string originalPath = context.Request.Path;
            HttpContext.Current.RewritePath("/", false);
            IHttpHandler httpHandler = new MvcHttpHandler();
            httpHandler.ProcessRequest(HttpContext.Current);
            HttpContext.Current.RewritePath(originalPath, false);
        }
    }

    #endregion
}

It is very simple to look up a user and in fact the above code does this. My problem is in the dynamic / premium part.

I am trying to do the following:

1) in the dynamic controller, lookup the username.

2) if the username is in the user list (database), show the Index ActionResult of the Dynamic controller.

3) if the username is not found, look up the username in the premium list

4) if the username is fund in the premium list (database) then show the Index ActionResult of the Preium controller.

5) If all else fails jump to the 404 page (which will ask the user to sign up)

Is this possible?

Looking up the user twice is a bad idea for performance?

How do I do this without redirecting?

+1  A: 

How is your database organised? Hopefully one user table with an indicator of premium status, if so then you really only need to hit the database once. Otherwise you could possibly benefit from a view combining the user data.

Jonathan
I think this is a good approach too. Put all the users in one table and have a flag for premium. Render the appropriate view based on the premium flag.If user not present, 404...
Cymen
In an ideal world this would be one table and a simple matter of showing the data differantly.However this is not the case and I have two ActionResults and two views in the same controller as the logic.Im thinking that an ActionResult is not going to do this?
Desiny
can you not create a database level view to combine the user data? If not then you should be able to use RedirectToAction - see listing 3 for an example here: http://www.asp.net/Learn/mvc/tutorial-03-cs.aspx
Jonathan