क्या एक उप डोमेन के आधार पर ASP.NET MVC मार्ग बनाना संभव है?


235

क्या ASP.NET MVC मार्ग होना संभव है जो अपने मार्ग को निर्धारित करने के लिए उपडोमेन जानकारी का उपयोग करता है? उदाहरण के लिए:

  • user1 .domain.com एक स्थान पर जाता है
  • user2 .domain.com दूसरे में जाता है?

या, क्या मैं इसे बना सकता हूं ताकि ये दोनों एक ही नियंत्रक / कार्रवाई के साथ एक usernameपैरामीटर पर जाएं?


मैंने बहु-किराए वाले अनुप्रयोगों के लिए एक समान प्रकार को लागू किया, लेकिन एक कस्टम रूट क्लास के बजाय एक अमूर्त आधार नियंत्रक का उपयोग किया। इस पर मेरा ब्लॉग पोस्ट यहाँ है
ल्यूक सैम्पसन

6
इस दृष्टिकोण पर विचार करना सुनिश्चित करें: http://blog.tonywilliams.me/uk-asp-net-mvc-2-rout-subdomains-to-areas मैंने पाया कि अन्य उत्तरों की तुलना में अपने ऐप के लिए मल्टीटेनेंसी शुरू करने के लिए यह बेहतर होगा। , क्योंकि एमवीसी क्षेत्र एक संगठित तरीके से किरायेदार-विशिष्ट नियंत्रकों और विचारों को पेश करने का एक अच्छा तरीका है।
trebormf

2
@trebormf - मुझे लगता है कि आपको इसे एक उत्तर के रूप में जोड़ना चाहिए, यह वही है जो मैंने अपने समाधान के लिए आधार के रूप में उपयोग किया है।
शैगलेज़

@ शगलेज़ - धन्यवाद यह एक उत्तर था, लेकिन एक मॉडरेटर ने इसे उन कारणों के लिए एक टिप्पणी में बदल दिया, जिन्हें मैं नहीं समझ सकता।
trebormf

5
टोनी की तरह टूट गया था। यहाँ एक है कि मेरे लिए काम किया है: blog.tonywilliams.me.uk/…
Ronnie Overby

जवाबों:


168

आप इसे एक नया मार्ग बना सकते हैं और इसे अपने 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;
    }
}

1
विस्तृत नमूने के लिए धन्यवाद, लेकिन मैं निम्नलिखित नहीं कर रहा हूं कि कैसे निष्पादित किया जाए। Global.asax से।
JustSteve

4
मैंने मार्ग को SubdomainRoute कहा और इसे इस तरह से पहला मार्ग कहा: path.Add (new SubdomainRoute ());
जेफ हैन्डले

6
क्या इस दृष्टिकोण को संभावित उप-डोमेन की सूची में हार्ड-कोडिंग की आवश्यकता है?
मैक्सिम वी। पावलोव

2
नहीं, आप "उपडोमेन" जैसे डेटाबेस क्षेत्र को जोड़ सकते हैं, जो कि आप वही होगा जो आप उपडोमेन से किसी विशेष उपयोगकर्ता के लिए, या जो कुछ भी होने की उम्मीद कर रहे हैं, तो बस उपडोमेन पर एक खोज करें।
रयान हेस

1
किसी को भी इस के एक webforms संस्करण की सिफारिश कर सकता है?
मैथ्यू

52

मानक MVC5 रूटिंग विशेषताओं को बनाए रखते हुए उपडोमेन को पकड़ने के लिए, निम्न SubdomainRouteव्युत्पन्न वर्ग का उपयोग करें Route

इसके अतिरिक्त, SubdomainRouteउप-डोमेन को वैकल्पिक रूप से एक क्वेरी पैरामीटर , बनाने sub.example.com/foo/barऔर example.com/foo/bar?subdomain=subसमकक्ष के रूप में निर्दिष्ट करने की अनुमति देता है । इससे आप DNS सबडोमेन कॉन्फ़िगर होने से पहले परीक्षण कर सकते हैं। क्वेरी पैरामीटर (उपयोग में होने पर) Url.Actionआदि द्वारा उत्पन्न नए लिंक के माध्यम से प्रचारित किया जाता है ।

