视图模型用的SelectList在ASP.NET MVC2结合 [英] ViewModel with SelectList binding in ASP.NET MVC2

查看:200
本文介绍了视图模型用的SelectList在ASP.NET MVC2结合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现一个编辑视图模型我叫产品LINQ2SQL实体。它链接到的品牌列表的外键。

I am trying to implement an Edit ViewModel for my Linq2SQL entity called Product. It has a foreign key linked to a list of brands.

目前,我通过填充的ViewData的品牌榜,并使用DropDownListFor,这样的:

Currently I am populating the brand list via ViewData and using DropDownListFor, thus:

<div class="editor-field">
    <%= Html.DropDownListFor(model => model.BrandId, (SelectList)ViewData["Brands"])%>
    <%= Html.ValidationMessageFor(model => model.BrandId) %>
</div>

现在我想要重构视图中使用强类型的视图模型和Html.EditorForModel():

Now I want to refactor the view to use a strongly typed ViewModel and Html.EditorForModel():

<% using (Html.BeginForm()) {%>
    <%= Html.ValidationSummary(true) %>

    <fieldset>
        <legend>Fields</legend>

        <%=Html.EditorForModel() %>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>

<% } %>

在我的编辑视图模型,我有以下几点:

In my Edit ViewModel, I have the following:

public class EditProductViewModel
{
    [HiddenInput]
    public int ProductId { get; set; }

    [Required()]
    [StringLength(200)]
    public string Name { get; set; }

    [Required()]
    [DataType(DataType.Html)]
    public string Description { get; set; }

    public IEnumerable<SelectListItem> Brands { get; set; }

    public int BrandId { get; set; }

    public EditProductViewModel(Product product, IEnumerable<SelectListItem> brands)
    {
        this.ProductId = product.ProductId;
        this.Name = product.Name;
        this.Description = product.Description;
        this.Brands = brands;
        this.BrandId = product.BrandId;
    }
}

该控制器的设置,像这样:

The controller is setup like so:

public ActionResult Edit(int id)
{
    BrandRepository br = new BrandRepository();

    Product p = _ProductRepository.Get(id);
    IEnumerable<SelectListItem> brands = br.GetAll().ToList().ToSelectListItems(p.BrandId);

    EditProductViewModel model = new EditProductViewModel(p, brands);

    return View("Edit", model);
}

产品ID,名称和描述正确生成视图显示,但选择列表没有。该品牌名单肯定包含数据。

The ProductId, Name and Description display correctly in the generated view, but the select list does not. The brand list definitely contains data.

如果我这样做,我认为,选择列表是可见的:

If I do the following in my view, the SelectList is visible:

<% using (Html.BeginForm()) {%>
    <%= Html.ValidationSummary(true) %>

    <fieldset>
        <legend>Fields</legend>

        <%=Html.EditorForModel() %>

        <div class="editor-label">
            <%= Html.LabelFor(model => model.BrandId) %>
        </div>
        <div class="editor-field">
            <%= Html.DropDownListFor(model => model.BrandId, Model.Brands)%>
            <%= Html.ValidationMessageFor(model => model.BrandId) %>
        </div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>

<% } %>

我是什么做错了吗?是否EditorForModel()一般不支持的SelectList?我缺少某种DataAnnotation的?

What am I doing wrong? Does EditorForModel() not generically support the SelectList? Am I missing some kind of DataAnnotation?

我似乎无法找到的ViewModels,帮助的SelectList使用任何例子。我真的难住了。 这个答案似乎是接近,但并没有帮助。

I can't seem to find any examples of SelectList usage in ViewModels that help. I'm truly stumped. This answer seems to be close, but hasn't helped.

推荐答案

帮派

Html.EditorForModel()的方法是不够聪明,以匹配 BrandId 品牌选择列表中。

the Html.EditorForModel() method isn't smart enough to match BrandId with the Brands select list.

首先,你不能使用快捷键 EditorForModel()方法。

你必须创建这样自己的HTML模板。

First, you can't use the shortcut EditorForModel() method.
You have to create your own HTML template like this.

