Aspnetcore: Allow routing to areas by hostname

Created on 7 Mar 2019  路  8Comments  路  Source: dotnet/aspnetcore

I'm trying to build a Razor Pages application using two areas: ProductSite1 and ProductSite2.

My folder structure is (simplified):

/wwwroot
/Areas
    /ProductSite1
        /Pages
            Index.cshtml
    /ProductSite2
        /Pages
            Index.cshtml

I can access these areas using https://example.com/ProductSite1 and https://example.com/ProductSite2.

That's fine, but I want that these areas are directly accessible as https://product1.com and https://product2.com using two different domains and without the sub path (/ProductSite1).

After playing around with the router and searching on the internet, I just cannot find any way to do this using razor pages. There are multiple examples about how to implement something like that with the regular MVC, but the routing in Razor Pages seems to work different.

Is there a way to achieve this functionallity using MVC routing or Razor Pages conventions? If not, what do you think about implementing a feature to enable this?

Edit: There is this very new Domain Routing Policy sample: https://github.com/aspnet/samples/tree/master/samples/aspnetcore/mvc/domain
Might be useful to integrate this into razor pages? Something like @domain? And how can one use this for the whole area?

area-mvc question

All 8 comments

Does anyone have an idea for how to do this using Razor Pages?
I can't imagine that such a common use case isn't possible.

Thanks for contacting us, @MarcusWichelmann.
@rynowak can you please take a look at this? Thanks!

This will be possible in 3.0 - preview 6

app.UseEndpoints(endpoints =>
{
    endpoints.MapAreaControllerRoute(
                    areaName: "us",
                    name: "us",
                    pattern: "{controller=Home}/{action=Index}/{id?}").RequireHost("us.example.com");
});

@rynowak Your sample targets regular MVC, right? How would this look like when I'm using Razor Pages only?
I can't think of any action in this case.

Ah, you're right. This can be done for pages as well, I'll write up a sample.

Here's a sample doing something similar for pages:

```C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.HostFiltering;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace WebApplication6
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
        });

        services.Configure<HostFilteringOptions>(options =>
        {
            options.AllowedHosts.Add("localhost");
            options.AllowedHosts.Add("*.example.com");
        });

        services.AddRazorPages(options =>
        {
            options.Conventions.Add(new PageAreaToHostnameConvention());
        })
        .AddNewtonsoftJson();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseCookiePolicy();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }
}

internal class PageAreaToHostnameConvention : IPageRouteModelConvention
{
    public void Apply(PageRouteModel model)
    {
        if (model.AreaName != null)
        {
            for (var i = 0; i < model.Selectors.Count; i++)
            {
                var selector = model.Selectors[i];
                selector.AttributeRouteModel.Template = selector.AttributeRouteModel.Template.Substring($"/{model.AreaName}".Length);
                selector.EndpointMetadata.Add(new HostAttribute($"{model.AreaName}.example.com"));
            }
        }
    }
}

}
```

Aah, thank you very much. This is helpful.
I'll test this. :+1:

Thank you for contacting us. Due to no activity on this issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MaximRouiller picture MaximRouiller  路  338Comments

moodya picture moodya  路  153Comments

natemcmaster picture natemcmaster  路  213Comments

rmarinho picture rmarinho  路  78Comments

davidfowl picture davidfowl  路  126Comments