क्वेरी पैरामीटर netsh से कॉन्फ़िगर किए बिना या व्यवस्थापक के रूप में चलाने के बिना विज़ुअल स्टूडियो 2013 के साथ स्थानीय डीबगिंग को भी सक्षम करता है । डिफ़ॉल्ट रूप से, IIS एक्सप्रेस केवल लोकलहोस्ट को बांधता है जब गैर-ऊंचा हो जाता है; यह host.ames जैसे 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()
    });
}

अंत में, आसानी से उपडोमेन (या तो एक सच्चे उपडोमेन या एक क्वेरी पैरामीटर से) का उपयोग कर सकते हैं, यह इस Subdomainसंपत्ति के साथ एक नियंत्रक आधार वर्ग बनाने में सहायक है :

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

1
मैंने उपडोमेन को हमेशा रूट वैल्यू के रूप में उपलब्ध कराने के लिए कोड को अपडेट किया। यह उपडोमेन तक पहुंच को सरल करता है।
एडवर्ड ब्रे

यह मुझे पंसद है। मेरी परियोजना के लिए बहुत सरल, और पर्याप्त से अधिक।
जल्द से जल्द

यह एक बेहतरीन जवाब है। क्या इसके लिए मार्ग विशेषताओं के साथ काम करने का कोई तरीका है? मैं "subdomain.domain.com/portal/register" जैसे रास्तों के लिए यह काम करने की कोशिश कर रहा हूं और विशेषताओं का उपयोग करना आसान हो जाएगा।
perfect_element

@perfect_element - विशेषता मार्ग ऐसे नहीं हैं जो सम्मेलन आधारित मार्ग हैं। ऐसा कुछ करने का एकमात्र तरीका अपनी स्वयं की विशेषता रूटिंग सिस्टम बनाना होगा।
नाइटऑव 8888

23

यह मेरा काम नहीं है, लेकिन मुझे इस जवाब पर इसे जोड़ना था।

यहाँ इस समस्या का एक शानदार समाधान है। Maartin Balliauw ने कोड लिखा जो एक DomainRoute क्लास बनाता है जिसे सामान्य रूटिंग के समान उपयोग किया जा सकता है।

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

;


5
इस समाधान के साथ एक समस्या है। कहो, आप उप-डोमेन को अलग-अलग उपयोगकर्ताओं के रूप में संभालना चाहते हैं: path.Add ("SD", नया DomainRoute ("user} .localhost", "", नया {कंट्रोलर = "होम", एक्शन = "IndexForUser", user = "u1) }}); यह मुखपृष्ठ को भी कैश करता है। यह रेगेक्स के कारण उत्पन्न होता है। इसे ठीक करने के लिए, आप DomainRoute.cs में CreateRegex पद्धति की एक प्रतिलिपि बना सकते हैं, इसे CreateDomainRegex नाम दें, इस रेखा पर * +: source = source.Replace ("}", @ "> ([a-) को बदलें) zA-Z0-9 _] *)) "); और GetRouteData विधि में डोमेन रेक्स के लिए इस नई विधि का उपयोग करें: domainRegex = CreateDomainRegex (डोमेन);
गोर्केम पैकसी

मुझे नहीं पता कि मैं इस कोड को क्यों नहीं चला सकता ... मुझे सिर्फ SERVER NOT FOUNDत्रुटि प्राप्त हुई ... इसका मतलब है कि कोड मेरे लिए काम नहीं कर रहा है ... क्या आप किसी अन्य व्यक्ति या किसी अन्य व्यक्ति को सेट कर रहे हैं ?!
डॉ। टीजे


1
@IDisposable MvcApplication.DnsSuffix क्या है?
हाबो

हम सिर्फ web.config में आधार डीएनएस डोमेन बेनकाब ... ठेठ मूल्य .example.org होगा
IDisposable

4

वेब एपीआई का उपयोग करते समय उपडोमेन को पकड़ने के लिए , 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()));

कोई भी समस्या है जहाँ मार्ग डेटा वेब एपीआई नियंत्रक पर नहीं दिखाई देता है और नियंत्रक के अंदर Request.GetRouteData का निरीक्षण करना कोई मान नहीं दिखा रहा है?
एलन मैकडोनाल्ड

