要创建网站的移动版本,我想重用我的控制器,一些视图等,但创建看起来像移动版本的子目录。所以你可以有以下网址:
/Controller/Action/Id
/mobile/Controller/Action/Id
etc.
理想情况下,这些路径将映射到同一个控制器,然后我可以查看路径数据中的某个位置以查看该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
前缀并使其正常工作?或者是否有一种完全不同的方式可以解决整个问题,这会更有意义呢?
希望这不是太模糊,任何建议都会非常感激。
答案 0 :(得分:2)
对于传入请求,这很简单,你只需要两组ruotes,一组所有路由都以mobile/
开头。问题在于URL生成,为了解决这个问题,您需要实现仅在URL生成上执行的IRouteConstraint,并检查(当前HTTP请求的)当前路由是否以mobile/
开头,并将其与正在测试的路线进行比较。我在MvcCodeRouting库中使用了类似的方法。
答案 1 :(得分:1)
你见过这个:http://51degrees.codeplex.com/
非常适合在同一代码库中使用移动/浏览器
答案 2 :(得分:1)
我已经在用于“常见”浏览器的asp.net mvc + jquery和用于移动浏览器的asp.net mvc + jqueryMobile的web项目中执行此操作。我不需要在我的全局asax中创建新路由。这些是移动重定向的漂亮网站:
Mobile enabled web apps with ASP.NET MVC 3 and jQuery Mobile(如果你使用mvc3要容易得多) Walkthrough: Creating an ASP.NET MVC Areas Application Using Multiple Projects A First Look at ASP.NET MVC 2
所以,在我的解决方案中,我使用了移动重定向属性,我在控制器的操作中标记了我想要检查重定向。我在你的解决方案中看到你“问”用户点击正确的链接,取决于用户并且不好(也许我没有抓住你的意图)。但是,在此解决方案中,您检查请求中的用户代理,以了解对您的站点执行请求的浏览器:
/// <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
}
因此,在此之后,您唯一需要做的就是标记您想要重定向到不同视图的控制器操作。控制器逻辑可以重构并将其提取为常用方法。
// GET: /MyController/
[MobileRedirectAttribute("MyController","IndexMobile")]
public ActionResult Index(string guid)
希望能提供帮助,询问您是否有任何疑问。
答案 3 :(得分:0)
这不起作用:
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创建的链接会考虑匹配的路由并为其构建链接吗?
我可能错了 - 我实际上没有测试过它。