Как обработать запрос маршрутизации "john.myexample.com" в ASP.NET Core
Предположим, что URL моего приложения myexample.com
, myexample.com имеет пользователя john
у него есть общедоступная ссылка на профиль john.myexample.com
как обрабатывать такие типы запросов в приложении ASP.NET Core и отображать на UserController
который имеет действие Profile
принимает username
в качестве аргумента и returns
Профиль Джона.
routes.MapRoute(
name: "user_profile",
template: "{controller=User}/{action=Profile}/{username}");
1 ответ
Встроенная маршрутизация ASP.NET Core не предоставляет шаблонов для поддоменов запросов. Вот почему вам нужно реализовать собственный роутер для такого сценария.
Реализация будет довольно простой. Вы должны проанализировать имя хоста входящего запроса, чтобы проверить, является ли он субдоменом профиля. Если это так, вы указываете контроллер, действие и имя пользователя в данных маршрута.
Вот рабочий образец:
Реализация роутера:
public class SubdomainRouter : IRouter
{
private readonly Regex hostRegex = new Regex(@"^(.+?)\.(.+)$", RegexOptions.Compiled);
private readonly IRouter defaultRouter;
private readonly string domain;
private readonly string controllerName;
private readonly string actionName;
public SubdomainRouter(IRouter defaultRouter, string domain, string controllerName, string actionName)
{
this.defaultRouter = defaultRouter;
this.domain = domain;
this.controllerName = controllerName;
this.actionName = actionName;
}
public async Task RouteAsync(RouteContext context)
{
var request = context.HttpContext.Request;
var hostname = request.Host.Host;
var match = hostRegex.Match(hostname);
if (match.Success && String.Equals(match.Groups[2].Value, domain, StringComparison.OrdinalIgnoreCase))
{
var routeData = new RouteData();
routeData.Values["controller"] = controllerName;
routeData.Values["action"] = actionName;
routeData.Values["username"] = match.Groups[1].Value;
context.RouteData = routeData;
await defaultRouter.RouteAsync(context);
}
}
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
return defaultRouter.GetVirtualPath(context);
}
}
Регистрация в Startup.Configure():
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMvc(routes =>
{
routes.Routes.Add(new SubdomainRouter(routes.DefaultHandler, "myexample.com", "User", "Profile"));
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
Образец контроллера:
public class UserController : Controller
{
[HttpGet]
public IActionResult Profile(string username)
{
return Ok();
}
}
ОБНОВЛЕНИЕ (использование маршрута для localhost в среде разработки)
У вас есть два варианта использования такого маршрута для localhost в среде разработки:
Первый полностью эмулирует URL субдоменов, как в производственной среде. Чтобы это работало, вы должны настроить свой файл hosts так, чтобы
john.myexample.com
указать на127.0.0.1
и заставьте ваше основное приложение ASP.NET принимать запросы на такой хост. В этом случае вам не нужно никаких дополнительных настроек в маршрутизации, так как запросы будут иметь те же URL-адреса, что и в производственном процессе (только порт добавлен): http://john.myexample.com:12345/.Если вы хотите сохранить простоту и использовать обычные URL-адреса разработки, указывающие на localhost, вам следует обойти описанное
SubdomainRouter
(потому что он анализирует субдомен, который не будет работать дляlocalhost
) и использовать обычную маршрутизацию ASP.NET Core. Вот настроенная конфигурация маршрутизации для этого случая:app.UseMvc(routes => { if (env.IsDevelopment()) { routes.MapRoute( name: "user-profile", template: "profiles/{username}", defaults: new { controller = "User", action = "Profile" }); } else { routes.Routes.Add(new SubdomainRouter(routes.DefaultHandler, "myexample.com", "User", "Profile")); } routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });
Теперь, если вы отправляете запрос на URL вроде
http://localhost:12345/profiles/john
,UserController.Profile
действие будет вызвано с правильным именем пользователя.