192 votos

Es posible hacer una ASP.NET MVC ruta basada en un subdominio?

Es posible tener una ASP.NET MVC ruta que utiliza subdominio información para determinar su ruta? Por ejemplo:

  • user1.domain.com va a un lugar
  • user2.domain.com se va a otra?

O, puedo hacerlo para que ambos van a la misma o controlador de la acción con un username parámetro?

140voto

Jon Cahill Puntos 2516

Usted puede hacer esto mediante la creación de una nueva ruta, y la adición a las rutas de recolección en registerroutes al en el global.asax. A continuación es un ejemplo muy simple de una Ruta personalizada:

public class ExampleRoute : RouteBase
{

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var url = httpContext.Request.Headers["HOST"];
        var index = url.IndexOf(".");

        if (index < 0)
            return null;

        var subDomain = url.Substring(0, index);

        if (subDomain == "user1")
        {
            var routeData = new RouteData(this, new MvcRouteHandler());
            routeData.Values.Add("controller", "User1"); //Goes to the User1Controller class
            routeData.Values.Add("action", "Index"); //Goes to the Index action on the User1Controller

            return routeData;
        }

        if (subDomain == "user2")
        {
            var routeData = new RouteData(this, new MvcRouteHandler());
            routeData.Values.Add("controller", "User2"); //Goes to the User2Controller class
            routeData.Values.Add("action", "Index"); //Goes to the Index action on the User2Controller

            return routeData;
        }

        return null;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        //Implement your formating Url formating here
        return null;
    }
}

39voto

Edward Brey Puntos 8771

Para capturar el subdominio manteniendo el estándar de MVC5 características de enrutamiento, utilice el siguiente SubdomainRoute clase derivada de Route.

Además, SubdomainRoute permite el subdominio opcionalmente a ser especificado como un parámetro de consulta, haciendo sub.example.com/foo/bar y example.com/foo/bar?subdomain=sub equivalente. Esto le permite probar antes de las DNS de los subdominios están configurados. El parámetro de consulta (cuando se usa) se propaga a través de nuevos enlaces generados por Url.Action, etc.

El parámetro de la consulta también permite a los locales de depuración con Visual Studio 2013 sin tener que configurar con el comando netsh o ejecutar como Administrador. De forma predeterminada, IIS Express sólo se une a localhost cuando no elevada; no se unen a sinónimos de los nombres de host como sub.localtest.me.

class SubdomainRoute : Route
{
    public SubdomainRoute(string url) : base(url, new MvcRouteHandler()) {}

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var routeData = base.GetRouteData(httpContext);
        if (routeData == null) return null; // Only look at the subdomain if this route matches in the first place.
        string subdomain = httpContext.Request.Params["subdomain"]; // A subdomain specified as a query parameter takes precedence over the hostname.
        if (subdomain == null) {
            string host = httpContext.Request.Headers["Host"];
            int index = host.IndexOf('.');
            if (index >= 0)
                subdomain = host.Substring(0, index);
        }
        if (subdomain != null)
            routeData.Values["subdomain"] = subdomain;
        return routeData;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        object subdomainParam = requestContext.HttpContext.Request.Params["subdomain"];
        if (subdomainParam != null)
            values["subdomain"] = subdomainParam;
        return base.GetVirtualPath(requestContext, values);
    }
}

Para su comodidad, llamar a los siguientes MapSubdomainRoute método de su RegisterRoutes método tal como lo haría el viejo y simple MapRoute:

static void MapSubdomainRoute(this RouteCollection routes, string name, string url, object defaults = null, object constraints = null)
{
    routes.Add(name, new SubdomainRoute(url) {
        Defaults = new RouteValueDictionary(defaults),
        Constraints = new RouteValueDictionary(constraints),
        DataTokens = new RouteValueDictionary()
    });
}

Por último, para acceder cómodamente a la subdominio (ya sea a partir de un cierto subdominio o a un parámetro de consulta), es útil para crear un Controlador de base de la clase con este Subdomain de la propiedad:

protected string Subdomain
{
    get { return (string)Request.RequestContext.RouteData.Values["subdomain"]; }
}

19voto

Jim Blake Puntos 707

Este no es mi trabajo, pero he de añadir en esta respuesta.

Aquí es una gran solución a este problema. Maartin Balliauw escribió el código que crea un DomainRoute clase que puede ser utilizado de forma muy similar a la normal de enrutamiento.

http://blog.maartenballiauw.be/post/2009/05/20/ASPNET-MVC-Domain-Routing.aspx

Ejemplo de uso sería como ese...

routes.Add("DomainRoute", new DomainRoute( 
    "{customer}.example.com", // Domain with parameters 
    "{action}/{id}",    // URL with parameters 
    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults 
))

;

4voto

Edward Brey Puntos 8771

Para capturar el subdominio cuando se utiliza la API de Web, anular la Acción Selector para inyectar subdomain parámetro de consulta. A continuación, utilice el subdominio parámetro de consulta de tus controladores " acciones como esta:

public string Get(string id, string subdomain)

Este enfoque hace que la depuración conveniente ya que se puede especificar el parámetro de consulta con la mano cuando se utiliza localhost en lugar del nombre de host real (véase la norma MVC5 de enrutamiento de respuesta para más detalles). Este es el código de la Acción:Selector

class SubdomainActionSelector : IHttpActionSelector
{
    private readonly IHttpActionSelector defaultSelector;

    public SubdomainActionSelector(IHttpActionSelector defaultSelector)
    {
        this.defaultSelector = defaultSelector;
    }

    public ILookup<string, HttpActionDescriptor> GetActionMapping(HttpControllerDescriptor controllerDescriptor)
    {
        return defaultSelector.GetActionMapping(controllerDescriptor);
    }

    public HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
    {
        var routeValues = controllerContext.Request.GetRouteData().Values;
        if (!routeValues.ContainsKey("subdomain")) {
            string host = controllerContext.Request.Headers.Host;
            int index = host.IndexOf('.');
            if (index >= 0)
                controllerContext.Request.GetRouteData().Values.Add("subdomain", host.Substring(0, index));
        }
        return defaultSelector.SelectAction(controllerContext);
    }
}

Sustituir la Acción por defecto del Selector mediante la adición de este a WebApiConfig.Register:

config.Services.Replace(typeof(IHttpActionSelector), new SubdomainActionSelector(config.Services.GetActionSelector()));

3voto

Nick Berardi Puntos 31361

Sí, pero usted tiene que crear su propia ruta de controlador.

Normalmente, la ruta no es consciente de que el dominio ya que la aplicación podría ser implementado en cualquier dominio y la ruta no atención de una manera o de otra. Pero en el caso de que usted desee basar el controlador y la acción del dominio, por lo que tendrá que crear una ruta personalizada que es consciente del dominio.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X