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

demo:http://pan.baidu.com/s/1bnTUaKJ

有人会疑问,为什么他能识别.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 ;
}
int index = this._displayModes.IndexOf(currentDisplayMode);
if (index < )
{
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 :
this.<>1__state = -;
this.<first>5__5 = this.<>4__this.FindFirstAvailableDisplayMode(this.currentDisplayMode, this.requireConsistentDisplayMode);
this.<i>5__6 = this.<first>5__5;
goto Label_00A5; case :
this.<>1__state = -;
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 = ;
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 == -))
{
this.<>1__state = ;
d__ = this;
}
else
{
d__ = new DisplayModeProvider.<GetAvailableDisplayModesForContext>d__4() {
<>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;
}
}
}
}
}

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

参考: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视图展现模式之移动布局解析-续集的更多相关文章

  1. 网站就必须用响应式布局吗?MVC视图展现模式之移动布局

    本文先引入给读者一个自己研究的机会,下次深入说明一下: 废话不多说,直接上图 新建一个mvc的项目 在视图里面添加一个移动端视图 正常访问一下 Bootstrap自带的响应式的方式(页面代码并没有改变 ...

  2. MVC视图展现模式之移动布局

    参考:http://www.cnblogs.com/dunitian/p/5218140.html 简单点,直接上用法 新建MVC项目,在golbal.asax中添加如下代码 //添加一个自定义后缀 ...

  3. Spring MVC视图解析器

    Spring MVC提供的视图解析器使用ViewResolver进行视图解析,实现浏览器中渲染模型.ViewResolver能够解析JSP.Velocity模板.FreeMarker模板和XSLT等多 ...

  4. ASP.NET Core 入门教程 6、ASP.NET Core MVC 视图布局入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)视图母版页教程 ASP.NET Core MVC (Razor)带有Section的视图母版页教程 ASP.NET Cor ...

  5. 模型-视图-控制器模式(MVC模式,10种常见体系架构模式之一)

    一.简介: 架构模式是一个通用的.可重用的解决方案,用于在给定上下文中的软件体系结构中经常出现的问题.架构模式与软件设计模式类似,但具有更广泛的范围. 模型-视图-控制器模式,也称为MVC模式.是软件 ...

  6. ASP.NET Core 入门笔记7,ASP.NET Core MVC 视图布局入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)视图母版页教程 ASP.NET Core MVC (Razor)带有Section的视图母版页教程 ASP.NET Cor ...

  7. 二、ASP.NET MVC Controller 控制器(一:深入解析控制器运行原理)

    阅读目录: 1.开篇介绍 2.ASP.NETMVC Controller 控制器的入口(Controller的执行流程) 3.ASP.NETMVC Controller 控制器的入口(Controll ...

  8. NET/ASP.NET MVC Controller 控制器(一:深入解析控制器运行原理)

    阅读目录: 1.开篇介绍 2.ASP.NETMVC Controller 控制器的入口(Controller的执行流程) 3.ASP.NETMVC Controller 控制器的入口(Controll ...

  9. Asp.net MVC 视图之公用代码

    一.公共模板 转自:http://www.cnblogs.com/kissdodog/archive/2013/01/07/2848881.html 1.@RenderBody() 在网站公用部分通过 ...

随机推荐

  1. ASP.NET Core HTTP 管道中的那些事儿

    前言 马上2016年就要过去了,时间可是真快啊. 上次写完 Identity 系列之后,反响还不错,所以本来打算写一个 ASP.NET Core 中间件系列的,但是中间遇到了很多事情.首先是 NPOI ...

  2. 一步步开发自己的博客 .NET版(10、前端对话框和消息框的实现)

    关于前端对话框.消息框的优秀插件多不胜数.造轮子是为了更好的使用轮子,并不是说自己造的轮子肯定好.所以,这个博客系统基本上都是自己实现的,包括日志记录.响应式布局.评论功能等等一些本可以使用插件的.好 ...

  3. setTimeout 的黑魔法

    setTimeout,前端工程师必定会打交道的一个函数.它看上去非常的简单,朴实.有着一个很不平凡的名字--定时器.让年少的我天真的以为自己可以操纵未来.却不知朴实之中隐含着惊天大密.我还记得我第一次 ...

  4. console的高级使用

    1.console.table()用来表格化展示数据. var people = { zqz: { name: 'zhaoqize', age: 'guess?' }, wdx: { name: 'w ...

  5. 关于Layer弹出框初探

    layer至今仍作为layui的代表作,她的受众广泛并非偶然,而是这五年多的坚持,不断完善和维护.不断建设和提升社区服务,使得猿们纷纷自发传播,乃至于成为今天的Layui最强劲的源动力.目前,laye ...

  6. 基于AOP的MVC拦截异常让代码更优美

    与asp.net 打交道很多年,如今天微软的优秀框架越来越多,其中微软在基于mvc的思想架构,也推出了自己的一套asp.net mvc 框架,如果你亲身体验过它,会情不自禁的说‘漂亮’.回过头来,‘漂 ...

  7. ASP.NET Core 中文文档目录

    翻译计划 五月中旬 .NET Core RC2 如期发布,我们遂决定翻译 ASP.NET Core 文档.我们在 何镇汐先生. 悲梦先生. 张仁建先生和 雷欧纳德先生的群中发布了翻译计划招募信息,并召 ...

  8. WPF 捕获键盘输入事件

    最近修改的一个需求要求捕获键盘输入的 Text,包括各种标点符号. 最开始想到的是 PreviewKeyDown 或者 PreviewKeyUp 这样的键盘事件. 但是这两个事件的对象 KeyEven ...

  9. 通过自定义特性,使用EF6拦截器完成创建人、创建时间、更新人、更新时间的统一赋值(使用数据库服务器时间赋值,接上一篇)

    目录: 前言 设计(完成扩展) 实现效果 扩展设计方案 扩展后代码结构 集思广益(问题) 前言: 在上一篇文章我写了如何重建IDbCommandTreeInterceptor来实现创建人.创建时间.更 ...

  10. java统计字符串单词的个数

    在一些项目中可能需要对一段字符串中的单词进行统计,我在这里写了一个简单的demo,有需要的同学可以拿去看一下. 本人没怎么写个播客,如果有啥说的不对的地方,你来打我啊 不说废话了直接贴代码: 实现代码 ...