3

हां लेकिन आपको अपना मार्ग हैंडलर बनाना होगा।

आमतौर पर मार्ग को डोमेन के बारे में पता नहीं होता है क्योंकि आवेदन को किसी भी डोमेन पर तैनात किया जा सकता है और मार्ग एक या दूसरे तरीके की परवाह नहीं करेगा। लेकिन आपके मामले में आप नियंत्रक को बंद करना चाहते हैं और डोमेन से कार्रवाई करना चाहते हैं, इसलिए आपको एक कस्टम मार्ग बनाना होगा जो डोमेन के बारे में जानता हो।


3

मैंने उपडोमेन रूटिंग के लिए लाइब्रेरी बनाई जिसे आप इस तरह का मार्ग बना सकते हैं। यह वर्तमान में .NET कोर 1.1 और .NET फ्रेमवर्क 4.6.1 के लिए काम कर रहा है, लेकिन निकट भविष्य में अपडेट किया जाएगा। यह है कि यह कैसे काम कर रहा है:
1) Start.up में मानचित्र उपडोमेन मार्ग

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) वह दायित्व आपको URL और फ़ॉर्म जेनरेट करने की भी अनुमति देगा। कोड:

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

उत्पन्न होगा <a href="http://user1.localhost:54575/Home/Index">User home</a> उत्पन्न यूआरएल भी वर्तमान मेजबान स्थान और स्कीमा पर निर्भर करेगा।
तुम भी BeginFormऔर के लिए HTML सहायकों का उपयोग कर सकते हैं UrlHelper। आप यदि आप भी उपयोग कर सकते हैं की तरह नई सुविधा बुलाया टैग सहायकों ( FormTagHelper, AnchorTagHelper)
यही कारण है कि lib ही दस्तावेज़ों अभी तक नहीं है, लेकिन कुछ परीक्षण और नमूने तो परियोजना यह पता लगाने के लिए स्वतंत्र महसूस कर रहे हैं।


2

में 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);
}

1

एक नया रूट हैंडलर परिभाषित करने के बाद , जो 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();
}

मैं आपको ल्यूक सैम्पसन ब्लॉग पर जाने का उल्लेख करता हूं


1

यदि आप प्रत्येक किरायेदार के लिए विभिन्न डोमेन / उप-डोमेन के साथ अपने प्रोजेक्ट में मल्टीटेनेन्सी की क्षमताएँ देख रहे हैं, तो आपको SaasKit पर एक नज़र रखना चाहिए:

https://github.com/saaskit/saaskit

कोड के उदाहरण यहां देखे जा सकते हैं: http://benfoster.io/blog/saaskit-multi-tenancy-made-easy

ASP.NET कोर का उपयोग करते हुए कुछ उदाहरण: http://andrewlock.net/forking-the-pipeline-adding-tenant-specific-files-with-saaskit-in-asp-net-core/

संपादित करें: यदि आप अपने ASP.NET कोर प्रोजेक्ट में SaasKit का उपयोग नहीं करना चाहते हैं तो आप MVC6 के लिए डोमेन रूटिंग के Maarten के कार्यान्वयन पर एक नज़र डाल सकते हैं: https://blog.maartenballiauw.be/post/2015/02/17/domain -routing और हल करने वर्तमान-टेनेंट-साथ-aspnet-MVC-6-aspnet-5.html

हालांकि उन Gists को बनाए नहीं रखा गया है और ASP.NET कोर की नवीनतम रिलीज के साथ काम करने के लिए इसे ट्वीक करने की आवश्यकता है।

कोड का सीधा लिंक: https://gist.github.com/maartenba/77ca6f9cfef50efa96ec#file-domaintemplateroutebuilderextensions-cs


मल्टीटेनेंसी की तलाश नहीं है - लेकिन टिप के लिए धन्यवाद!
Dan Esparza

0

कुछ महीने पहले मैंने एक विशेषता विकसित की है जो विशिष्ट डोमेन के तरीकों या नियंत्रकों को प्रतिबंधित करती है।

इसका उपयोग करना काफी आसान है:

[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(){}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.