문제

하위 도메인 정보를 사용하여 경로를 결정하는 ASP.NET MVC 경로를 가질 수 있습니까? 예를 들어:

  • user1.Domain.com 한 곳으로갑니다
  • user2.Domain.com 다른 사람에게 간다?

또는이 두 가지 모두 동일한 컨트롤러/작업으로 이동하여 username 매개 변수?

도움이 되었습니까?

해결책

새로운 경로를 만들고 Global.asax의 RegisterRoutes의 경로 컬렉션에 추가하여 수행 할 수 있습니다. 아래는 사용자 정의 경로의 매우 간단한 예입니다.

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;
    }
}

다른 팁

에게 표준 MVC5 라우팅 기능을 유지하면서 하위 도메인 캡처, 다음을 사용하십시오 SubdomainRoute 수업에서 파생 Route.

또한, SubdomainRoute 하위 도메인을 선택적으로 지정할 수 있습니다 쿼리 매개 변수, 만들기 sub.example.com/foo/bar 그리고 example.com/foo/bar?subdomain=sub 동등한. 이를 통해 DNS 하위 도메인이 구성되기 전에 테스트 할 수 있습니다. 쿼리 매개 변수 (사용시)는 생성 된 새 링크를 통해 전파됩니다. Url.Action, 등.

쿼리 매개 변수는 또한 visual studio 2013을 사용하여 로컬 디버깅을 할 필요없이 netsh로 구성하거나 관리자로 실행하십시오. 기본적으로 IIS Express 만 바인딩합니다 로컬 호스트 비 엘리시가 발생했을 때; 동의어 호스트 이름과 같은 결합하지 않습니다 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);
    }
}

편의를 위해 다음에 전화하십시오 MapSubdomainRoute 당신의 방법 RegisterRoutes 방법은 당신이 평범한 늙은 것처럼 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()
    });
}

마지막으로, 하위 도메인 (True Sub 도메인 또는 쿼리 매개 변수)에 편리하게 액세스하려면 컨트롤러 기본 클래스를 작성하는 것이 도움이됩니다. Subdomain 재산:

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

이것은 내 일이 아니지만이 답변에 추가해야했습니다.

이 문제에 대한 훌륭한 해결책이 있습니다. Maartin Balliauw는 정상 라우팅과 매우 유사하게 사용할 수있는 도메인 라우트 클래스를 생성하는 코드를 작성했습니다.

http://blog.maartenballiauw.be/post/2009/05/20/aspnet-mvc-domain-routing.aspx

샘플 사용은 다음과 같습니다 ...

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

;

사용할 때 하위 도메인을 캡처합니다 웹 API, 조치 선택기를 무시하여 a를 주입하십시오 subdomain 쿼리 매개 변수. 그런 다음 컨트롤러의 동작에서 다음과 같은 하위 도메인 쿼리 매개 변수를 사용하십시오.

public string Get(string id, string subdomain)

이 접근법은 사용할 때 쿼리 매개 변수를 직접 지정할 수 있으므로 디버깅을 편리하게합니다. 로컬 호스트 실제 호스트 이름 대신 (참조 표준 MVC5 라우팅 답변 자세한 내용은). 이것은 행동 선택기 코드입니다.

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);
    }
}

이것을 추가하여 기본 조치 선택기를 교체하십시오 WebApiConfig.Register:

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

예,하지만 자신만의 경로 처리기를 만들어야합니다.

일반적으로 경로는 응용 프로그램이 모든 도메인에 배치 될 수 있고 경로는 어떤 방식 으로든 신경 쓰지 않기 때문에 도메인을 알지 못합니다. 그러나 귀하의 경우 컨트롤러와 작업을 도메인에서 벗어나려면 도메인을 알고있는 사용자 정의 경로를 만들어야합니다.

내가 만들었다 하위 도메인 라우팅을위한 라이브러리 그러한 경로를 만들 수 있습니다. 현재 .NET Core 1.1 및 .NET Framework 4.6.1에서 작동하지만 가까운 시일 내에 업데이트 될 예정입니다. 이것이 어떻게 작동하는지입니다.
1) startup.cs의 서브 도메인 경로를지도

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    var hostnames = new[] { "localhost:54575" };

    app.UseMvc(routes =>
    {
        routes.MapSubdomainRoute(
            hostnames,
            "SubdomainRoute",
            "{username}",
            "{controller}/{action}",
            new { controller = "Home", action = "Index" });
    )};

2) 컨트롤러/homecontroller.cs

public IActionResult Index(string username)
{
    //code
}

3)이 lib를 사용하면 URL 및 양식을 생성 할 수 있습니다. 암호:

@Html.ActionLink("User home", "Index", "Home" new { username = "user1" }, null)

생성됩니다 <a href="http://user1.localhost:54575/Home/Index">User home</a>생성 된 URL은 또한 현재 호스트 위치 및 스키마에 따라 다릅니다.
HTML 도우미를 사용할 수도 있습니다 BeginForm 그리고 UrlHelper. 좋아한다면 Tag Helpers라는 새로운 기능을 사용할 수도 있습니다.FormTagHelper, AnchorTagHelper)
그 LIB에는 아직 문서가 없지만 일부 테스트 및 샘플 프로젝트가 있으므로 자유롭게 탐색하십시오.

