4

I created Admin Area inside my ASP.NET Core application and updated my routes like that:

app.UseMvc(routes =>
{
    routes.MapRoute(name: "areaRoute",
    template: "{area:exists}/{controller=Home}/{action=Index}");

    routes.MapRoute(
      name: "default",
      template: "{controller=Home}/{action=Index}");
});

I would like to implement subdomain routing inside my application in order to when we type URL admin.mysite.com, I render my Admin area (mysite.com/admin).

I saw many examples for ASP.NET MVC 5, but I have not been able to adapt for ASP.NET Core.

Razvan Dumitru
  • 11,815
  • 5
  • 34
  • 54
rony
  • 121
  • 1
  • 7

5 Answers5

1

Michael Graf has a blog post about it.

Basicly you need a custom router:

public class AreaRouter : MvcRouteHandler, IRouter
{
    public new async Task RouteAsync(RouteContext context)
    {
        string url = context.HttpContext.Request.Headers["HOST"]; 
        var splittedUrl = url.Split('.');

        if (splittedUrl.Length > 0 && splittedUrl[0] == "admin")
        {
            context.RouteData.Values.Add("area", "Admin");
        }

        await base.RouteAsync(context);
    }
}

And then register it.

app.UseMvc(routes =>
{
    routes.DefaultHandler = new AreaRouter();
    routes.MapRoute(name: "areaRoute",
        template: "{controller=Home}/{action=Index}");
});

On the other hand we have the IIS Rewrite module, or even a Middleware

aaron
  • 39,695
  • 6
  • 46
  • 102
Christian Gollhardt
  • 16,510
  • 17
  • 74
  • 111
1

I tried the last solution and did not work for ASP.NET Core 1.1

Microsoft has a nuget package named Rewrite, A middleware where you can rewrite or redirect some requests, but also there is a way to write a custom Rule, where you can capture the subdomain and add it to the request path:

public class RewriteSubdomainRule : IRule
    {
        public void ApplyRule(RewriteContext context)
        {
            var request = context.HttpContext.Request;
            var host = request.Host.Host;
            // Check if the host is subdomain.domain.com or subdomain.localhost for debugging
            if (Regex.IsMatch(host, @"^[A-Za-z\d]+\.(?:[A-Za-z\d]+\.[A-Za-z\d]+|localhost)$"))
            {
                string subdomain = host.Split('.')[0];
                //modifying the request path to let the routing catch the subdomain
                context.HttpContext.Request.Path = "/subdomain/" + subdomain + context.HttpContext.Request.Path;
                context.Result = RuleResult.ContinueRules;
                return;
            }
            context.Result = RuleResult.ContinueRules;
            return;
        }
    }

On Startup.cs

You have to add the middleware to use the custom rewrite rule:

 app.UseRewriter(new RewriteOptions().Add(new RewriteSubdomainRule())); 

And after this lines I define a route that receives the subdomain added on the request path and assign it to the subdomain variable:

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");

        routes.MapRoute(
            name: "subdomain",
            template: "subdomain/{subdomain}/{controller=Home}/{action=Index}/{id?}");
    });

On the controller you can use it like this

public async Task<IActionResult> Index(int? id, string subdomain)
{
}
Sergio López
  • 973
  • 9
  • 16
0

Good solution Sergio was able to create the subdomain routing. Just to add to your solution and to complete the subdomain route to the physical directory.

    public class HomeController : Controller
    {
        public async Task<IActionResult> Index(int? id, string subdomain)
        {
             if (!string.IsNullOrWhiteSpace(subdomain))
             {
                if(subdomain=="admin")
                return View("~/wwwrootadmin/index.cshtml");
             }
             return View("~/wwwroot/index.cshtml");
        }
    }

Then wwwrootadmin has to be created with your files for the subdomain. Remember the order of route order matters inside the app.UseMvc()

0

Today similar question is asked (not duplicate because versions are different).

I can propose the same configuration to you, firstly, you must use nginx on your localserver to redirect or rewrite the url on localserver to specific sub-path, so no need to configure .net application to do redirection just configure the route areas.

Mapping Subdomains to Areas in ASP.Net Core 3

0

I finally got this working in .Net Core 2.1

Created a new router

public class SubdomainAreaRouter : MvcRouteHandler, IRouter
{
    public SubdomainAreaRouter(IActionInvokerFactory actionInvokerFactory, IActionSelector actionSelector, DiagnosticSource diagnosticSource, ILoggerFactory loggerFactory) : base(actionInvokerFactory, actionSelector, diagnosticSource, loggerFactory)
    {
    }

    public SubdomainAreaRouter(IActionInvokerFactory actionInvokerFactory, IActionSelector actionSelector, DiagnosticSource diagnosticSource, ILoggerFactory loggerFactory, IActionContextAccessor actionContextAccessor) : base(actionInvokerFactory, actionSelector, diagnosticSource, loggerFactory, actionContextAccessor)
    {
    }

    public new async Task RouteAsync(RouteContext context)
    {
        string url = context.HttpContext.Request.Headers["HOST"];
        var splittedUrl = url.Split('.');

        if (splittedUrl != null && (splittedUrl.Length > 0 && splittedUrl[0] == "admin"))
        {
            context.RouteData.Values.Add("area", "Admin");
        }

        await base.RouteAsync(context);
    }
}

In Startup.cs, add the following into the ConfigureServices method:

services.AddSingleton<SubdomainAreaRouter>();

In Startup.cs, pass in your new router into the Configure method and update the UseMvc logic to use your new router:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, SubdomainAreaRouter subdomainRouter)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseSession();
    app.UseCookiePolicy();

    app.UseMvc(routes =>
    {
        routes.DefaultHandler = subdomainRouter;
        routes.MapRoute(
            "admin",
            "{area:exists}/{controller=Home}/{action=Index}/{id?}");
        routes.MapRoute(
            "default",
            "{controller=Home}/{action=Index}/{id?}");
    });
}
Ryan Durkin
  • 813
  • 6
  • 17