ASP.NET MVC 视图

本文总阅读量:
  1. 1. 视图引擎的结构与性能
    1. 1.1. 视图引擎机制
      1. 1.1.1. 视图引擎类(检测已注册的试图引擎)
      2. 1.1.2. 解析视图引擎
      3. 1.1.3. 视图引擎调用者是谁
      4. 1.1.4. 视图对象View
    2. 1.2. 视图模板定义
      1. 1.2.1. 模板解析
      2. 1.2.2. 默认规则和文件夹
      3. 1.2.3. 用于视图的模板
      4. 1.2.4. 母版视图
  2. 2. HTML帮助器
    1. 2.1. 基础帮助器
      1. 2.1.1. 呈现HTML表单
      2. 2.1.2. 呈现输入元素
      3. 2.1.3. 操作链接
      4. 2.1.4. 部分视图
      5. 2.1.5. HtmlHelper其他的原生方法
    2. 2.2. 模板化帮助器
      1. 2.2.1. Display帮助器
      2. 2.2.2. Editor帮助器
    3. 2.3. 自定义帮助器
      1. 2.3.1. 帮助器结构
      2. 2.3.2. MvcHtmlString不只是字符串
      3. 2.3.3. 自定义帮助器样例
  3. 3. Razor视图引擎
    1. 3.1. 视图引擎内部机制
      1. 3.1.1. 搜索位置
      2. 3.1.2. 代码碎块
      3. 3.1.3. 条件式代码碎块
      4. 3.1.4. Razor视图对象
    2. 3.2. 设计一个样例视图
      1. 3.2.1. 建立视图专用的Model
      2. 3.2.2. 定义母版视图
      3. 3.2.3. 定义节
      4. 3.2.4. 节的默认内容
      5. 3.2.5. 嵌套布局
      6. 3.2.6. 声明式Html帮助器
  4. 4. 视图编码
    1. 4.1. 视图建模
      1. 4.1.1. ViewData,ViewBag
      2. 4.1.2. 强类型视图模型
    2. 4.2. 高级功能
      1. 4.2.1. 更改视图引擎检索格式
      2. 4.2.2. 呈现操作

设计并非外观怎样,感觉如何。设计是(解决)如何工作的问题 –Steve Jobs

视图引擎的结构与性能

视图引擎是位浏览器生成html输出的组件

控制器—数据—>视图模板—–>html

视图引擎机制

在asp.net mvc中,视图引擎只是一个实现固定接口(IViewEngine)的类。

每个应用程序可以有一个或多个视图引擎。asp.net mvc5中默认两个Razor,Aspx

视图引擎类(检测已注册的试图引擎)

ViewEngines类跟踪当前已安装的引擎的系统资源库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
namespace System.Web.Mvc
{
/// <summary>表示对应用程序可用的视图引擎的集合。</summary>
public static class ViewEngines
{
private static readonly ViewEngineCollection _engines;

/// <summary>获取视图引擎。</summary>
/// <returns>视图引擎。</returns>
public static ViewEngineCollection Engines
{
get
{
return ViewEngines._engines;
}
}

static ViewEngines()
{
ViewEngineCollection engineCollection = new ViewEngineCollection();
engineCollection.Add((IViewEngine) new WebFormViewEngine());
engineCollection.Add((IViewEngine) new RazorViewEngine());
ViewEngines._engines = engineCollection;
}
}
}

引擎集合_engines中初始化两个默认视图引擎

解析视图引擎

视图引擎是实现IViewEngine接口的类,引擎会以架构的名义检索视图对象(实际响应的所需所有信息的容器)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/// <summary>定义视图引擎所需的方法。</summary>
public interface IViewEngine
{
/// <summary>使用指定的控制器上下文来查找指定的部分视图。</summary>
/// <returns>部分视图。</returns>
/// <param name="controllerContext">控制器上下文。</param>
/// <param name="partialViewName">部分视图的名称。</param>
/// <param name="useCache">若指定视图引擎返回缓存的视图(如果存在缓存的视图),则为 true;否则为 false。</param>
ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache);

