首页 新闻 搜索 专区 学院

asp.net mvc4中关于viewmodel继承的问题

0
[待解决问题]

近日使用asp.net mvc4做一个提交提交viewmodel集合对象的例子,发现viewmodel如果继承了ICollection<T>接口,post提交是action中该viewmodel对象的实例就为空,不知道为什么。请大神们指点。以下是我的代码:

1、首先看一下我的html代码,该页面使用的是TestModel对象。

@model ShoppingMall.Admin.Models.Product.TestModel
@{
    ViewBag.Title = "Test";
    Layout = "~/Views/Shared/_Layout.cshtml";
}


@using (Html.BeginForm("Test", "Product", FormMethod.Post))
{
<div>
    名称 : @Html.TextBoxFor(x=>x.TestName)
    <input type="submit" value="搜索" />
</div>
}

2、再看一下定义的TestModel对象

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ShoppingMall.Admin.Models.Product
{
    public class TestModel : BaseListModel2<ItemTestModel>
    {
        public string TestName { get; set; }
    }


    public class ItemTestModel
    { 
        
    }
}

基类BaseListModel2的定义如下,该对象继承了ICollection<T>

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ShoppingMall.Admin.Models
{
    public class BaseListModel2<T> :  ICollection<T>
    {
        /// <summary>
        /// 构造方法
        /// </summary>
        public BaseListModel2()
        {
            
        }
        
        #region Count

        /// <summary>
        /// 获取元素的数量
        /// </summary>
        public virtual Int32 Count
        {
            get
            {
                return this.Children.Count;
            }
        }

        #endregion

        #region Children

        /// <summary>
        /// 获取元素的集合
        /// </summary>
        public virtual List<T> Children
        {
            get;
            private set;
        }

        #endregion

        #region Add

        /// <summary>
        /// 将对象添加到集合的结尾处。
        /// </summary>
        /// <param name="item">要添加到集合的末尾处的对象</param>
        public virtual void Add(T item)
        {
            this.Children.Add(item);
        }

        #endregion

        #region Remove

        /// <summary>
        /// 从集合中移除特定对象的第一个匹配项。
        /// </summary>
        /// <param name="item">要从集合中移除的对象</param>
        /// <returns>如果成功移除 item,则为 true;否则为 false。如果在集合中没有找到item,该方法也会返回 false。</returns>
        public virtual Boolean Remove(T item)
        {
            return this.Children.Remove(item);
        }

        #endregion

        #region RemoveAt

        /// <summary>
        /// 移除集合的指定索引处的元素。
        /// </summary>
        /// <param name="index">要移除的元素的从零开始的索引</param>
        public virtual void RemoveAt(Int32 index)
        {
            this.Children.RemoveAt(index);
        }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public int IndexOf(T item)
        {
            return this.Children.IndexOf(item);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        /// <param name="item"></param>
        public void Insert(Int32 index, T item)
        {
            this.Children.Insert(index, item);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Clear()
        {
            this.Children.Clear();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public Boolean Contains(T item)
        {
            return this.Children.Contains(item);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="array"></param>
        /// <param name="arrayIndex"></param>
        public void CopyTo(T[] array, Int32 arrayIndex)
        {
            this.Children.CopyTo(array, arrayIndex);
        }

        /// <summary>
        /// 
        /// </summary>
        public Boolean IsReadOnly
        {
            get { return ((IList)this.Children).IsReadOnly; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public IEnumerator<T> GetEnumerator()
        {
            return this.Children.GetEnumerator();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.Children.GetEnumerator();
        }

        
    }
}

3、定义的controller中的action如下:

 [HttpGet]
        public ActionResult Test()
        {

            return View();
        }

        [HttpPost]
        public ActionResult Test(TestModel model)
        {

            return RedirectToAction("Test");
        }

4、经过调试问题出来了,每次post提交数据model实例都是null,但是如果BaseListModel2<T>不继承 ICollection<T>时model实例是有数据的,请大神们指点是有什么引起的。

 

 

 

 

 

沉默万年的主页 沉默万年 | 菜鸟二级 | 园豆:211
提问于:2014-05-12 09:51
< >
分享
所有回答(1)
0

首先,你的BaseListModel2<T>类应该说是【实现】而非继承ICollection<T>接口。

此外,你碰到的这个问题应该是可枚举接口IEnumerable的实现导致的。具体说就是,每次post提交数据model实例,实际上这有一个过程是,根据提交的数据进行参数类型的实例化及成员赋值的过程,所以我估计关键问题在于你把参数类TestModel的Children属性的set访问器设置成了private,导致Children永远为null。而当你的参数类TestModel继承了可枚举接口IEnumerable,那么它的实例化过程可能会处理可枚举接口的一些特殊处理,例如会调用GetEnumerator()或者Insert()等方法,而你的这些方法实现中都引用了“永远为空”的Children属性,所以可能导致不可预测的问题。

ps.这是我的思考,具体是不是这样导致的,因为现在微软已经将.net库开源啦,所以你可以去看有关源码一探究竟。Good Luck!

cshere | 园豆:188 (初学一级) | 2016-08-19 10:03
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册