【问题标题】:How to handle routing request "john.myexample.com" in ASP.NET Core如何在 ASP.NET Core 中处理路由请求“john.myexample.com”
【发布时间】:2018-03-23 13:12:37
【问题描述】:

假设我的应用程序 URL 是 myexample.com,myexample.com 有用户 john 他有一个公共配置文件链接 john.myexample.com 如何在 ASP.NET Core 应用程序中处理此类请求并映射到 UserController has action Profileusername 作为参数,returns Johns 个人资料。

routes.MapRoute(
                name: "user_profile",
                template: "{controller=User}/{action=Profile}/{username}");

【问题讨论】:

    标签: c# asp.net-core asp.net-core-routing


    【解决方案1】:

    内置ASP.NET Core Routing 不提供请求子域的任何模板。这就是为什么你需要实现自定义路由器来覆盖这种情况。

    实现将非常简单。您应该解析传入请求的主机名以检查它是否是配置文件子域。如果是这样,您在路由数据中填写控制器、操作和用户名。

    这是一个工作示例:

    路由器实现:

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

    Sample Project on GitHub

    更新(在开发环境中使用 localhost 的路由)

    您有两种选择在开发环境中为 localhost 使用此类路由:

    1. 第一个完全模拟生产环境中的子域 URL。为了让它工作,你应该配置你的主机文件,使john.myexample.com 指向127.0.0.1,并使你的 ASP.NET Core 应用程序接受对此类主机的请求。在这种情况下,您不需要对路由进行任何额外的调整,因为请求将具有与生产中相同的 URL(只是添加了端口):http://john.myexample.com:12345/

    2. 如果您想保持简单并使用指向 localhost 的常用开发 URL,则应绕过所描述的 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?}");
      });
      

      现在,如果您向 http://localhost:12345/profiles/john 之类的 URL 发送请求,则将使用正确的用户名调用 UserController.Profile 操作。

    【讨论】:

    • 如何在开发环境中使用localhost:xxx拦截子域请求。
    • 我正在使用SubdomainRoute 类和我的域名username.appname.azurewebsites.net/,它无法访问用户页面。
    • 具体的问题是什么?路由器不命中或不从域名解析用户?
    • 我认为路由没有命中,因为我无法获得状态码。我正在incognitoclone.azurewebsites.net 运行我的实时应用程序,您可以查看。
    • 问题在于子域的 DNS。尝试 ping someuser.incognitoclone.azurewebsites.net,您将看到无法解析此主机。所以 request 甚至没有丰富你的 web 应用程序。您应该配置 DNS,以便将 *.incognitoclone.azurewebsites.net 解析为与 incognitoclone.azurewebsites.net 相同的 IP 地址。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    • 2014-04-02
    • 2021-12-18
    • 2012-02-16
    • 1970-01-01
    相关资源
    最近更新 更多