C# 如何将所有路由复制为一个子目录
要创建一个站点的移动版本,我希望重用我的控制器、一些视图等,但要创建一个移动版本的子目录。因此,您可以使用如下URL: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()等,默认情况下,我可以使用移动版或桌面版,而无需指定此选项,但我可以强制使用其中一个选项
/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时