在网上看到的一个不错的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 顾名思义就是将一个实体对象绑定在页面上,上面两种都是放在作用域中。这里只讲用法。
页面代码的使用:<%=(Model as MVCTest.Models.Student).Name %> Model 是ViewPage d的一个属性值,用于接收控制器中返回的值
Model 传输数据还可以这样用:
使用泛型的ViewPage,将Model中的值指定特定类型不用强制性转换
4.传递多个对象类型
其实传递多个对象类型,最简单的办法就是将这些对象封装成另外一个类的属性,然后将这个对象传递到页面。不再做介绍。
原文作者:情缘 http://www.cnblogs.com/qingyuan