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.

WPF Observble Extensions



using System;
using System.ComponentModel;
using System.Linq.Expressions;

namespace DemoCode.Shared.Extensions
{
    public static class ObservableExts
    {
        public static IObservable<IObservedChange<TSender, TValue>> ObservableForProperty<TSender, TValue>
            (this TSender This, Expression<Func<TSender, TValue>> property, bool beforeChange = false)
            where TSender : INotifyPropertyChanged
        {
            var observedChange = new ObservedChange<TSender, TValue>(This, property);
            return new Observable<TSender, TValue>(observedChange);
        }

        public static IDisposable Subscribe<TSource>(this IObservable<TSource> source, Action<TSource> onNext)
            where TSource : class
        {
            return new Unsubscriber<TSource>(source, onNext);
        }

    }

    internal interface INotifySender
    {
        INotifyPropertyChanged Sender { get; }
        string PropertyName { get; }
        TSource GetSource<TSource>();
    }

    public interface IObservedChange<out TSender, out TValue>
    {
        TSender Sender { get; }
        TValue Value { get; }
        string PropertyName { get; }
    }

    public class ObservedChange<TSender, TValue> : IObservedChange<TSender, TValue>
    {
        private Expression<Func<TSender, TValue>> _property;

        public ObservedChange(TSender sender, Expression<Func<TSender, TValue>> property)
        {
            Sender = sender;

            var expression = property.Body as MemberExpression;
            if (expression != null)
            {
                var member = expression.Member;
                PropertyName = member.Name;
            }
            _property = property;

        }

        public TSender Sender { get; private set; }
        public TValue Value { get { return (TValue)Sender.GetType().GetProperty(PropertyName).GetValue(Sender, null); } }
        public string PropertyName { get; private set; }
    }

    public class Observable<TSender, TValue> : IObservable<IObservedChange<TSender, TValue>>, INotifySender
    {
        public Observable(IObservedChange<TSender, TValue> observedChange)
        {
            ObservedChange = observedChange;
        }

        public IObservedChange<TSender, TValue> ObservedChange { get; private set; }

        public IDisposable Subscribe(IObserver<IObservedChange<TSender, TValue>> observer)
        {
            throw new NotImplementedException();
        }

        public INotifyPropertyChanged Sender
        {
            get { return ObservedChange.Sender as INotifyPropertyChanged; }
        }

        public string PropertyName
        {
            get { return ObservedChange.PropertyName; }
        }

        public TSource GetSource<TSource>()
        {
            return (TSource)ObservedChange;
        }
    }

    internal class Unsubscriber<TSource> : IDisposable
        where TSource : class
    {
        private IObservable<TSource> _source;
        private readonly Action<TSource> _onNext;
        private readonly INotifySender _notifySender;

        public Unsubscriber(IObservable<TSource> source, Action<TSource> onNext)
        {
            _source = source;
            _notifySender = source as INotifySender;
            if (_notifySender != null && _notifySender.Sender != null)
            {
                _notifySender.Sender.PropertyChanged += SenderPropertyChanged;
            }
            _onNext = onNext;
        }

        void SenderPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (_onNext != null && e.PropertyName == _notifySender.PropertyName)
            {
                //_onNext(_onNext.Target as TSource);
                System.Windows.Application.Current.Dispatcher
                    .Invoke(System.Windows.Threading.DispatcherPriority.Normal,
                            (Action) (() => _onNext(_notifySender.GetSource<TSource>())));
            }
        }

        public void Dispose()
        {
            _notifySender.Sender.PropertyChanged -= SenderPropertyChanged;
        }
    }

}

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; }
    }