~ 안에 asp.net 코어, 호스트는 이용 가능합니다 Request.Host.Host. 쿼리 매개 변수를 통해 호스트를 재정의하는 경우 먼저 확인하십시오. Request.Query.

호스트 쿼리 매개 변수가 새 경로 기반 URL로 전파되도록하려면이 코드를 app.UseMvc 경로 구성 :

routes.Routes.Add(new HostPropagationRouter(routes.DefaultHandler));

그리고 정의 HostPropagationRouter 이와 같이:

/// <summary>
/// A router that propagates the request's "host" query parameter to the response.
/// </summary>
class HostPropagationRouter : IRouter
{
    readonly IRouter router;

    public HostPropagationRouter(IRouter router)
    {
        this.router = router;
    }

    public VirtualPathData GetVirtualPath(VirtualPathContext context)
    {
        if (context.HttpContext.Request.Query.TryGetValue("host", out var host))
            context.Values["host"] = host;
        return router.GetVirtualPath(context);
    }

    public Task RouteAsync(RouteContext context) => router.RouteAsync(context);
}

URL에 통과 된 호스트를 볼 수있는 새 경로 처리기를 정의한 후, 당신은 액세스하는 사이트를 알고있는 기본 컨트롤러의 아이디어를 가지고 갈 수 있습니다. 다음과 같이 보입니다.

public abstract class SiteController : Controller {
    ISiteProvider _siteProvider;

    public SiteController() {
        _siteProvider = new SiteProvider();
    }

    public SiteController(ISiteProvider siteProvider) {
        _siteProvider = siteProvider;
    }

    protected override void Initialize(RequestContext requestContext) {
        string[] host = requestContext.HttpContext.Request.Headers["Host"].Split(':');

        _siteProvider.Initialise(host[0]);

        base.Initialize(requestContext);
    }

    protected override void OnActionExecuting(ActionExecutingContext filterContext) {
        ViewData["Site"] = Site;

        base.OnActionExecuting(filterContext);
    }

    public Site Site {
        get {
            return _siteProvider.GetCurrentSite();
        }
    }

}

ISiteProvider 간단한 인터페이스입니다.

public interface ISiteProvider {
    void Initialise(string host);
    Site GetCurrentSite();
}

나는 당신이 간다 루크 샘슨 블로그

각 세입자마다 다른 도메인/하위 도메인을 사용하여 프로젝트에 다중 설정 기능을 제공하려는 경우 Saaskit을 살펴 봐야합니다.

https://github.com/saaskit/saaskit

코드 예제는 여기에서 볼 수 있습니다. http://benfoster.io/blog/saaskit-multi-tenancy-made-easy

ASP.NET Core를 사용하는 몇 가지 예 : http://andrewlock.net/forking-the-pipeline-tenant-pecific-files-with-saaskit-in-asp-net-core/

편집 : ASP.NET Core 프로젝트에서 Saaskit을 사용하지 않으려면 MAARTEN의 MVC6에 대한 도메인 라우팅 구현을 볼 수 있습니다. https://blog.maartenballiauw.be/post/2015/02/17/domain-routing-and-resolving-current-tenant-with-aspnet-mvc-6-aspnet-5.html

그러나 이러한 GIST는 유지 관리되지 않으며 ASP.NET Core의 최신 릴리스에서 작업하기 위해 조정해야합니다.

코드에 대한 직접 링크 : https://gist.github.com/maartenba/77ca6f9cfef50efa96ec#file-domaintemplateroutebuilderextensions-cs

몇 달 전에 나는 방법이나 컨트롤러를 특정 도메인으로 제한하는 속성을 개발했습니다.

사용하기가 매우 쉽습니다.

[IsDomain("localhost","example.com","www.example.com","*.t1.example.com")]
[HttpGet("RestrictedByHost")]
public IActionResult Test(){}

컨트롤러에 직접 적용 할 수도 있습니다.

public class IsDomainAttribute : Attribute, Microsoft.AspNetCore.Mvc.Filters.IAuthorizationFilter
{

    public IsDomainAttribute(params string[]  domains)
    {
        Domains = domains;
    }

    public string[] Domains { get; }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var host = context.HttpContext.Request.Host.Host;
        if (Domains.Contains(host))
            return;
        if (Domains.Any(d => d.EndsWith("*"))
                && Domains.Any(d => host.StartsWith(d.Substring(0, d.Length - 1))))
            return;
        if (Domains.Any(d => d.StartsWith("*"))
                && Domains.Any(d => host.EndsWith(d.Substring(1))))
            return;

        context.Result = new Microsoft.AspNetCore.Mvc.NotFoundResult();//.ChallengeResult
    }
}

제한 : 다른 필터를 사용하여 다른 방법에 대해 두 개의 동일한 경로를 가질 수 없을 수도 있습니다. 다음은 중복 경로에 대한 예외를 던질 수 있습니다.

[IsDomain("test1.example.com")]
[HttpGet("/Test")]
public IActionResult Test1(){}

[IsDomain("test2.example.com")]
[HttpGet("/Test")]
public IActionResult Test2(){}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top