C# 如何将所有路由复制为一个子目录

C# 如何将所有路由复制为一个子目录,c#,asp.net-mvc,asp.net-mvc-3,razor,C#,Asp.net Mvc,Asp.net Mvc 3,Razor,要创建一个站点的移动版本,我希望重用我的控制器、一些视图等,但要创建一个移动版本的子目录。因此,您可以使用如下URL: /Controller/Action/Id /mobile/Controller/Action/Id etc. 理想情况下,这些路由将映射到同一个控制器,然后我可以查看路由数据中的某个地方,以查看URL是否为移动URL。我可以在视图中使用@Html.ActionLink()等,默认情况下,我可以使用移动版或桌面版,而无需指定此选项,但我可以强制使用其中一个选项

要创建一个站点的移动版本,我希望重用我的控制器、一些视图等,但要创建一个移动版本的子目录。因此,您可以使用如下URL:

       /Controller/Action/Id
/mobile/Controller/Action/Id
etc.
理想情况下,这些路由将映射到同一个控制器,然后我可以查看路由数据中的某个地方,以查看URL是否为移动URL。我可以在视图中使用
@Html.ActionLink()
等,默认情况下,我可以使用移动版或桌面版,而无需指定此选项,但我可以强制使用其中一个选项

我可以通过在每条路线的前面设置一个可选参数来实现类似的功能,例如

routes.MapRoute(
        "Default",
        "{mobile}/{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", id = UrlParameter.Optional, mobile = UrlParameter.Optional },
        new { mobile = "mobile|" }
      );
然后,这将按预期工作:

Takes you to either / or /mobile version depending on where you are currently:
@Html.ActionLink("Current", "Index"); 

/ version
@Html.ActionLink("Desktop", "Index", new { mobile = "" });

/mobile version
@Html.ActionLink("Mobile", "Index", new { mobile = "mobile" });
然而,这似乎是一个非常蹩脚的解决方案,因为我真的不想把它添加到每条路线的前面。有没有更好的方法可以做到这一点,例如在所有路线上添加可选的
/mobile
前缀,并使其正常工作?或者,是否有一种完全不同的方式来处理整个问题,这会更有意义

希望这不是太模糊,任何建议都将不胜感激。

您是否看到以下内容:

非常适合将手机/浏览器放在同一代码库上

您看到了吗:

非常适合将手机/浏览器放在同一个代码库上这不起作用:

