我们可以通过ViewResult 使Action传递数据到View.
一般来说我们使用3种方式通过Action向View传递数据:
1.ViewData
2.TempData
3.强类型Model
我们先来看看ViewContext,其有3个Virtual 属性:
public
class
ViewContext : ControllerContext
{
public
virtual
TempDataDictionary TempData {
get
;
set
; }
public
virtual
IView View {
get
;
set
; }
public
virtual
ViewDataDictionary ViewData {
get
;
set
; }
...
}
ViewData TempData传递过程:
Action中的赋值语句实际上操作的是Controller类的ViewData和TempData属性, 此时并没有任何的数据传递.Action返回ViewResult,
Controller的View方法会将Controller类的ViewData和TempData属性值传递给ViewResult,代码如下:
public
abstract
class
Controller : ControllerBase, IActionFilter,IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter
{
...
protected
internal
virtual
ViewResult View(IView view,
object
model)
{
if
(model
!=
null
)
{
base
.ViewData.Model
=
model;
}
return
new
ViewResult { View
=
view, ViewData
=
base
.ViewData, TempData
=
base
.TempData };
}
...
}
ViewResult的ExecuteResult根据ViewData和TempData构建ViewContext对象:
public
abstract
class
ViewResultBase : ActionResult
{
...
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 writer
=
context.HttpContext.get_Response().get_Output();
ViewContext viewContext
= new ViewContext(context, this.View, this.ViewData, this
.TempData, writer);
this
.View.Render(viewContext, writer);
if
(result
!=
null
)
{
result.ViewEngine.ReleaseView(context,
this
.View);
}
}
...
}
ViewContext对象最终会传递给ViewPage, 也就是说ViewData和TempData集合传递到了ViewPage. 实际上ViewData对象并不是通过ViewContext传递到ViewPage中的。
ViewPage上的ViewData是一个单独的属性,它继承自:IVeiwContainer
public
interface
IViewDataContainer
{
//
Properties
ViewDataDictionary ViewData {
get
;
set
; }
}
TempData在Controller的基类ControllerBase中定义
public
abstract
class
ControllerBase : IController
{
...
public
TempDataDictionary TempData
{
get
{
if
((
this
.ControllerContext
!=
null
)
&&
this
.ControllerContext.IsChildAction)
{
return
this
.ControllerContext.ParentActionViewContext.TempData;
}
if
(
this
._tempDataDictionary
==
null
)
{
this
._tempDataDictionary
=
new
TempDataDictionary();
}
return
this
._tempDataDictionary;
}
set
{
this
._tempDataDictionary
=
value;
}
}
...
}
TempData其实访问的是ViewContext.TempData
ViewPage Code如下:
[FileLevelControlBuilder(
typeof
(ViewPageControlBuilder))]
public
class
ViewPage : Page, IViewDataContainer
{
...
public
ViewDataDictionary ViewData
{
get
{
if
(
this
._viewData
==
null
)
{
this
.SetViewData(
new
ViewDataDictionary());
}
return
this
._viewData;
}
set
{
this
.SetViewData(value);
}
}
public
TempDataDictionary TempData
{
get
{
return
this
.ViewContext.TempData;
}
}
...
}
ViewData 和TempData传值如下:
public
class
HomeController : Controller
{
public
ActionResult Index()
{
ViewData[
"ViewData"] = "ViewData";
TempData["TempData"] = "TempData"
;
return
View();
}
}
在View中我们如下使用:
<
asp:Content
ID
="Content2"
ContentPlaceHolderID
="MainContent"
runat
="server"
>
ViewData传值:
<%=ViewData["ViewData"]%><br />
TempData传值:<%=TempData["TempData"]%>
</
asp:Content
>
ViewData只能在当前Action中有效
TempData可以类似于Session一样到其它页面仍然存在,但仅仅局限于这两个前后相连的页面(只能经过一次Controller传递)
TempData一般用于临时的缓存内容或抛出错误页面时传递错误信息
强类型Model传值如下:
1. 我们需要Create一个Model类:
public
class
Movie
{
public
int
Id {
get
;
set
; }
public
string
Title {
get
;
set
; }
public
string
Director {
get
;
set
; }
}
2. Create一个View:
ViewName:Index
Check:Cerate aStrongly-typed view
选择刚Create的Movie Model
Scaffold template:选择List
点击ADD创建View
VS自动生成如下Code:
<%
@ Page Title
=
""
Language
=
"
C#
"
MasterPageFile
=
"
~/Views/Shared/Site.Master
"
Inherits
=
"
System.Web.Mvc.ViewPage<Jeriffe.Web.MVC.MovieApp.Movie>
"
%>
<
asp:Content
ID
="Content1"
ContentPlaceHolderID
="TitleContent"
runat
="server"
>
Details
</
asp:Content
>
<
asp:Content
ID
="Content2"
ContentPlaceHolderID
="MainContent"
runat
="server"
>
<
h2
>
Details
</
h2
>
<
fieldset
>
<
legend
>
Movie
</
legend
>
<
div
class
="display-label"
>
Title
</
div
>
<
div
class
="display-field"
>
<%
: Html.DisplayFor(model
=>
model.Title)
%>
</
div
>
<
div
class
="display-label"
>
Director
</
div
>
<
div
class
="display-field"
>
<%
: Html.DisplayFor(model
=>
model.Director)
%>
</
div
>
</
fieldset
>
<
p
>
<%
: Html.ActionLink(
"
Edit
"
,
"
Edit
"
,
new
{ id
=
Model.Id })
%>
|
<%
: Html.ActionLink(
"
Back to List
"
,
"
Index
"
)
%>
</
p
>
</
asp:Content
>
ViewPage的Model属性就是一个强类型对象, 在这里就是Movie.page页面指令可以看出, 这里的页面继承自ViewPage<Model>类, 而不是ViewPage.
ViewPage<TModel> Code如下:
public
class
ViewPage
<
TModel
>
: ViewPage
{
//
Fields
private
ViewDataDictionary
<
TModel
>
_viewData;
//
Methods
public
ViewPage();
public
override
void
InitHelpers();
protected
override
void
SetViewData(ViewDataDictionary viewData);
//
Properties
public
AjaxHelper
<
TModel
>
Ajax {
get
;
set
; }
public
HtmlHelper
<
TModel
>
Html {
get
;
set
; }
public TModel Model { get
; }
public
ViewDataDictionary
<
TModel
>
ViewData {
get
;
set
; }
}