MVC视图展现模式之移动布局解析-续集

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MVC视图展现模式之移动布局解析-续集相关的知识,希望对你有一定的参考价值。

网站就必须用响应式布局吗?MVC视图展现模式之移动布局:http://www.cnblogs.com/dunitian/p/5213787.html

有人会疑问,为什么他能识别.mobile的后缀却不能识别例如:.mac .dnt 等等后缀呢?这些又是放在哪里的呢?

mobile 这个后缀其实是存放在:DisplayModeProvider.Instance.Modes 里面的,我们监视一下,发现里面就一个mobile,还有一个是默认的

技术分享

可以猜想,运行的时候是从上往下匹配的,“”的是通用匹配,那么我们加入一个自定义的后缀看看==>(可以思考一下,为什么用 insert 不用 add)

            //添加一个自定义后缀
            DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("dnt")
            {
                ContextCondition = (Context) => Context.Request.UserAgent.Contains("dnt")
            });

可能你不是很理解 DefaultDisplayMode,看看反编译吧----构造函数为suffix赋值(后缀)

技术分享

添加一个自定义的后缀视图

技术分享

打开谷歌浏览器,设置一下User-Agent Switcher的浏览模式

技术分享

技术分享

技术分享

技术分享

附录:

DisplayModeProvider:

技术分享
// Generated by .NET Reflector from F:\\Work\\Net\\Mobile\\packages\\Microsoft.AspNet.WebPages.3.2.3\\lib\\net45\\System.Web.WebPages.dll
namespace System.Web.WebPages
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Runtime.CompilerServices;
    using System.Web;
    
    public sealed class DisplayModeProvider
    {
        private static readonly object _displayModeKey = new object();
        private readonly List<IDisplayMode> _displayModes;
        private static readonly DisplayModeProvider _instance = new DisplayModeProvider();
        public static readonly string DefaultDisplayModeId = string.Empty;
        public static readonly string MobileDisplayModeId = "Mobile";
        
        internal DisplayModeProvider()
        {
            List<IDisplayMode> list = new List<IDisplayMode>();
            DefaultDisplayMode item = new DefaultDisplayMode(MobileDisplayModeId) {
                ContextCondition = context => context.GetOverriddenBrowser().IsMobileDevice
            };
            list.Add(item);
            list.Add(new DefaultDisplayMode());
            this._displayModes = list;
        }
        
        private int FindFirstAvailableDisplayMode(IDisplayMode currentDisplayMode, bool requireConsistentDisplayMode)
        {
            if (!requireConsistentDisplayMode || (currentDisplayMode == null))
            {
                return 0;
            }
            int index = this._displayModes.IndexOf(currentDisplayMode);
            if (index < 0)
            {
                return this._displayModes.Count;
            }
            return index;
        }
        
        public IEnumerable<IDisplayMode> GetAvailableDisplayModesForContext(HttpContextBase httpContext, IDisplayMode currentDisplayMode)
        {
            return this.GetAvailableDisplayModesForContext(httpContext, currentDisplayMode, this.RequireConsistentDisplayMode);
        }
        
        internal IEnumerable<IDisplayMode> GetAvailableDisplayModesForContext(HttpContextBase httpContext, IDisplayMode currentDisplayMode, bool requireConsistentDisplayMode)
        {
            int iteratorVariable0 = this.FindFirstAvailableDisplayMode(currentDisplayMode, requireConsistentDisplayMode);
            for (int i = iteratorVariable0; i < this._displayModes.Count; i++)
            {
                IDisplayMode iteratorVariable2 = this._displayModes[i];
                if (iteratorVariable2.CanHandleContext(httpContext))
                {
                    yield return iteratorVariable2;
                }
            }
        }
        
        public DisplayInfo GetDisplayInfoForVirtualPath(string virtualPath, HttpContextBase httpContext, Func<string, bool> virtualPathExists, IDisplayMode currentDisplayMode)
        {
            return this.GetDisplayInfoForVirtualPath(virtualPath, httpContext, virtualPathExists, currentDisplayMode, this.RequireConsistentDisplayMode);
        }
        
        internal DisplayInfo GetDisplayInfoForVirtualPath(string virtualPath, HttpContextBase httpContext, Func<string, bool> virtualPathExists, IDisplayMode currentDisplayMode, bool requireConsistentDisplayMode)
        {
            for (int i = this.FindFirstAvailableDisplayMode(currentDisplayMode, requireConsistentDisplayMode); i < this._displayModes.Count; i++)
            {
                IDisplayMode mode = this._displayModes[i];
                if (mode.CanHandleContext(httpContext))
                {
                    DisplayInfo info = mode.GetDisplayInfo(httpContext, virtualPath, virtualPathExists);
                    if (info != null)
                    {
                        return info;
                    }
                }
            }
            return null;
        }
        
        internal static IDisplayMode GetDisplayMode(HttpContextBase context)
        {
            if (context == null)
            {
                return null;
            }
            return (context.Items[_displayModeKey] as IDisplayMode);
        }
        
        internal static void SetDisplayMode(HttpContextBase context, IDisplayMode displayMode)
        {
            if (context != null)
            {
                context.Items[_displayModeKey] = displayMode;
            }
        }
        
        public static DisplayModeProvider Instance
        {
            get
            {
                return _instance;
            }
        }
        
        public IList<IDisplayMode> Modes
        {
            get
            {
                return this._displayModes;
            }
        }
        
        public bool RequireConsistentDisplayMode { get; set; }
        
        [CompilerGenerated]
        private sealed class <GetAvailableDisplayModesForContext>d__4 : IEnumerable<IDisplayMode>, IEnumerable, IEnumerator<IDisplayMode>, IEnumerator, IDisposable
        {
            private int <>1__state;
            private IDisplayMode <>2__current;
            public IDisplayMode <>3__currentDisplayMode;
            public HttpContextBase <>3__httpContext;
            public bool <>3__requireConsistentDisplayMode;
            public DisplayModeProvider <>4__this;
            private int <>l__initialThreadId;
            public int <first>5__5;
            public int <i>5__6;
            public IDisplayMode <mode>5__7;
            public IDisplayMode currentDisplayMode;
            public HttpContextBase httpContext;
            public bool requireConsistentDisplayMode;
            
            [DebuggerHidden]
            public <GetAvailableDisplayModesForContext>d__4(int <>1__state)
            {
                this.<>1__state = <>1__state;
                this.<>l__initialThreadId = Environment.CurrentManagedThreadId;
            }
            
            private bool MoveNext()
            {
                switch (this.<>1__state)
                {
                    case 0:
                        this.<>1__state = -1;
                        this.<first>5__5 = this.<>4__this.FindFirstAvailableDisplayMode(this.currentDisplayMode, this.requireConsistentDisplayMode);
                        this.<i>5__6 = this.<first>5__5;
                        goto Label_00A5;
                    
                    case 1:
                        this.<>1__state = -1;
                        break;
                    
                    default:
                        goto Label_00BD;
                }
            Label_0097:
                this.<i>5__6++;
            Label_00A5:
                if (this.<i>5__6 < this.<>4__this._displayModes.Count)
                {
                    this.<mode>5__7 = this.<>4__this._displayModes[this.<i>5__6];
                    if (this.<mode>5__7.CanHandleContext(this.httpContext))
                    {
                        this.<>2__current = this.<mode>5__7;
                        this.<>1__state = 1;
                        return true;
                    }
                    goto Label_0097;
                }
            Label_00BD:
                return false;
            }
            
            [DebuggerHidden]
            IEnumerator<IDisplayMode> IEnumerable<IDisplayMode>.GetEnumerator()
            {
                DisplayModeProvider.<GetAvailableDisplayModesForContext>d__4 d__;
                if ((Environment.CurrentManagedThreadId == this.<>l__initialThreadId) && (this.<>1__state == -2))
                {
                    this.<>1__state = 0;
                    d__ = this;
                }
                else
                {
                    d__ = new DisplayModeProvider.<GetAvailableDisplayModesForContext>d__4(0) {
                        <>4__this = this.<>4__this
                    };
                }
                d__.httpContext = this.<>3__httpContext;
                d__.currentDisplayMode = this.<>3__currentDisplayMode;
                d__.requireConsistentDisplayMode = this.<>3__requireConsistentDisplayMode;
                return d__;
            }
            
            [DebuggerHidden]
            IEnumerator IEnumerable.GetEnumerator()
            {
                return this.System.Collections.Generic.IEnumerable<System.Web.WebPages.IDisplayMode>.GetEnumerator();
            }
            
            [DebuggerHidden]
            void IEnumerator.Reset()
            {
                throw new NotSupportedException();
            }
            
            void IDisposable.Dispose()
            {
            }
            
            IDisplayMode IEnumerator<IDisplayMode>.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.<>2__current;
                }
            }
            
            object IEnumerator.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.<>2__current;
                }
            }
        }
    }
}
View Code

