首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通配符子域路由ASP

通配符子域路由ASP
EN

Stack Overflow用户
提问于 2013-06-30 16:30:27
回答 3查看 3.4K关注 0票数 3

我正在寻找一种将通配符子域路由到ASP.MVC 4中控制器的方法。

所以就像这样:

CompanyName.mydomain.com

需要将其转化为:

mydomain.com/CompanyName

我找不到任何关于怎么做的信息,我被困住了。这是IIS问题还是ASP.MVC路由问题?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-08 16:57:22

因此,相当一段时间后,我自己在应用程序级别上解决了这个问题。IIS重写不能工作,ASP.MVC没有匹配正确的路径,它将404退出。

最后,对我有用的解决方案是让我自己实现路由类,它搜索主机名寻找参数,并将其映射为路由参数。它现在运行得完美无缺,而且定制的实现非常简单。在这个过程中,我爱上了灵活的ASP.MVC给您带来的灵活性:)

因此,自定义路由需要两个重写,一个用于匹配传入路由的方法"GetRouteData“,另一个用于写入传出路由的"GetVirtualPath”。

以下是整个自定义路由类:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace System.Web.Routing
{
public class WildcardRoute : Route
{


    public WildcardRoute(string url, IRouteHandler handler)
        : base(url, handler)
    { 

    }
    public WildcardRoute(string url, RouteValueDictionary defaults, IRouteHandler handler)
        : base(url, defaults, handler)
    {
    }

    public WildcardRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler handler)
        : base(url, defaults, constraints, handler)
    { 
    }

    public WildcardRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler handler)
        : base(url, defaults, constraints, dataTokens, handler)
    {

    }


    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        // save the original path before we edit it
        var orignalPath = HttpContext.Current.Request.Path;

        //split the hostname
        var split = HttpContext.Current.Request.Url.Host.Split('.');
        // fire only if there is more than 2 items in the split (company.mydomain.com) and if the first one is not www
        if (split.Count() > 2 && split[0].ToLower() != "www")
        {
            var split2 = HttpContext.Current.Request.Path.Split('/'); // split everything  after the hostname into segments
            string newPath = "/" + split[0]; // take the company from company.mydomain.com and rewrite it to mydomain.com/company
            foreach (var item in split2) // add all the other segments that come after mydomain.com/company 
            {                            // end result might be for example - mydomain.com/company/Home/Index 
                newPath = newPath + "/" + item;
            }
            httpContext.RewritePath(newPath); // rewrite the path into the newone
        }

        RouteData data = base.GetRouteData(httpContext); // match the route with the new path
        if (data == null) // if there is no match in this route write the path back to the original one
        {
            httpContext.RewritePath(orignalPath);
        }
        return data;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {

        var data = base.GetVirtualPath(requestContext, values); // do the original url write
        var split = requestContext.HttpContext.Request.Url.Host.Split('.'); // split the host by '.'

        var item = requestContext.RouteData.Values.FirstOrDefault(x => x.Key == "PermalinkTitle"); // the PermalinkTitle is the name of the "company" route value in mydomain.com/company in my implementation
        if (split.Count() > 0 && split[0].ToLower().Contains(item.Value.ToString().ToLower())) // fire only if the hostname contains the "company" route value
        {
            data.VirtualPath = data.VirtualPath.Replace(item.Value.ToString(), "");
            if (data.VirtualPath.StartsWith("/"))
                data.VirtualPath = data.VirtualPath.Substring(1);
            // this code removes the company part from the path so we dont get company.mydomain.com/company/controller/action rather we just get company.mydomain.com/controller/action
        }
        return data;
    }

}
}

这个实现非常灵活,它将与所有这些路线-- "company.mydomain.com“、"mydomain.com/company”和"www.mydomain.com/company“一起工作。

在创建自定义路由类之后,需要使用映射自定义路由类型的Map方法扩展RouteCollection,如果使用区域,还需要扩展AreaRegistrationContext,因为区域路由映射贯穿其中。以下是整个实现:

代码语言:javascript
复制
using System;
using System.Web.Mvc;
using System.Web.Routing;

namespace System.Web.Routing
{
    public static class WildcardRoutesExtension
    {

        public static WildcardRoute MapWildcardRoute(this RouteCollection routes, string name, string url, object defaults)
        {

            WildcardRoute route = new WildcardRoute(
                url,
                new RouteValueDictionary(defaults),
                new MvcRouteHandler());
            routes.Add(name, route);

            return route;
        }

        public static WildcardRoute MapWildcardRoute(this AreaRegistrationContext context, string name, string url, object defaults)
        {
                        WildcardRoute route = new WildcardRoute(
                url,
                new RouteValueDictionary(defaults),
                new RouteValueDictionary(new {}),
                new RouteValueDictionary(new {Area = context.AreaName }),
                new MvcRouteHandler());

            context.Routes.Add(name, route);
            return route;
        }


        public static WildcardRoute MapWildcardRoute(this AreaRegistrationContext context, string name, string url, object defaults, object constraints)
        {
            WildcardRoute route = new WildcardRoute(
                url,
                new RouteValueDictionary(defaults),
                new RouteValueDictionary(constraints),
                new RouteValueDictionary(new {Area = context.AreaName }),
                new MvcRouteHandler());

            context.Routes.Add(name, route);
            return route; 
        }

        public static WildcardRoute MapWildcardRoute(this RouteCollection routes, string name, string url, object defaults, object constraints)
        {
            WildcardRoute route = new WildcardRoute(
                url,
                new RouteValueDictionary(defaults),
                new RouteValueDictionary(constraints),

                new MvcRouteHandler());
            routes.Add(name, route);
            return route;
        }
    }
}

当您拥有了所有这些之后,现在只需要为RouteConfig类中的常规路由映射像这样的自定义路由:

代码语言:javascript
复制
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {


                 // rest of your routes

                routes.MapWildcardRoute(
                          name: "Default",
                          url: "{PermalinkTitle}/{controller}/{action}",
                          defaults: new {  }
                 );

              //Rest of your routes
        } 

对于AreaRegistration类中的区域,也是这样:

代码语言:javascript
复制
    public override void RegisterArea(AreaRegistrationContext context)
    {

        context.MapWildcardRoute(
            "MyArea_default",
            "{PermalinkTitle}/MyArea/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional }
        );

    }
票数 5
EN

Stack Overflow用户

发布于 2013-06-30 16:47:14

尝试将此规则用于IIS:

代码语言:javascript
复制
<rule name="Rule1" stopProcessing="true">
    <match url=".*" />
    <conditions>
        <add input="{HTTP_HOST}" pattern="^(?!www)(.*)\.mydomain\.com$" />
    </conditions>
    <action type="Rewrite" url="http://mydomain.com/{C:1}/{R:0}" />
</rule> 
票数 0
EN

Stack Overflow用户

发布于 2013-06-30 16:47:37

我想说的是,这在很大程度上与两者有关。在大多数情况下,子域实际上是域服务器上根目录下的文件夹。(也就是说,CompanyName.mydomain.com通常是mydomain.com/CompanyName文件夹(就像您编写的那样))。

然后,它将取决于您的mvc路由设置的路线,因为你想要。对于mvc路由,我使用这个方向:控制器/动作。

IIS将作为子域的根将您导入到CompanyName文件夹中。您的mvc只需要在该文件夹的控制器文件夹中有一个主控制器,就可以使用您的url定义在其中导航。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17392480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档