/// <summary>使用指定的控制器上下文来查找指定的视图。</summary>
/// <returns>页视图。</returns>
/// <param name="controllerContext">控制器上下文。</param>
/// <param name="viewName">视图的名称。</param>
/// <param name="masterName">母版的名称。</param>
/// <param name="useCache">若指定视图引擎返回缓存的视图(如果存在缓存的视图),则为 true;否则为 false。</param>
ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache);

/// <summary>使用指定的控制器上下文来释放指定的视图。</summary>
/// <param name="controllerContext">控制器上下文。</param>
/// <param name="view">视图。</param>
void ReleaseView(ControllerContext controllerContext, IView view);
}

视图引擎findview返回的ViewEngineResult包含三个元素:视图对象,对应的视图引擎,视图模板位置列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ViewEngineResult
{
。。。

/// <summary>获取或设置搜索的位置。</summary>
/// <returns>搜索的位置。</returns>
public IEnumerable<string> SearchedLocations { get; private set; }

/// <summary>获取或设置视图。</summary>
/// <returns>视图。</returns>
public IView View { get; private set; }

/// <summary>获取或设置视图引擎。</summary>
/// <returns>视图引擎。</returns>
public IViewEngine ViewEngine { get; private set; }
}

视图引擎调用者是谁

controller与viewengine一起工作明显是由mvc框架实现的,更细一步,控制器和视图引擎的活动是由一个外部管理器对象(操作调用程序)进行协调的。

操作调用程序由负责处理HTTP处理程序直接触发。

操作调用程序主要做两件事:1. 执行控制器的方法并保存操作结果 2. 处理操作结果。

https://luox78.github.io/images/操作调用程序时序图.png

1
2
3
4
5
6
7
8
9
10
ViewResult:ViewResultBase

public ViewResult();
public string MasterName { get; set; }
protected override ViewEngineResult FindView(ControllerContext context);

ViewResultBase:ActionResult

protected abstract ViewEngineResult FindView(ControllerContext context);
public override void ExecuteResult(ControllerContext context);

操作调用程序调用ExecuteResult

1
2
3
4
5
6
7
8
9
10
11
public override void ExecuteResult(ControllerContext context)
{
。。。
ViewEngineResult result = null;
if (this.View == null)
{
result = this.FindView(context);
this.View = result.View;
}
。。。
}

ExecuteResult会调用FindView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected override ViewEngineResult FindView(ControllerContext context)
{
ViewEngineResult result = base.ViewEngineCollection.FindView(context, base.ViewName, this.MasterName); if (result.View != null)
{
return result;
}
StringBuilder builder = new StringBuilder();
foreach (string str in result.SearchedLocations)
{
builder.AppendLine();
builder.Append(str);
}
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.Common_ViewNotFound, new object[] { base.ViewName, builder }));
}

FindView此时会调用ViewEngine里面的方法,遍历模板列表,没有抛出包含所有列表的信息的异常

ExecuteResult调用完FindView,执行this.View.Render(viewContext, output);将结果输出到响应流,这里viewContext中= new ViewContext(context, this.View, this.ViewData, this.TempData, output);包含了传入view里面的viewdata,同时强类型模型也是通过viewdata传入的