routes.MapRoute(
                "Mobile", // Mobile route
                "mobile/{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

routes.MapRoute(
                "Default", // Default route
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );
我相信,当一条路线匹配时,使用ActionLink创建链接时,会考虑匹配的路线并为其构建链接吗

但我可能错了——我还没有实际测试过它。

这会不会不起作用:

routes.MapRoute(
                "Mobile", // Mobile route
                "mobile/{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

routes.MapRoute(
                "Default", // Default route
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );
我相信,当一条路线匹配时,使用ActionLink创建链接时,会考虑匹配的路线并为其构建链接吗


不过我可能错了,我还没有真正测试过它。

我已经在一个针对asp.net mvc+jquery的web项目中为“普通”浏览器和针对移动浏览器的asp.net mvc+jqueryMobile执行过这项操作。我不需要在我的全球asax中创建新路线。此外,这些是一个非常适合移动重定向的网站:

(如果您使用的是mvc3,则更容易)

所以,在我的解决方案中,我使用了一个移动重定向属性,我在控制器的动作中标记了我想要检查重定向的动作。我看到在你的解决方案中,你“要求”用户点击正确的链接,这取决于用户,并不好(也许我没有领会你的意图)。但是,在此解决方案中,您可以检查请求中的用户代理,以了解对您的站点执行请求的浏览器:

/// <summary>
    /// Attribute for Mobile Redirection when the request action comes from a mobile device.
    /// </summary>
    public class MobileRedirectAttribute : AuthorizeAttribute
    {
        private const string defaultMobileController = "Mobile";

        #region Properties

        /// <summary>
        /// Gets or sets the action.
        /// </summary>
        /// <value>The action.</value>
        private string Action { get; set; }

        /// <summary>
        /// Gets or sets the controller.
        /// </summary>
        /// <value>The controller.</value>
        private string Controller { get; set; }

        private UrlHelper _urlHelper;
        /// <summary>
        /// Sets the URL helper.
        /// </summary>
        /// <value>The URL helper.</value>
        internal UrlHelper UrlHelper { set { this._urlHelper = value; } }

        /// <summary>
        /// Gets or sets the last URL redirected.
        /// </summary>
        /// <value>The last URL redirected.</value>
        internal string RedirectedTo { get; private set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is mobile device.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is mobile device; otherwise, <c>false</c>.
        /// </value>
        internal bool IsMobileDevice { get; private set; }

        #endregion

        #region Methods

        /// <summary>
        /// Determines whether the specified controller is mobile.
        /// </summary>
        /// <param name="controller">The controller.</param>
        /// <returns>
        ///     <c>true</c> if the specified controller is mobile; otherwise, <c>false</c>.
        /// </returns>
        private bool IsMobile(Controller controller)
        {
            bool isMobile = controller.Request.Browser.IsMobileDevice;
            string userAgent = controller.Request.UserAgent.ToLower();

            return (isMobile || userAgent.Contains("iphone") || userAgent.Contains("ipod") || userAgent.Contains("blackberry") || userAgent.Contains("mobile")
                             || userAgent.Contains("opera mini") || userAgent.Contains("palm"));
        }

        /// <summary>
        /// Called when [authorization].
        /// </summary>
        /// <param name="filterContext">The filter context.</param>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            Controller controller = filterContext.Controller as Controller;
            this.IsMobileDevice = IsMobile(controller); //test porpouse
            if (this.IsMobileDevice)
            {
                this.RedirectedTo = GetUrlRedirectAction(filterContext.RequestContext);
                filterContext.Result = new RedirectResult(this.RedirectedTo);
            }
        }

        /// <summary>
        /// Gets the URL redirect action.
        /// </summary>
        /// <param name="requestContext">The request context.</param>
        /// <returns></returns>
        private string GetUrlRedirectAction(RequestContext requestContext)
        {
            UrlHelper urlHelper = _urlHelper;
            if (urlHelper == null) //mocking porpouse;
                urlHelper = new UrlHelper(requestContext);

            return urlHelper.Action(this.Action, this.Controller, requestContext.RouteData.Values);
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="MobileRedirectAttribute"/> class.
        /// </summary>
        /// <param name="action">The action.</param>
        public MobileRedirectAttribute(string action)
        {
            this.Action = action;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="MobileRedirectAttribute"/> class.
        /// </summary>
        /// <param name="controller">The controller.</param>
        /// <param name="action">The action.</param>
        public MobileRedirectAttribute(string controller, string action)
        {
            this.Action = action;
            this.Controller = controller;
        }

        #endregion

    }

希望能提供帮助,如果您有任何问题,请询问。

我已经在一个针对asp.net mvc+jquery的web项目中为“常用”浏览器和针对移动浏览器的asp.net mvc+jqueryMobile执行了此操作。我不需要在我的全球asax中创建新路线。此外,这些是一个非常适合移动重定向的网站:

(如果您使用的是mvc3,则更容易)

所以,在我的解决方案中,我使用了一个移动重定向属性,我在控制器的动作中标记了我想要检查重定向的动作。我看到在你的解决方案中,你“要求”用户点击正确的链接,这取决于用户,并不好(也许我没有领会你的意图)。但是,在此解决方案中,您可以检查请求中的用户代理,以了解对您的站点执行请求的浏览器:

/// <summary>
    /// Attribute for Mobile Redirection when the request action comes from a mobile device.
    /// </summary>
    public class MobileRedirectAttribute : AuthorizeAttribute
    {
        private const string defaultMobileController = "Mobile";

        #region Properties

        /// <summary>
        /// Gets or sets the action.
        /// </summary>
        /// <value>The action.</value>
        private string Action { get; set; }

        /// <summary>
        /// Gets or sets the controller.
        /// </summary>
        /// <value>The controller.</value>
        private string Controller { get; set; }

        private UrlHelper _urlHelper;
        /// <summary>
        /// Sets the URL helper.
        /// </summary>
        /// <value>The URL helper.</value>
        internal UrlHelper UrlHelper { set { this._urlHelper = value; } }

        /// <summary>
        /// Gets or sets the last URL redirected.
        /// </summary>
        /// <value>The last URL redirected.</value>
        internal string RedirectedTo { get; private set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is mobile device.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is mobile device; otherwise, <c>false</c>.
        /// </value>
        internal bool IsMobileDevice { get; private set; }

        #endregion

        #region Methods

        /// <summary>
        /// Determines whether the specified controller is mobile.
        /// </summary>
        /// <param name="controller">The controller.</param>
        /// <returns>
        ///     <c>true</c> if the specified controller is mobile; otherwise, <c>false</c>.
        /// </returns>
        private bool IsMobile(Controller controller)
        {
            bool isMobile = controller.Request.Browser.IsMobileDevice;
            string userAgent = controller.Request.UserAgent.ToLower();

            return (isMobile || userAgent.Contains("iphone") || userAgent.Contains("ipod") || userAgent.Contains("blackberry") || userAgent.Contains("mobile")
                             || userAgent.Contains("opera mini") || userAgent.Contains("palm"));
        }

        /// <summary>
        /// Called when [authorization].
        /// </summary>
        /// <param name="filterContext">The filter context.</param>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            Controller controller = filterContext.Controller as Controller;
            this.IsMobileDevice = IsMobile(controller); //test porpouse
            if (this.IsMobileDevice)
            {
                this.RedirectedTo = GetUrlRedirectAction(filterContext.RequestContext);
                filterContext.Result = new RedirectResult(this.RedirectedTo);
            }
        }

        /// <summary>
        /// Gets the URL redirect action.
        /// </summary>
        /// <param name="requestContext">The request context.</param>
        /// <returns></returns>
        private string GetUrlRedirectAction(RequestContext requestContext)
        {
            UrlHelper urlHelper = _urlHelper;
            if (urlHelper == null) //mocking porpouse;
                urlHelper = new UrlHelper(requestContext);

            return urlHelper.Action(this.Action, this.Controller, requestContext.RouteData.Values);
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="MobileRedirectAttribute"/> class.
        /// </summary>
        /// <param name="action">The action.</param>
        public MobileRedirectAttribute(string action)
        {
            this.Action = action;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="MobileRedirectAttribute"/> class.
        /// </summary>
        /// <param name="controller">The controller.</param>
        /// <param name="action">The action.</param>
        public MobileRedirectAttribute(string controller, string action)
        {
            this.Action = action;
            this.Controller = controller;
        }

        #endregion

    }

希望能提供帮助,如果您有任何问题,请询问。

对于传入的请求,您只需要两套ruote,其中一套是所有路由都以
mobile/
开始的。问题在于URL生成,要解决这个问题,您需要实现一个仅针对URL生成的act,并检查当前路由(当前HTTP请求的)是否以
mobile/
开头,并将其与正在测试的路由进行比较。我在库中使用了类似的方法。

对于传入的请求,很容易,您只需要两套ruote,一套是所有路由都以
mobile/
开始的。问题在于URL生成,要解决这个问题,您需要实现一个仅针对URL生成的act,并检查当前路由(当前HTTP请求的)是否以
mobile/
开头,并将其与正在测试的路由进行比较。我在图书馆也使用类似的方法。

谢谢。我尝试了这个方法,但是当您在桌面部分中使用@Html.ActionLink()时,第一个(移动)路由将匹配。此外,如果可能的话,我希望避免这种重复。不,它不会-桌面部分将不匹配移动路由,因为它不包含移动/作为其url的一部分。除非我完全不理解路由是如何工作的,但是我在MVC中为我的一个应用做了很多路由工作。。用于调试路由-非常有效。我指的是反向匹配,当您尝试在给定控制器、操作和参数的情况下创建URL时。在这种情况下,我想你总是会得到第一条路线。谢谢你的链接,看起来真的很有用。我相信你会找到第一条匹配的路线。。将路线添加到global.asax时,在顶部添加最具体的路线,并向下移动到末尾的所有路线。如果它是那样的盲目,只是为第一条路线建造,那么它就不会那么强大。-所以这是第一条匹配的路线。。在桌面的情况下,这将是上面的最后一个。。在手机的情况下,将是第一个。刚刚做了一个快速测试,似乎我错了。。这是匹配的手机/-我会让你知道,一旦我知道它应该是什么。谢谢。我尝试了这个方法,但是当您在桌面部分中使用@Html.ActionLink()时,第一个(移动)路由将匹配。此外,如果可能的话,我希望避免这种重复。不,它不会-桌面部分将不匹配移动路由,因为它不包含移动/作为其url的一部分。除非我完全不理解路由是如何工作的,但是我在MVC中为我的一个应用做了很多路由工作。。用于调试您的路由-非常有效。我指的是反向匹配,当您尝试创建UR时