Reputation: 8639
I have been working on a mobile version of my site's main page using this article: http://www.hanselman.com/blog/MakingASwitchableDesktopAndMobileSiteWithASPNETMVC4AndJQueryMobile.aspx as guide.
I have two controllers: HomeController and EventController
HomeController has a Index view and EventController has a Detail view
I managed to create a Index.mobile.cshtml view that uses _Layout.mobile.cshtml correctly. Now when a user visits mysite.com/Home/Index on her phone it shows the mobile version correctly.
Now, I would have expected that if the same user visits mysite.com/Event/Detail/123, the default "Desktop" view would show (I DO NOT have a Detail.mobile.cshtml view).
The problem is that the Detail.cshtml view is indeed invoked, but it tries to use the _Layout.mobile.cshtml layout, making the page look awful.
Is there a way to achieve this (just rendering the desktop view with the desktop layout for the ones that I haven't implemented on mobile)?
Thanks!
Upvotes: 4
Views: 3426
Reputation: 1715
Add the following line to the end of your _ViewStart.cshtml file:
DisplayModeProvider.Instance.RequireConsistentDisplayMode = true;
This will stop the application from showing non-mobile views within your mobile layout and vice-versa.
Upvotes: 3
Reputation: 6741
The esiest solution would be to override Layout on Detail.cshtml explicitly using _Layout.cshtml:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
If you want more generic solution, you may try the following:
Create custom DisplayMode:
public class MobileDisplayMode : IDisplayMode
{
private bool _mobileViewWasUsed = false;
public override DisplayInfo GetDisplayInfo(HttpContextBase httpContext, string virtualPath, Func<string, bool> virtualPathExists)
{
string filePath = this.TransformPath(virtualPath, this._suffix);
if (filePath != null && virtualPathExists(filePath))
{
if (!_mobileViewWasUsed)
{
if (virtualPath.IndexOf("layout", StringComparison.InvariantCultureIgnoreCase) != -1)
return (DisplayInfo) null;
_mobileViewWasUsed = true;
}
return new DisplayInfo(filePath, (IDisplayMode) this);
}
else
return (DisplayInfo) null;
}
}
Add it in global.asax:
DisplayModeProvider.Instance.Modes.Insert(0, new MobileDisplayMode("mobile"));
Unfortunately, have no chance to test it while it's based on some unapproved assumptions (like creation of DisplayMode per request and others). Anyways, if you are interested and have a chance to test it, it would be wonderful.
Upvotes: 0
Reputation: 18954
I didn't used this NUGET Pakage before, but Note that it mentioned :
By default it will let you switch back and forth between Desktop and Mobile but only on mobile devices. Why? Check out the first line of code: And code checks the Mobile Device first as follow:
@if (Request.Browser.IsMobileDevice && Request.HttpMethod == "GET")
{
<div class="view-switcher ui-bar-a">
@if (ViewContext.HttpContext.GetOverriddenBrowser().IsMobileDevice)
{
@: Displaying mobile view
@Html.ActionLink("Desktop view", "SwitchView", "ViewSwitcher", new { mobile = false, returnUrl = Request.Url.PathAndQuery }, new { rel = "external" })
}
else
{
@: Displaying desktop view
@Html.ActionLink("Mobile view", "SwitchView", "ViewSwitcher", new { mobile = true, returnUrl = Request.Url.PathAndQuery }, new { rel = "external" })
}
</div>
}
According to MSDN :
In general, we recommend that you avoid having logic in your views. It can be difficult to discover and even more difficult to test. Instead, logic in views should be moved into view models or controller actions.
Problem Solving: Change default logic based on your need, Perhaps by Tracing Views (Break Points work on Views too) to meet your purpose.
You need to see This MSDN Topic to be aware in conjunction of MVC and named Package too. Understanding what happens in Action can solve your problem.
Upvotes: 1
Reputation: 1609
Note it appears that you can solve this problem on a per view basis by placing this line of code in the Controller Action.
HttpContext.SetOverriddenBrowser(BrowserOverride.Desktop);
However, what I'd really like is a solution that basically says if the current view doesn't have the .Mobile in the name/path, don't switch the Layout to a .Mobile version
Upvotes: 1