About Hasmukh patel

My Photo
Harrow, London, United Kingdom
Dot-Net developer with expertise in Web, WPF, Win-form applications. Have worked on Asp.net,mvc , WPF and Win-forms projects in c#.net language having Sql-Server/Oracle as database with service oriented architecture using test driven development. Having complete knowledge of SDLC and have successfully worked and implemented it on projects.

Display device specific views in MVC 3


Display device specific views in MVC 3

In MVC 3, view can be render based in requested device, each request come with browser type string called “User-Agent” string.
Example of user-agent sting as below
Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5
Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5
Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; HTC Vision Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
Mozilla/5.0 (BlackBerry; U; BlackBerry 9850; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.115 Mobile Safari/534.11+
BlackBerry9700/5.0.0.862 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/167
Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)
Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; Zune 4.7)
To override default behaviour of MVC rendering engine, create a class with inherit from RazorViewEngine as below;
    Internal class MobileViewEngine : RazorViewEngine
    {
        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
        {
            ViewEngineResult result = null;
            var request = controllerContext.HttpContext.Request;
 
            if (request.IsSupportedMobileDevice() && HttpExtentions.HasMobileSpecificViews)
            {
                var viewPathAndName = request.GetMobileViewsDirectoryName() + viewName;
 
                result = base.FindView(controllerContext, viewPathAndName, masterName, true);
 
                if (result == null || result.View == null)
                {
                    result = base.FindView(controllerContext, viewPathAndName, masterName, false);
                }
            }
            else
            {
                result = base.FindView(controllerContext, viewName, masterName, useCache);
            }
            return result;
        }
 
        protected override bool FileExists(ControllerContext controllerContext, string virtualPath)
        {
            return base.FileExists(controllerContext, virtualPath);
        }
 
        public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
        {
            return base.FindPartialView(controllerContext, partialViewName, useCache);
        }
    }
Following custom configuration required to identify devices, See post how to create custom settings
  <configSections>
        <!--your other sections-->
      <section name="viewTypeSettings" type="Mvc3Demo.Core.ViewTypeSettings,Mvc3Demo" />  
  </configSections>
 
    <viewTypeSettings>
    <viewTypes>
      <viewType name="Phone" deviceIdentifiers="iPhone,iPod,Droid,Blackberry"></viewType>
      <viewType name="Tablet" deviceIdentifiers="iPad,Playbook,Transformer,Xoom"></viewType>
    </viewTypes>
  </viewTypeSettings>
  
If you request URL is http://youdomain.com/home/ from desktop then Home/index.schtml view will be displayed, if request come from any tablet then Home/Tablet/index.schtml view will be displayed, if request come from any mobile then Home/Mobile/index.schtml view will be displayed.
In the MobileViewEngine, we have used an extension method which is a static class as below
   public static class HttpExtentions
    {
        private static readonly bool ConfigCheck;
 
        private static readonly IEnumerable<DeviceType> MobileDevicesList;
 
        static HttpExtentions()
        {
            var customSettins = ViewTypeSettings.Settings;
 
            MobileDevicesList = customSettins.ViewTypes
                                       .Select(x => new DeviceType
                                           {
                                               ViewType = x.Name,
                                               DeviceIdentifiers = x.DeviceIdentifiers.Split(',')
                                           })
                                       .ToList();
 
            ConfigCheck = MobileDevicesList.Any();
        }
 
        public static bool HasMobileSpecificViews
        {
            get { return ConfigCheck; }
        }
 
        /// <summary>
        /// Used to enable debugging using alternative devices
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static bool IsSupportedMobileDevice(this HttpRequestBase request)
        {
 
            bool isMobile = request.Browser.IsMobileDevice;
            string userAgent = request.UserAgent.ToLowerInvariant();
            
            isMobile = isMobile || MobileDevicesList.Any(x => x.DeviceIdentifiers.Any(userAgent.Contains));
 
            return isMobile;
        }
 
        /// <summary>
        /// Gets the name of the mobile views directory.
        /// </summary>
        /// <value>
        /// The name of the mobile views directory.
        /// </value>
        public static string GetMobileViewsDirectoryName(this HttpRequestBase request)
        {
            var directoryName = string.Empty;
            string userAgent = request.UserAgent.ToLowerInvariant();
            var deviceType = MobileDevicesList
                .First(x => x.DeviceIdentifiers.Any(userAgent.Contains));
 
            if (deviceType != null)
            {
                directoryName = deviceType.ViewType;
            }
 
            return !string.IsNullOrEmpty(directoryName) ? String.Format("{0}/", directoryName) : string.Empty;
        }
 
        public static string GetUserIpAddress(this HttpRequestBase request)
        {
            return request.UserHostAddress;
            //return request.ServerVariables["REMOTE_ADDR"];
        }
 
        public static string GetHostName(this HttpRequestBase request)
        {
            IPHostEntry ip = Dns.GetHostEntry(request.UserHostName);
            return ip.HostName;
        }
 
    }
 
    internal class DeviceType
    {
        public string ViewType { getset; }
        public string[] DeviceIdentifiers { getset; }
    }
   



No comments :