DefaultDisplayMode:

技术分享
// Generated by .NET Reflector from F:\\Work\\Net\\Mobile\\packages\\Microsoft.AspNet.WebPages.3.2.3\\lib\\net45\\System.Web.WebPages.dll
namespace System.Web.WebPages
{
    using System;
    using System.IO;
    using System.Runtime.CompilerServices;
    using System.Web;
    
    public class DefaultDisplayMode : IDisplayMode
    {
        private readonly string _suffix;
        
        public DefaultDisplayMode() : this(DisplayModeProvider.DefaultDisplayModeId)
        {
        }
        
        public DefaultDisplayMode(string suffix)
        {
            this._suffix = suffix ?? string.Empty;
        }
        
        public bool CanHandleContext(HttpContextBase httpContext)
        {
            if (this.ContextCondition != null)
            {
                return this.ContextCondition(httpContext);
            }
            return true;
        }
        
        public virtual DisplayInfo GetDisplayInfo(HttpContextBase httpContext, string virtualPath, Func<string, bool> virtualPathExists)
        {
            string arg = this.TransformPath(virtualPath, this._suffix);
            if ((arg != null) && virtualPathExists(arg))
            {
                return new DisplayInfo(arg, this);
            }
            return null;
        }
        
        protected virtual string TransformPath(string virtualPath, string suffix)
        {
            if (string.IsNullOrEmpty(suffix))
            {
                return virtualPath;
            }
            string extension = Path.GetExtension(virtualPath);
            return Path.ChangeExtension(virtualPath, suffix + extension);
        }
        
        public Func<HttpContextBase, bool> ContextCondition { get; set; }
        
        public virtual string DisplayModeId
        {
            get
            {
                return this._suffix;
            }
        }
    }
}
View Code

参考:https://msdn.microsoft.com/en-us/magazine/hh975347.aspx

http://www.asp.net/mvc/overview/older-versions/aspnet-mvc-4-mobile-features

http://stackoverflow.com/questions/9354188/asp-net-mvc-4-mobile-display-modes-stop-working

 

以上是关于MVC视图展现模式之移动布局解析-续集的主要内容,如果未能解决你的问题,请参考以下文章

添加两个窗格的平板电脑布局会导致在移动设备中找不到视图(小于w600dp)

MVC 在布局代码之前执行视图代码并破坏我的脚本顺序

ThinkPHP之MVC简析

javaweb之MVC设计模式

简单谈谈js中的MVC

设计模式之MVC中的设计模式(连载中 12)