翔如菲菲

其实天很蓝,阴云总会散;其实海不宽,此岸连彼岸.

导航

ASP.NET MVC3 向View传递数据

我们可以通过ViewResult 使Action传递数据到View.

一般来说我们使用3种方式通过Action向View传递数据:

1.ViewData

2.TempData

3.强类型Model 

我们先来看看ViewContext,其有3个Virtual 属性:

public class ViewContext : ControllerContext
{
  
public virtual TempDataDictionary TempData { getset; }
  
public virtual IView View { getset; }
  
public virtual ViewDataDictionary ViewData { getset; }
 ...
}

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

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 { getset; }
        
public string Title { getset; }
        
public string Director { getset; }
    }

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 { getset; }
    
public HtmlHelper<TModel> Html { getset; }
    
public TModel Model { get; }
    
public ViewDataDictionary<TModel> ViewData { getset; }
}

 

 

 

 

 

 

 

posted on 2011-07-02 10:37  翔如飞飞  阅读(848)  评论(0编辑  收藏  举报