ASP.NET MVC separate mobile views using same contr

2019-04-06 13:37发布

问题:

I am working on a new project using ASP.NET MVC 3 w/ Razor and developing 2 different views of the same site, a full version and a mobile version. What are the best practices/approaches for using the same controllers, but displaying different views based on the user agent? Should I handle this in the controllers? It seems that it would be cumbersome, redundant, error prone to have if statements in every controller action checking the user agent and then returning a different view depending on their device.

回答1:

This can now be accomplished using a built-in feature of ASP.NET MVC (from version 4 onwards) called "DisplayModes"

By default, ASP.NET MVC ships with two display modes built-in. There's the default display mode, which renders your "standard" views as it always has done, and there's also a generic "mobile" display mode.

This works by detecting whether the client device is a mobile browser or not (which itself is determined by sniffing the User-Agent string of the client device so not 100% reliable). If the device is determined to be a mobile device, then the actual MVC view that is sent to the client is overridden and an alternative view is rendered and sent instead. In the case of the included mobile display mode, it's configured to look for a View with the suffix of .mobile.cshtml rather than .cshtml (As shown in the screenshot below)

This allows you to design entirely different views which will be sent to a mobile vs a non-mobile device without requiring any changes to your controller logic, so you don't need to include any conditional logic in there.

If you require more granularity of control over the exact view that's sent to the client device, the entire Display Modes functionality is configurable and extensible. You can define your own display modes (usually performed in Application Startup) that can be specific to a given browser, a given device or any arbitrary definition that you wish. All are based upon the user agent string coming from the client device.

Consider the following snippet of code below that shows adding 3 additional custom display modes for Windows Phone, iPhone and Android in the Application Start method:

protected void Application_Start()
{   
    DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("WP")
    {
        ContextCondition = (context => context.GetOverriddenUserAgent().
            IndexOf("Windows Phone OS",StringComparison.OrdinalIgnoreCase) >= 0)
    });

    DisplayModeProvider.Instance.Modes.Insert(1, new DefaultDisplayMode("iPhone")
    {
        ContextCondition = (context => context.GetOverriddenUserAgent().
            IndexOf("iPhone", StringComparison.OrdinalIgnoreCase) >= 0)
    });

    DisplayModeProvider.Instance.Modes.Insert(2, new DefaultDisplayMode("Android")
    {
        ContextCondition = (context => context.GetOverriddenUserAgent().
            IndexOf("Android", StringComparison.OrdinalIgnoreCase) >= 0)
    });
}

Each display mode is given an ID and a string to match from the user agent string to determine if this display mode is to be used. If it is, the DisplayModeProvider will look for a View with the same string suffix. (i.e. For the iPhone display mode above, we expect to find the string "iPhone" anywhere in the user agent string, and if it exists, we use this display mode which renders views with the iphone.cshtml suffix rather than a .cshtml suffix.

You can read more about this functionality here: http://www.asp.net/mvc/overview/older-versions/aspnet-mvc-4-mobile-features specifically in the sections headed "Overriding Views, Layouts, and Partial Views" and "Browser-Specific Views".