<% using (Html.BeginForm()) { %>

    <div style="display:none"><%= Html.AntiForgeryToken() %></div>

    <table>
        <tr>
            <td><%= Html.LabelFor(m => m.Name) %></td>
            <td><%= Html.EditorFor(m => m.Name) %></td>
        </tr>

        <tr>
            <td><%= Html.LabelFor(m => m.Description) %></td>
            <td><%= Html.EditorFor(m => m.Description) %></td>
        </tr>

        <tr>
            <td><%= Html.LabelFor(m => m.BrandId) %></td>
            <td><%= Html.EditorFor(m => m.BrandId) %></td>
        </tr>
    </table>
<% } %>




其次,你需要改变你的操作方法。



Second, you need to change your Action method.

[ImportModelStateFromTempData]
public ActionResult Edit(int id)
{
    BrandRepository br = new BrandRepository();

    Product p = _ProductRepository.Get(id);
    ViewData["BrandId"] = br.GetAll().ToList().ToSelectListItems(p.BrandId);

    EditProductViewModel model = new EditProductViewModel(p);

    return View("Edit", model);
}




第三,你需要更新你的 EditProductViewModel 类。

public class EditProductViewModel
{
    [Required]
    [StringLength(200)]
    public string Name { get; set; }

    [Required()]
    [DataType(DataType.Html)]
    public string Description { get; set; }

    [Required] // this foreign key *should* be required
    public int BrandId { get; set; }

    public EditProductViewModel(Product product)
    {
        this.Name = product.Name;
        this.Description = product.Description;
        this.BrandId = product.BrandId;
    }
}

到现在为止,你可能会说:?老兄,哪里是我的的[ProductID] 属性

简答题:你不需要它。

By now, you are probably saying: Dude, where is my [ProductId] property?".
Short Answer: You don't need it!

您的视图中呈现的HTML已指向编辑的操作方法与适当的产品编号,如下图所示。

The HTML rendered by your view already points to "Edit" action method with an appropriate "ProductId" as shown below.

<form action="/Product/Edit/123" method="post">
    ...
</form>

这是您的HTTP POST操作方法,并它接受2个参数。

标识来自的&lt;形式为GT;标签的action属性。

This is your HTTP POST action method and it accepts 2 parameters.
The "id" comes from the <form> tag's action attribute.

[HttpPost, ValidateAntiForgeryToken, ExportModelStateToTempData]
public ActionResult Edit(int id, EditProductViewModel model)
{
    Product p = _ProductRepository.Get(id);

    // make sure the product exists
    // otherwise **redirect** to [NotFound] view because this is a HTTP POST method
    if (p == null)
        return RedirectToAction("NotFound", new { id = id });

    if (ModelState.IsValid)
    {
        TryUpdateModel<Product>(p);
        _ProductRepository.UpdateProduct( p );
    }

    return RedirectToAction("Edit", new { id = id });
}

ExportModelStateToTempData ImportModelStateFromTempData 是非常有用的。

这些属性用于PRG(邮政重定向获取)模式。

The ExportModelStateToTempData and ImportModelStateFromTempData are very useful.
Those attributes are used for PRG (Post Redirect Get) pattern.

卡子门祖尔·拉希德
阅读数据修改此使用PRG模式在这个博客帖子部分
http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx





好吧,这个数据绑定code不是我喜欢的做事方式。




Okay, this data bind code is not my favorite way of doing things.

TryUpdateModel<Product>( p );

我最喜欢做的方式,它是有一个独立 接口纯数据绑定。

public interface IProductModel
{
    public string Name {get; set;}
    public string Description {get; set;}
    public int BrandId {get; set;}
}

public partial class Product : IProductModel
{
}

public partial class EditProductViewModel : IProductModel
{
}

这是我将如何更新我的数据绑定code。

And this is how I will update my data binding code.

TryUpdateModel<IProductModel>( p );

这是什么帮助是它使简单对我来说,数据绑定后,从数据回我的模型对象。
此外,它使得它更安全,因为你只绑定要绑定的数据。仅此而已,无所不及。

What this helps is it makes it simple for me to data bind my model objects from post back data. Additionally, it makes it more secure because you are only binding the data that you want to bind for. Nothing more, nothing less.

让我知道,如果你有任何问题。

Let me know if you have any question.

这篇关于视图模型用的SelectList在ASP.NET MVC2结合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