Thứ Năm, 14 tháng 8, 2014

Dotnet tips: Handling sub-domains in ASP.Net MVC

In SaasApp which is framework for mulituser-multitenant SAAS framework for ASP.Net MVC, what I wanted was that when user types the url without a subdomain my app should display the website where user can get details about the product and plans, select a plan and register an account (in this post account refers to say a company that can have multiple users) with selected plan. Once an account is created their users should be able to go to their selected subdomain like myaccount.[SAAS app domain].com, login and access the product. I wanted the subbdomain “myaccount” to be forwarded as a parameter to required actions in the controller to identify the account I am dealing with.

ASP.Net MVC has a sophisticated and flexible routing mechanism. It allows developers to create their own customized routing system by extending RouteBase class and providing your own implementation of GetRouteData(HttpContextBase) function.
Following is what I have used -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SaasApp.Utility;
namespace System.Web.Routing
{
    public class DomainRoute : RouteBase
    {
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
    //get subdomain, the string before first dot in the url
            string subdomain = UtilityHelper.GetSubdomain(httpContext.Request.Headers["HOST"]);
            RouteData routeData = new RouteData(this, new MvcRouteHandler());
            if (!string.IsNullOrEmpty(subdomain))
            {
//url has subdomain
                routeData.Values.Add("account", subdomain);
                string filepath = httpContext.Request.FilePath;
                string[] parts = filepath.Split('/');
                switch (parts[1].ToLower())
                {
                    case "app":
                        routeData.Values.Add("controller", "App");
                        if (parts.Length > 2)
                        {
                            switch (parts[2].ToLower())
                            {
                                case "index":
                                    routeData.Values.Add("action", "Index");
                                    break;
                                case "about":
                                    routeData.Values.Add("action", "About");
                                    break;
                                default:
                                    routeData.Values.Add("action", "Index");
                                    break;
                            }
                        }
                        else
                        {
                            routeData.Values.Add("action", "Index");
                        }
                        break;
                    case "account":
                        routeData.Values.Add("controller", "Account");
                        if (parts.Length > 2)
                        {
                            switch (parts[2].ToLower())
                            {
                                case "login":
                                    routeData.Values.Add("action", "Login");
                                    break;
                                case "logout":
                                    routeData.Values.Add("action", "Logout");
                                    break;
                            }
                        }
                        break;
                    default:
                        if (httpContext.Request.IsAuthenticated)
                        {
                            httpContext.Response.Redirect("/App/Index");
                        }
                        httpContext.Response.Redirect("/Account/Login");
                        break;
                }
            }
            else
            {
//url does not have subdomain
                string filepath = httpContext.Request.FilePath;
                string[] parts = filepath.Split('/');
                switch (parts[1].ToLower())
                {
                    case "home":
                        routeData.Values.Add("controller", "Home");
                        if (parts.Length > 2)
                        {
                            switch (parts[2].ToLower())
                            {
                                case "index":
                                    routeData.Values.Add("action", "Index");
                                    break;
                                case "plans":
                                    routeData.Values.Add("action", "Plans");
                                    break;
                                case "selectplan":
                                    routeData.Values.Add("action", "SelectPlan");
                                    if (parts.Length > 3)
                                    {
                                        routeData.Values.Add("planType", parts[3]);
                                    }
                                    else
                                    {
                                        routeData.Values.Add("planType", "1");
                                    }
                                    break;
                                case "selectaplan":
                                    routeData.Values.Add("action", "SelectAPlan");
                                    break;
                                case "accountcreated":
                                    routeData.Values.Add("action", "AccountCreated");
                                    if (parts.Length > 3)
                                    {
                                        routeData.Values.Add("accountName", parts[3]);
                                    }
                                    else
                                    {
                                        routeData.Values.Add("accountName", "");
                                    }
                                    break;
                                case "about":
                                    routeData.Values.Add("action", "About");
                                    break;
                                default:
                                    routeData.Values.Add("action", "Index");
                                    break;
                            }
                        }
                        else
                        {
                            routeData.Values.Add("action", "Index");
                        }
                        break;
                    default:
                        httpContext.Response.Redirect("/Home/Index");
                        break;
                }
            }
            return routeData;
        }
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            //Implement your formating Url formating here
            return null;
        } 
    }
}

0 nhận xét:

Đăng nhận xét