为什么我的视图没有使用我的EditorTemplates文件夹进行创建操作?

时间:2013-10-07 22:15:04

标签: c# asp.net-mvc entity-framework asp.net-mvc-4 razor

在我的MedicalProductController中,我尝试通过将Create传递到视图,使我的DeleteIEnumerable<ViewModel>操作能够在一个页面上创建和删除多个对象。我使用Create操作时使用的方法适用于this stack overflow question中的Edit操作。但它不能用我的create动作,所以我怀疑有些事情是不对的。

问题是页面上没有字段。该页面简单地说:该页面上的“创建”,“保存”(按钮),“返回列表”(可点击链接)。在“创建”和“保存”之间,应该有由下面显示的MedicalProductViewModel.cshtml创建的html编辑器字段和标签。

以下是我的设置。

Create.cshtml

@model IEnumerable<MvcMedicalStore.Models.MedicalProductViewModel>

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>MedicalProduct</legend>
        @Html.EditorFor(m => m)        
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

视图\ MedicalProduct \ EditorTemplates \ MedicalProductViewModel.cshtml

@model MvcMedicalStore.Models.MedicalProductViewModel

@Html.HiddenFor(item => Model.ID)


<div class="editor-label">
    @Html.LabelFor(item => Model.Name)
</div>
<div class="editor-field">
    @Html.EditorFor(item => Model.Name)
    @Html.ValidationMessageFor(item => Model.Name)
</div>

<div class="editor-label">
    @Html.LabelFor(item => Model.Price)
</div>
<div class="editor-field">
    @Html.EditorFor(item => Model.Price)
    @Html.ValidationMessageFor(item => Model.Price)
</div>

<div class="editor-label">
    @Html.LabelFor(item => Model.ID)
</div>
<div class="editor-field">
    @Html.DropDownListFor(item => Model.BrandID, Model.BrandSelectListItem)
    @Html.ValidationMessageFor(item => Model.BrandID)
</div>

MedicalProductController.cs

public class MedicalProductController : Controller
{
    private MvcMedicalStoreDb _db = new MvcMedicalStoreDb();

    public ActionResult Index()
    {
        var productList = _db.Products.ToArray();

        var viewModelList = GetMedicalProductViewModelList(productList);
        return View(viewModelList);
    }

    public IEnumerable<MedicalProductViewModel> GetMedicalProductViewModelList(IEnumerable<MedicalProduct> productList)
    {
        var brandList = _db.Brands.ToArray();

        var mapper = new MedicalProductMapper();

        return mapper.MapMedicalProductViewModel(productList, brandList);            
    }
    public IEnumerable<MedicalProduct> GetMedicalProductList(IEnumerable<MedicalProductViewModel> viewModelList)
    {
        var mapper = new MedicalProductMapper();

        return mapper.MapMedicalProductList(viewModelList);
    }

    //
    // GET: /MedicalSupply/Create

    public ActionResult Create()
    {
        return View();
    }

    //
    // POST: /MedicalSupply/Create

    [HttpPost]
    [ValidateAntiForgeryToken]
    //public ActionResult Create(MedicalProduct medicalProduct)
    public ActionResult Create(IEnumerable<MedicalProductViewModel> productViewModelList)
    {
        var productList = GetMedicalProductList(productViewModelList);

        if (ModelState.IsValid)
        {
            foreach (MedicalProduct product in productList)
                _db.Products.Add(product);

            _db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(productViewModelList);
    }
}

MedicalProductMapper.cs

public class MedicalProductMapper
{

    public IEnumerable<MedicalProductViewModel> MapMedicalProductViewModel(IEnumerable<MedicalProduct> productList, IEnumerable<Brand> brandList)
    {            
        var brandSelectListItem = brandList.Select(b => new SelectListItem()
                                                {
                                                    Text = b.Name,
                                                    Value = b.ID.ToString()
                                                });

        var viewModelList = productList.Select(p => new MedicalProductViewModel() 
                                {
                                    BrandID = p.BrandID,
                                    //BrandName = brandList.SingleOrDefault(b => b.ID == p.BrandID).Name,
                                    BrandSelectListItem = brandSelectListItem,
                                    ID = p.ID,
                                    Price = p.Price,
                                    Name = p.Name
                                });

        return viewModelList;
    }

    public IEnumerable<MedicalProduct> MapMedicalProductList(IEnumerable<MedicalProductViewModel> viewModelList)
    {
        var modelList = viewModelList.ToArray().Select( viewModel => new MedicalProduct()
        {
            Name = viewModel.Name,
            Price = viewModel.Price,
            BrandID = viewModel.BrandID
        });

        return modelList;
    }
}

修改

我的编辑视图与我的创建视图非常相似:

EDIT.cshtml

@model IEnumerable<MvcMedicalStore.Models.MedicalProductViewModel>

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>MedicalProduct</legend>
        @Html.EditorFor(m => m)        
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

2 个答案:

答案 0 :(得分:2)

您的Create()控制器方法将null传递给您的视图,因此editortemplate不会触发。

public ActionResult Create()
{
    return View();
}

如果您传入新的列表&lt;&gt;,那么它将像您的编辑一样工作。

public ActionResult Create()
{
    return View(new List<MedicalProductViewModel>() { new MedicalProductViewModel() });
}

你有没有理由不只是传递一个视图模型而不是列表?您将能够以相同的方式使用编辑器模板。

另外需要注意的是,传入IEnumerable&lt;&gt;可能不是一个好主意。作为你的viewmodel。如果您需要将其他非MedicalProduct属性传递给您的视图,该怎么办?

我会提倡复合视图模型,就像这样。

public class EditMedicalProductViewModel
{
    public IEnumerable<MedicalProductViewModel> MedicalProducts { get; set; }
}

public class CreateMedicalProductViewModel
{
    public MedicalProductViewModel MedicalProduct { get; set; }
}

在您的修改视图中,您可以执行此操作

@Html.EditorFor(m => m.MedicalProducts)

对于您的创建视图,您可以执行此操作

@Html.EditorFor(m=> m.MedicalProduct)   

在您的创建方法中,您应该创建一个新的医疗产品

return View(new CreateMEdicalProductViewModel() { MedicalProduct = new MedicalProductViewModel() } );

答案 1 :(得分:1)

它不起作用,因为您的模型是IEnumerable<MedicalProductViewModel>,但您的编辑器模板适用于MedicalProductViewModel

你可以试试这个:

<fieldset>
    <legend>MedicalProduct</legend>
    @foreach(var item in Model)
    {
        Html.EditorFor(model => item)        
    }
    <p>
        <input type="submit" value="Save" />
    </p>
</fieldset>

但是这可能不会按照你想要的方式格式化字段,因为它会创建大量的编辑器。最简单的方法是重构控制器,以便它允许一次编辑一条记录。