1
2
3
4
5
6
7
public TModel Model
{
get
{
return this.ViewData.Model;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public override void ExecuteResult(ControllerContext context)
{
//判断
if (context == null)
{
throw new ArgumentNullException("context");
}
if (string.IsNullOrEmpty(this.ViewName))
{
this.ViewName = context.RouteData.GetRequiredString("action");
}

//找视图
ViewEngineResult result = null;
if (this.View == null)
{
result = this.FindView(context);
this.View = result.View;
}

//输出
TextWriter output = context.HttpContext.Response.Output;
ViewContext viewContext = new ViewContext(context, this.View, this.ViewData, this.TempData, output);
this.View.Render(viewContext, output);
if (result != null)
{
result.ViewEngine.ReleaseView(context, this.View);
}
}

视图对象View

public IView View { get; [CompilerGenerated] private set; }

视图对象是实现IView接口的实例,视图对象的唯一目的是编写一些HTML响应到文本编辑器

视图模板定义

模板解析

在任务处理结束时,控制器要找出呈现给用户的下一个视图的名称。但视图名称转换成对应的HTML还需要一些额外的步骤

1。确定使用哪个视图引擎可以成功处理该视图的请求 2。视图名称必须匹配到一个html布局,并基于该布局创建一个试图对象 3。从获取视图名称开始,ViewResult对象就会按照视图引擎出现在ViewEngines.Engines集合中顺序,对所有已经安装的视图引擎进行插叙

默认规则和文件夹

默认情况下系统会在View文件夹下找,controller名对应的文件夹下action对应的后缀为cshtml、vbhtml的文件(Razor)

用于视图的模板

aspx视图引擎与webform中aspx页面语法基本一致,最大的不同在于,mvc中aspx并不是公共资源,不通i过特殊设置不能直接访问,所有的请求都是有controller接受和回复,对应的aspx页面只不过是回复的模板

1
2
3
4
5
6
public ActionResult About()
{
ViewBag.Message = "Your application description page.";

return View();
}

About.cshtml,这里通过viewbag传递的值

1
2
3
4
5
6
7
@{
ViewBag.Title = "About";
}
<h2>@ViewBag.Title.</h2>
<h3>@ViewBag.Message</h3>

<p>Use this area to provide additional information.</p>

母版视图

  1. 在 cshtml中直接指定

    1
    2
    3
    4
    @{
    Layout = "Index.cshtml";
    ViewBag.Title = "About";
    }
  2. 默认的layout在_ViewStart.cshtml中指定

HTML帮助器

asp.net mvc中创建html视图使用的不是webform中的空间而是HTML帮助器。

HTML帮助器就是一个简单的HTML工厂,返回的是没mvchtmlstring,内部实现也是使用stringbuilder进行拼接,视图引擎解析

基础帮助器

BeginForm,BeginRouteForm

EndForm

CheckBox,CheckBoxFor

Hidden,HiddenFor

Password,PasswordFor….

用法是@Html.ActionLink(...)

BeginForm,BeginRouteForm区别是带Route可以导航到任何已注册路由的任何位置,BeginForm只能使用控制器,action等属性

CheckBox,CheckBoxFor区别:带For参数只接受lamada表达式

注意:HTML帮助器是视图引擎的内置属性,所以不同的视图引擎帮助器是不同的,尽管默认的两个细节都是差不多的,但内部还是有些不同的

下面举一些例子

呈现HTML表单

1
2
3
4
@using (Html.BeginForm("Index", "Home"))
{

}

BeginForm代表《form》,using中finally会添加《/form》,BeginForm当然还有很多重载

呈现输入元素

再次说明,从功能的角度使用帮助器和直接编写HTML是一样的效果,下面的事例是复选框选中同时禁用

1
@Html.CheckBox("wode", true, htmlAttributes: new { disabled = "disabled" })

操作链接

1
@Html.ActionLink("index","Index")

对应的html

1
<a href="/">index</a>

RouteLink帮助器的工作方式差不多相同,可以使用任何已经注册的路由名称来确定生成的URL模式

1
@Html.RouteLink("index", "Default", new { Controller = "Home", Action = "Index" })

如果想在a标签下嵌套其他标签,这时候可以使用UrlHelper来解决

1
2
3
<a href="@Url.Action("Index")">
//添加其他标签
</a>

部分视图

可以使用Partial和RenderPartial帮助器插入部分视图看。区别是,Partial返回的是字符串,RenderPartial会写入输出流,返回空,所以两者的用法略有不同

1
2
@Html.Partial("_PartialForTest")
@{ Html.RenderPartial("_PartialForTest");}

HtmlHelper其他的原生方法

  • AntiForgeryToken:创建一个包含口令的隐藏域,Post、Get到controller时添加[ValidateAntiForgeryToken]特性验证
  • Raw:返回未经编码的原始Html字符串
  • AttributeEncode:这个方法在效率上比HtmlEncode快很多。但这是有代价的付出的HtmlAttributeEncode只对 左引号(),左括号(),and符合(&)转换为等效的字符实体。

“*HtmlAttributeEncode 方法的结果字符串只应当用于由双引号括起的属性。使用 HtmlAttributeEncode* 方法和用单引号括起的属性可能会引起安全问题。”

看大家的选择了,如果仅仅是担心输出HTML代码和JS方面的安全,可以使用HtmlAttributeEncode 方法,效率更高!

1
2
@Html.AttributeEncode("<script>alert(\"nihao\")</script>")
html:&lt;script>alert(&quot;nihao&quot;)&lt;/script>

模板化帮助器

一遍遍编写Html模板枯燥且容易出错,模板化帮助器可以很好的解决这一问题

在asp.net mvc中Editor,Display是两个基本的模板化帮助器

Display帮助器

显示viewdata里面的值

1
2
3
4
5
@{
ViewData["Title"] = "nihao";
}

@Html.Display("Title")

显示model对应属性的值

1
@Html.DisplayFor(model => model.Title)

显示model中所有的值

1
@Html.DisplayForModel()

Editor帮助器

Editor帮助器让你可以编辑指定的值

1
@Html.EditorFor(model => model.Title)

模板化帮助器可以使用模板进行自定义编辑,比如对于Editor可以将模板文件放在对应的controller下面的EditorTemplates下或者公用的Views/Shared下

1
@Html.EditorFor(model => model.date,"DateTime")

视图引擎会自己找对应文件夹下面的文件

自定义帮助器

有时候mvc提供的帮助器下没有我们需要的,这时候可以编辑自定义帮助器

帮助器结构

htmlhelper就是一个普通拓展方法

MvcHtmlString不只是字符串

自定义帮助器返回对象最好是MvcHtmlString封装对象而不是普通的字符串,实际上,所有的原生的帮助器方法也都是通过stringbuilder然后构造的MvcHtmlString对象,可以通过以下代码轻松的创建MvcHtmlString对象

1
MvcHtmlString.Create((string)str);

自定义帮助器样例

添加引用并使用

1
2
3
@using _02.Helper

@Html.Title("自定义帮助器创建的title")

简单的拓展方法

1
2
3
4
5
6
7
8
9
10
11
12
13
public static class TitleHelper
{
public static MvcHtmlString Title(this HtmlHelper html, string title, string className)
{
var h1Tag = new TagBuilder("h1");
if (!string.IsNullOrEmpty(className))
{
h1Tag.Attributes["class"] = className;
}
h1Tag.SetInnerText(title);
return MvcHtmlString.Create(h1Tag.ToString());
}
}

Razor视图引擎

视图引擎内部机制

搜索位置

视图引擎的构造函数中定义了视图搜索位置的格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public RazorViewEngine(IViewPageActivator viewPageActivator)
: base(viewPageActivator)
{
this.AreaViewLocationFormats = new string[4]
{
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/{1}/{0}.vbhtml",
"~/Areas/{2}/Views/Shared/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.vbhtml"
};
this.AreaMasterLocationFormats = new string[4]
{
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/{1}/{0}.vbhtml",
"~/Areas/{2}/Views/Shared/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.vbhtml"
};
this.AreaPartialViewLocationFormats = new string[4]
{
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/{1}/{0}.vbhtml",
"~/Areas/{2}/Views/Shared/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.vbhtml"
};
this.ViewLocationFormats = new string[4]
{
"~/Views/{1}/{0}.cshtml",
"~/Views/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml"
};
this.MasterLocationFormats = new string[4]
{
"~/Views/{1}/{0}.cshtml",
"~/Views/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml"
};
this.PartialViewLocationFormats = new string[4]
{
"~/Views/{1}/{0}.cshtml",
"~/Views/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml"
};
this.FileExtensions = new string[2]
{
"cshtml",
"vbhtml"
};
}

代码碎块

1
@{//code}

解析器会正确的识别标记 @{<h1>@Viewbag.Title</h1>}

可以通过@()插入字符

1
<p>@("hello" + Model.userName)</p>

括号中同时可以 放置一个函数

1
2
<p>@(Method())</p>
//等同于<p>@{Method();}</p>

注释使用@。。。@,使用@@表示@字符

Razor处理过的视图都是自动编码的,如果想保留原始格式使用

1
@Html.Raw(...)

条件式代码碎块

1
2
3
<div class="@Model.Css">
....
</div>

当Model.Css为null时,解析器理论上会抛出异常,但mvc4之后,条件逻辑已经内置在Razor引擎中了

Razor视图对象

Razor引擎生成视图对象可以通过反射dll看到继承自WebViewPage

1
public class _Page_Views_Home_About_cshtml : WebViewPage<object>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
namespace System.Web.Mvc
{
using System;
using System.Globalization;
using System.IO;
using System.Runtime.CompilerServices;
using System.Web;
using System.Web.Mvc.Properties;
using System.Web.WebPages;

public abstract class WebViewPage : WebPageBase, IViewDataContainer, IViewStartPageChild
{
private AjaxHelper<object> _ajax;
private HttpContextBase _context;
private DynamicViewDataDictionary _dynamicViewData;
private HtmlHelper<object> _html;
private ViewDataDictionary _viewData;

protected WebViewPage()
{
}

protected override void ConfigurePage(WebPageBase parentPage)
{
WebViewPage page = parentPage as WebViewPage;
if (page == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.CshtmlView_WrongViewBase, new object[] { parentPage.get_VirtualPath() }));
}
this.ViewContext = page.ViewContext;
this.ViewData = page.ViewData;
this.InitHelpers();
}

public override void ExecutePageHierarchy()
{
TextWriter writer = this.ViewContext.Writer;
this.ViewContext.Writer = base.get_Output();
base.ExecutePageHierarchy();
if (!string.IsNullOrEmpty(this.OverridenLayoutPath))
{
this.set_Layout(this.OverridenLayoutPath);
}
this.ViewContext.Writer = writer;
}

public virtual void InitHelpers()
{
this.Html = null;
this.Ajax = null;
this.Url = new UrlHelper(this.ViewContext.RequestContext);
}

protected virtual void SetViewData(ViewDataDictionary viewData)
{
this._viewData = viewData;
}

public AjaxHelper<object> Ajax
{
get
{
if ((this._ajax == null) && (this.ViewContext != null))
{
this._ajax = new AjaxHelper<object>(this.ViewContext, this);
}
return this._ajax;
}
set
{
this._ajax = value;
}
}

public override HttpContextBase Context
{
get =>
(this._context ?? this.ViewContext.HttpContext);
set
{
this._context = value;
}
}

public HtmlHelper<object> Html
{
get
{
if ((this._html == null) && (this.ViewContext != null))
{
this._html = new HtmlHelper<object>(this.ViewContext, this);
}
return this._html;
}
set
{
this._html = value;
}
}

public object Model =>
this.ViewData.Model;

internal string OverridenLayoutPath { get; set; }

public TempDataDictionary TempData =>
this.ViewContext.TempData;

public UrlHelper Url { get; set; }

[Dynamic]
public object ViewBag
{
[return: Dynamic]
get
{
Func<ViewDataDictionary> viewDataThunk = null;
if (this._dynamicViewData == null)
{
if (viewDataThunk == null)
{
viewDataThunk = () => this.ViewData;
}
this._dynamicViewData = new DynamicViewDataDictionary(viewDataThunk);
}
return this._dynamicViewData;
}
}

public System.Web.Mvc.ViewContext ViewContext { get; set; }

public ViewDataDictionary ViewData
{
get
{
if (this._viewData == null)
{
this.SetViewData(new ViewDataDictionary());
}
return this._viewData;
}
set
{
this.SetViewData(value);
}
}
}
}

可以看到View可以使用的对象都在这里面

设计一个样例视图

建立视图专用的Model

1
2
3
4
5
6
7
namespace _02.Models.Home
{
public class HomeIndexViewModel
{
public string Str { get; set; }
}
}

在视图中声明model类型

1
@model _02.Models.Home.HomeIndexViewModel

使用Model

1
2
3
<div>
<h1>@Model.Str</h1>
</div>

controller中添加返回对象

1
2
3
4
5
6
7
public ActionResult Index()
{
return View(new HomeIndexViewModel()
{
Str = "传递的数据"
});
}

定义母版视图

布局页就是一个普通的cshtml页面但是必须添加@RenderBody()告诉解析器在哪儿注入布局模板

layout可以使任意路径或设置条件,默认的layout在_VIewStart.cshtml中定义

1
2
3
4
5
6
@{
if (Request.Browser.IsMobileDevice)
{
Layout = "About.cshtml";
}
}

通过~返回根目录

1
Layout = "~/Views/Shared/_Layout.cshtml";

定义节

RenderBody方法定义了布局注入的单个点,但你可能需要将内容注入到多个位置,在布局模板中,可以通过在希望出现内容的位置放置一个RenderSection的调用来定义注入点

默认的_Layout中就有关于scripts的节

1
@RenderSection("scripts", required: false)

required: false指的是不是必须的,可以通过@section+名称进行节的编写

1
2
3
4
@section scripts
{
<script>alert("nihao");</script>
}

节的默认内容

webform中视图引擎中的母版页可以指定默认内容,Razor没有但是可以通过IsSectionDefined进行判断,添加默认的内容

1
2
3
4
5
6
7
<div id="footer">
@if(IsSectionDefined("name")){
@RenderSection("name");
}else{
<span>undefined</span>
}
</div>

嵌套布局

布局是可以嵌套的通过指定Layout实现嵌套

声明式Html帮助器

通过HtmlHelper创建网页内容如果有很多元素就十分困难,这时候使用声明式Html帮助器就方便很多

首先在项目中添加App_Code,添加MyHelpers.cshtml,定义一个简单的方法,格式@helper+签名

1
2
3
4
@helper ShowTitle(string title)
{
<h1>@title</h1>
}

使用

1
@MyHelpers.ShowTitle("nihao")

注意在App_Code外编辑的帮助器不会被检测

视图编码

视图建模

ViewData,ViewBag

通过这两个对象可以从controller中传值到view中,两个类型都是dynomic,用法:

1
2
3
4
5
6
ViewData["Title"]="nihao";
ViewBag.Title="nihao";

view中:
@ViewData["Title"]
@ViewBag.Title

强类型视图模型

上面已经说过

应尽量减少viewbag,viewdata,因为使用viewmodel更易维护,同时注意的是这里的model是视图模型,应尽量减少直接将数据模型当做视图模型

高级功能

更改视图引擎检索格式

创建自己的检索格式,项目中只是用Razor就没必要检索aspx格式的视图,提高效率,同时可以将PartialViews放在不同的地方便于管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
namespace _02.App_Start
{
public class NewFormatViewEngine : RazorViewEngine
{
public NewFormatViewEngine()
{
this.MasterLocationFormats = base.MasterLocationFormats;
this.ViewLocationFormats = new string[]
{
"~/Views/{1}/{0}.cshtml"
};
this.PartialViewLocationFormats = new string[]
{
"~/PartialViews/{1}/{0}.cshtml"
};
}
}
}

我在App_Start中创建自己的新类继承自RazorViewEngine

Global.asax中,清空原来的引擎,添加新的

1
2
3
4
5
6
7
8
9
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
。。。
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new NewFormatViewEngine());
}
}

需要注意的是要添加Web.config配置对应的视图引擎,这里直接复制Views里面的即可

已经可以使用了,文件夹PartialViews ==> Home ==> Home_Contact_PartialView.cshtml

1
@Html.Partial("Home_Contact_PartialView")

呈现操作

当需要呈现一个固定不变的视图或者需要控制器提供数据的视图的时候使用呈现操作即可

菜单例子:控制中添加返回PartialView的方法Menu

1
2
3
4
5
6
7
8
9
public ActionResult Menu()
{
return PartialView(new List<string>()
{
"menu1",
"menu2",
"menu3"
});
}

创建对应的视图

1
2
3
4
5
6
7
8
@model IList<string>

<div>
@foreach (var str in Model)
{
<a>@str</a>
}
</div>

使用

1
@Html.Action("Menu")

与@Html.Partial一样ActionRender也是写入到响应流,Action直接返回html字符串