Add [HttpPost]方法上的ViewModel为空

时间:2012-05-17 17:39:45

标签: asp.net asp.net-mvc-3 viewmodel

我关注ViewModel

public class CategoryViewModel
{
    public Category Category { get; set; }
    public IList<Category> Categories { get; set; }
    public IList<Product> Products { get; set; }

    public IEnumerable<SelectListItem> CategorySelectItems
    {
        get { var ret = new List<SelectListItem>();
        if(Categories==null)
            return ret;

            ret.AddRange(Categories.Where(x => (Category == null || x.Id != 
                        Category.Id)).Select(category => new SelectListItem 
                                     { Text = category.Name, Value = 
                                        category.Id.ToString()}));
            return ret;
        }
    }

    public CategoryViewModel(){}
}

以下是控制器:

namespace mysite.com.Controllers{
    public class CategoryController : Controller{
        private IRepository<Category> _repository;
        private IRepository<Product> _productRepo;
        private CategoryViewModel _categoryViewModel;

        public CategoryController(){
            _repository = new CategoryRepository();
            _productRepo = new ProductRepository();
        }

        [HttpGet]
        public ActionResult Index(){
           return View(new CategoryViewModel{Categories=_repository.GetAll()});
        }

        [HttpGet]
        public ActionResult Add(){
            return View(new CategoryViewModel{
           Category = new Category(), Categories= _repository.GetAll()});
        }

        [HttpPost]
        public ActionResult Add(CategoryViewModel category){
            if (ModelState.IsValid){
                _repository.Save(category.Category);
                return RedirectToAction("Index");
            }
            return View(category);
        }
    }
}

这是我认为的代码:

@model mysite.com.ViewModels.CategoryViewModel

@using (Html.BeginForm("Add", "Category", FormMethod.Post))
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Add Category</legend>
        @Html.HiddenFor(x => x.Category.Id)
        <div class="editor-label">
            @Html.LabelFor(x => x.Category.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(x => x.Category.Name)
            @Html.ValidationMessageFor(x => x.Category.Name)
        </div>
        <div class="editor-label">
            @Html.LabelFor(x => x.Category.ParentCategory)
        </div>
        <div class="editor-field">
            @Html.DropDownList("ParentCategory", 
                     Model.CategorySelectItems,"--select parent category--")
            @Html.ValidationMessageFor(x => x.Category.Name)
        </div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

但是在我的控制器的[HttpPost] Add方法中,category对象(类型CategoryViewModel)是空的:(

我做错了什么?

2 个答案:

答案 0 :(得分:1)

我认为你的回报太快了:

if(Categories==null)
        **return ret;**

        ret.AddRange(Categories.Where(x => (Category == null || x.Id != 
                    Category.Id)).Select(category => new SelectListItem 
                                 { Text = category.Name, Value = 
                                    category.Id.ToString()}));
        return ret;
    }

答案 1 :(得分:1)

您的模型无法反序列化。您的模型只能在没有很多帮助的情况下反序列化原始属性和原始属性集合,并且通常不值得帮助。

你的模型应该是这样的:

public class CategoryAddModel
{
    //these values are used to populate the view, but will not deserialize
    public IList<Category> AvailableCategories { get; set; }

    //these values are deserializable
    public int CategoryId {get;set;}
    public string CategoryName {get;set;}
    public int ParentCategory {get;set;}
}

public class CategoryIndexModel
{
    public IList<Category> Categories { get; set; }
}

您的Add.cshtml视图看起来像这样:

@model mysite.com.ViewModels.CategoryAddModel

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Add Category</legend>
        @Html.HiddenFor(x => x.CategoryId)
        <div class="editor-label">
            @Html.LabelFor(x => x.CategoryName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(x => x.CategoryName)
            @Html.ValidationMessageFor(x => x.CategoryName)
        </div>
        <div class="editor-label">
            @Html.LabelFor(x => x.Category.ParentCategory)
        </div>
        <div class="editor-field">
            @Html.DropDownList("ParentCategory", 
                new SelectList(Model.AvailableCategories, "Id", "Name"),
                "--select parent category--")
            @Html.ValidationMessageFor(x => x.ParentCategory)
        </div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

您的Index.cshtml视图应该类似于:

@model mysite.com.ViewModels.CategoryIndexModel
@Html.ActionLink("Add Category", "Add")
<ul>
@foreach(var item in Model.Categories)
{
    <li> @{ // List your categories, hyperlinks to editing pages } </li>
}
</ul>

您的CategoryController.cs应如下所示:

namespace mysite.com.Controllers{
    public class CategoryController : Controller
    {
        private IRepository<Category> _repository = new CategoryRepository();
        private IRepository<Product> _productRepo = new ProductRepository();

        public ActionResult Index()
        {
            var model = new CategoryIndexModel
            {
                Categories=_repository.GetAll()
            };

            return View(model);
        }

        public ActionResult Add()
        {
            var model = new CategoryAddModel()
            {
                AvailableCategories = _repository.GetAll()
            };
            return View(model);
        }

        [HttpPost]
        public ActionResult Add(CategoryAddModel model){
            if (ModelState.IsValid)
            {
                //TODO: (varies based on your repository model)
                //create a Category object from the model and persist it here.

                return RedirectToAction("Index");
            }
            //the complex collection does not return with the model; repopulate it here.
            model.AvailableCategories = _repository.GetAll()
            return View(model);
        }
    }
}

这可以让你进入你正在寻找的一般领域。