asp.net MVC进阶学习---View和Controller之间的数据传递(一)

发布时间:2020-01-19编辑:脚本学堂
asp.net MVC进阶学习---View和Controller之间的数据传递(一)

    在网上看到的一个不错的asp.net MVC学习系列,希望可以帮助那些正在研究MVC的朋友们。
    本部分内容:asp.net MVC进阶学习--View和Controller之间的数据传递(一)

1.使用ViewData
 ViewData 的是ControllerBase 的一个属性,是一个数据字典类型的,其实现代码如(这段代码来自asp.net MVC开源项目中源码)下:
 

复制代码 代码如下:

public class ViewDataDictionary : IDictionary<string, object> {  
           private readonly Dictionary<string, object> _innerDictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
           private object _model;
           private readonly ModelStateDictionary _modelState = new ModelStateDictionary();
  
           public ViewDataDictionary()
               : this((object)null) {
           }
 
          [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors",
              Justification = "See note on SetModel() method.")]
          public ViewDataDictionary(object model) {
              Model = model;
          }
 
          [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors",
              Justification = "See note on SetModel() method.")]
          public ViewDataDictionary(ViewDataDictionary dictionary) {
              if (dictionary == null) {
                  throw new ArgumentNullException("dictionary");
              }
 
              foreach (var entry in dictionary) {
                  _innerDictionary.Add(entry.Key, entry.Value);
              }
              foreach (var entry in dictionary.ModelState) {
                  ModelState.Add(entry.Key, entry.Value);
              }
              Model = dictionary.Model;
          }
 
          [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
          public int Count {
              get {
                  return _innerDictionary.Count;
              }
          }
 
          [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
          public bool IsReadOnly {
              get {
                  return ((IDictionary<string, object>)_innerDictionary).IsReadOnly;
              }
          }
 
          [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
          public ICollection<string> Keys {
              get {
                  return _innerDictionary.Keys;
              }
          }
 
          public object Model {
              get {
                  return _model;
              }
              set {
                  SetModel(value);
              }
          }
 
          public ModelStateDictionary ModelState {
              get {
                  return _modelState;
              }
          }
 
          [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
          public object this[string key] {
              get {
                  object value;
                  _innerDictionary.TryGetValue(key, out value);
                  return value;
              }
              set {
                  _innerDictionary[key] = value;
              }
          }
 
          [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
          public ICollection<object> Values {
              get {
                  return _innerDictionary.Values;
              }
          }
 
          [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
          public void Add(KeyValuePair<string, object> item) {
              ((IDictionary<string, object>)_innerDictionary).Add(item);
          }
 
          [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
          public void Add(string key, object value) {
              _innerDictionary.Add(key, value);
          }
 
          [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
          public void Clear() {
             _innerDictionary.Clear();
         }
 
         [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
         public bool Contains(KeyValuePair<string, object> item) {
             return ((IDictionary<string, object>)_innerDictionary).Contains(item);
         }
 
         [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
         public bool ContainsKey(string key) {
             return _innerDictionary.ContainsKey(key);
         }
 
         [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
         public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex) {
             ((IDictionary<string, object>)_innerDictionary).CopyTo(array, arrayIndex);
         }
 
         [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Eval",
             Justification = "Commonly used shorthand for Evaluate.")]
         public object Eval(string expression) {
             if (String.IsNullOrEmpty(expression)) {
                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "expression");
             }
 
             return ViewDataEvaluator.Eval(this, expression);
         }
 
         [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Eval",
             Justification = "Commonly used shorthand for Evaluate.")]
         public string Eval(string expression, string format) {
             object value = Eval(expression);
 
             if (value == null) {
                 return String.Empty;
             }
 
             if (String.IsNullOrEmpty(format)) {
                 return Convert.ToString(value, CultureInfo.CurrentCulture);
             }
             else {
                 return String.Format(CultureInfo.CurrentCulture, format, value);
             }
         }

         [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
         public IEnumerator<KeyValuePair<string, object>> GetEnumerator() {
             return _innerDictionary.GetEnumerator();
         }
 
         [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
         public bool Remove(KeyValuePair<string, object> item) {
             return ((IDictionary<string, object>)_innerDictionary).Remove(item);
         }
 
         [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
         public bool Remove(string key) {
             return _innerDictionary.Remove(key);
         }
 
         // This method will execute before the derived type's instance constructor executes. Derived types must
         // be aware of this and should plan accordingly. For example, the logic in SetModel() should be simple
         // enough so as not to depend on the "this" pointer referencing a fully constructed object.
         protected virtual void SetModel(object value) {
             _model = value;
         }
 
         [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
         public bool TryGetValue(string key, out object value) {
             return _innerDictionary.TryGetValue(key, out value);
         }
 
         internal static class ViewDataEvaluator {
             public static object Eval(ViewDataDictionary vdd, string expression) {
                 //Given an expression "foo.bar.baz" we look up the following (pseudocode):
                 //  this["foo.bar.baz.quux"]
                 //  this["foo.bar.baz"]["quux"]
                 //  this["foo.bar"]["baz.quux]
                 //  this["foo.bar"]["baz"]["quux"]
                 //  this["foo"]["bar.baz.quux"]
                 //  this["foo"]["bar.baz"]["quux"]
                 //  this["foo"]["bar"]["baz.quux"]
                 //  this["foo"]["bar"]["baz"]["quux"]
 
                 object evaluated = EvalComplexExpression(vdd, expression);
                 return evaluated;
             }
 
             private static object EvalComplexExpression(object indexableObject, string expression) {
                 foreach (ExpressionPair expressionPair in GetRightToLeftExpressions(expression)) {
                     string subExpression = expressionPair.Left;
                     string postExpression = expressionPair.Right;
 
                     object subtarget = GetPropertyValue(indexableObject, subExpression);
                     if (subtarget != null) {
                         if (String.IsNullOrEmpty(postExpression))
                             return subtarget;
 
                         object potential = EvalComplexExpression(subtarget, postExpression);
                         if (potential != null) {
                             return potential;
                         }
                     }
                 }
                 return null;
             }
 
             private static IEnumerable<ExpressionPair> GetRightToLeftExpressions(string expression) {
                 // Produces an enumeration of all the combinations of complex property names
                 // given a complex expression. See the list above for an example of the result
                 // of the enumeration.
 
                 yield return new ExpressionPair(expression, String.Empty);
 
                 int lastDot = expression.LastIndexOf('.');
 
                 string subExpression = expression;
                 string postExpression = string.Empty;
 
                 while (lastDot > -1) {
                     subExpression = expression.Substring(0, lastDot);
                     postExpression = expression.Substring(lastDot + 1);
                     yield return new ExpressionPair(subExpression, postExpression);
 
                     lastDot = subExpression.LastIndexOf('.');
                 }
             }
 
             private static object GetIndexedPropertyValue(object indexableObject, string key) {
                 Type indexableType = indexableObject.GetType();
 
                 ViewDataDictionary vdd = indexableObject as ViewDataDictionary;
                 if (vdd != null) {
                     return vdd[key];
                 }
 
                 MethodInfo containsKeyMethod = indexableType.GetMethod("ContainsKey", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string) }, null);
                 if (containsKeyMethod != null) {
                     if (!(bool)containsKeyMethod.Invoke(indexableObject, new object[] { key })) {
                         return null;
                     }
                 }
 
                 PropertyInfo info = indexableType.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance, null, null, new Type[] { typeof(string) }, null);
                 if (info != null) {
                     return info.GetValue(indexableObject, new object[] { key });
                 }
 
                 PropertyInfo objectInfo = indexableType.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance, null, null, new Type[] { typeof(object) }, null);
                 if (objectInfo != null) {
                     return objectInfo.GetValue(indexableObject, new object[] { key });
                 }
                 return null;
             }
 
             private static object GetPropertyValue(object container, string propertyName) {
                 // This method handles one "segment" of a complex property expression
 
                 // First, we try to evaluate the property based on its indexer
                 object value = GetIndexedPropertyValue(container, propertyName);
                 if (value != null) {
                     return value;
                 }
 
                 // If the indexer didn't return anything useful, continue
 
                 // If the container is a ViewDataDictionary then treat its Model property
                 // as the container instead of the ViewDataDictionary itself.
                 ViewDataDictionary vdd = container as ViewDataDictionary;
                 if (vdd != null) {
                     container = vdd.Model;
                 }
 
                 // Second, we try to use PropertyDescriptors and treat the expression as a property name
                 PropertyDescriptor descriptor = TypeDescriptor.GetProperties(container).Find(propertyName, true);
                 if (descriptor == null) {
                     return null;
                 }
 
                 return descriptor.GetValue(container);
             }
 
             private struct ExpressionPair {
                 public readonly string Left;
                 public readonly string Right;
 
                 public ExpressionPair(string left, string right) {
                     Left = left;
                     Right = right;
                 }
             }
         }
 
         #region IEnumerable Members
         [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
         IEnumerator IEnumerable.GetEnumerator() {
             return ((IEnumerable)_innerDictionary).GetEnumerator();
         }
         #endregion
 
     }
 

  ViewData的用法如下:ViewData["user"] = LoginUser;  页面的代码<%=(ViewData["user"] as Users).UserName%>
  ViewData的作用域从控制器设置值到页面值显示。

2.使用TempData
  TempData同样属于ControllerBase 的属性 用法和ViewData 基本相同,但是他们的实质是不同的,ViewData 是数据字典类型而TempData是Session存储的值,TempData数据只能在控制器中传递一次,每个元素也只能被访问一次,然后Session中的值就会被自动删除,它的生命周期要比ViewData的要长.

3.使用Model
  使用Model 顾名思义就是将一个实体对象绑定在页面上,上面两种都是放在作用域中。这里只讲用法。
  

复制代码 代码如下:
public ActionResult Student()
  {
    DbContext context=new DbContext();
    Student stu=context.Single(s=>s.ID==1);
    return View(stu);
  }

  页面代码的使用:<%=(Model as MVCTest.Models.Student).Name %>  Model 是ViewPage d的一个属性值,用于接收控制器中返回的值

  Model 传输数据还可以这样用:
  

复制代码 代码如下:
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MVCTest.Models.Student>" %>
  <%=Model.Name %>
 

  使用泛型的ViewPage,将Model中的值指定特定类型不用强制性转换

4.传递多个对象类型
其实传递多个对象类型,最简单的办法就是将这些对象封装成另外一个类的属性,然后将这个对象传递到页面。不再做介绍。

原文作者:情缘 http://www.cnblogs.com/qingyuan