Reputation: 4336
Currently, I have a Desktop application that has some of its views available to Mobile. I added the ability to switch between Desktop and Mobile versions. However, if the user is on a page that does not have a mobile version and switches to Mobile, a bunch of bad things happen... Is there some way to tell MVC4 to go to a "Sorry, this isn't implemented on Mobile yet" page if a mobile version of the current view does not exist?
Thanks!
Upvotes: 1
Views: 255
Reputation: 4336
This is what I ended up doing. I created a HasMobileVersion attribute to decorate all View methods that have a corresponding mobile version. Instead of showing a "sorry" page, I just redirect the user to the root URL (mobile version must exist there). Here is the code for it:
/// <summary>
/// This attribute specifies which views have Mobile versions available.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class HasMobileVersionAttribute : ActionFilterAttribute
{
#region << Constructors >>
/// <summary>
/// Default constructor.
/// </summary>
public HasMobileVersionAttribute()
{
// Nothing to do
}
#endregion
#region << Overridden Methods >>
/// <summary>
/// Allows a View to switch between mobile and desktop versions, ensuring that if a page does not have a mobile version that
/// it sends the user to the root page.
/// </summary>
/// <param name="ac">Request data.</param>
public override void OnActionExecuting(ActionExecutingContext ac)
{
ac.Controller.ViewBag.HasMobileVersion = true;
}
#endregion
}
There is a link that we declare (well, icon) that allows the user to switch between Mobile and Desktop. This link will check for HasMobileVersion == true from the ViewBag. If it is, it will use the current URL as the return URL once the user is in Mobile mode. If this does not exist, then we force the return URL the Mobile link will use to be the root of the site "/". You have to go out of your way to decorate all the Views that have Mobile pages, but it works nicely.
EDIT:
To switch between Mobile/Desktop, we have a ViewSwitcher controller. If you are in the _Layout, obviously you will switch to the Mobile version. If you are in _Layout.Mobile, you would go to desktop. The attribute is only used to determine if the current page has a Mobile version available for viewing. On the Mobile side, the desktop version is always present (otherwise, you'd have to make a HasDesktopVersion attribute, too). Here is that code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.WebPages;
using System.Web.Mvc;
public class ViewSwitcherController : Controller
{
#region << Views >>
/// <summary>
/// Allows the user to swicth between mobile and desktop versions of the site.
/// </summary>
/// <param name="mobile">True if the user should view the mobile version; false if the user should view the desktop version.</param>
/// <param name="returnUrl">Original URL.</param>
/// <returns>RedirectResult to original URL.</returns>
public RedirectResult SwitchView(bool mobile, string returnUrl)
{
if (Request.Browser.IsMobileDevice == mobile)
HttpContext.ClearOverriddenBrowser();
else
HttpContext.SetOverriddenBrowser(mobile ? BrowserOverride.Mobile : BrowserOverride.Desktop);
return Redirect(returnUrl);
}
#endregion
}
Here is the Razor for the URL to get the talked about result:
@Url.Action("SwitchView", "ViewSwitcher" , new { mobile = true, returnUrl = ViewBag.HasMobileVersion != null && ViewBag.HasMobileVersion ? Request.Url.PathAndQuery : "/" })
On the mobile side, mobile would = false.
Upvotes: 1