2

I'm trying to make my Action return a different view for different platforms, respecting the routing config. If I create a custom ViewResult, will I override the FindView method? And if so, how can I modify the View that is automatically found?

For example: HomeController.About action would display View\Home\About.cshtml on computer, View\Home\AboutTablet.cshtml on a tablet, and View\Home\AboutMobile.cshtml on a cell phone

Mike Cole
  • 14,474
  • 28
  • 114
  • 194

5 Answers5

2

There's a NuGet for you: MobileViewEngines. ScottHa covered it in a blog post. It's spec compatible with ASP.NET MVC 4 where you can get rid of it easily because this functionality is built-in.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • I'm not sure it's going to work right out of the box, but the source code should be enough to get me going. Thanks! – Mike Cole Jul 30 '12 at 16:19
2

You could define an Actionfilter like this:

public class SetDeviceDependantView : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        // Only works on ViewResults...
        ViewResultBase viewResult = filterContext.Result as ViewResultBase;
        if (viewResult != null)
        {
            if (filterContext == null)
                throw new ArgumentNullException("context");

            // Default the viewname to the action name
            if (String.IsNullOrEmpty(viewResult.ViewName))
                viewResult.ViewName = filterContext.RouteData.GetRequiredString("action");

            // Add suffix according to device type
            if (IsTablet(filterContext.HttpContext))
                viewResult.ViewName += "Tablet";
            else if (IsMobile(filterContext.HttpContext))
                viewResult.ViewName += "Mobile";
        }
        base.OnResultExecuting(filterContext);
    }

    private static bool IsMobile(HttpContextBase httpContext)
    {
        return httpContext.Request.Browser.IsMobileDevice;
    }

    private static bool IsTablet(HttpContextBase httpContext)
    {
        // this requires the 51degrees "Device Data" package: http://51degrees.mobi/Products/DeviceData/PropertyDictionary.aspx
        var isTablet = httpContext.Request.Browser["IsTablet"];
        return isTablet != null && isTablet.Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase);
    }
}

Then you can either annotate the required Actions / Controllers like this:

[SetDeviceDependantView]
public ActionResult About()
{
    return View();
}

Or set it globally in the global.asax:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new SetDeviceDependantView());
}

Note, that I'm relying here on the 51degrees library to detect the tablet, you could consider using a different technique. However, that's a different topic.

Sam7
  • 3,382
  • 2
  • 34
  • 57
0

If you want to do this pre-MVC4, check out this blog post from Christopher Bennage

http://dev.bennage.com/blog/2012/04/27/render-action/

I was specially interested in the ContentTypeAwareResult class, which looks like it might be what you are looking for.

https://github.com/liike/reference-application/blob/master/MileageStats.Web/ContentTypeAwareResult.cs

0

You'll have to create your own ViewEngine (probably deriving it from the one you're using) and override FindView and FindPartialView. You can provide fallbacks (i.e., use generic view if no tablet one is found).

Most trouble will be in defining the criteria to differentiate between different "modes".

Sergei Rogovtcev
  • 5,804
  • 2
  • 22
  • 35
0

Building a custom ViewEngine is a preferred approach in MVC3 for this requirement. For you info - MVC4 support this feature out of the box.

For more information about device specific view, a similar answer is posted here on StackOverflow itself https://stackoverflow.com/a/1387555/125651

Community
  • 1
  • 1
Rajeesh
  • 4,377
  • 4
  • 26
  • 29