使用MVC3进行后期操作后,嵌套模型会丢失

时间:2011-12-15 15:42:11

标签: c# .net linq asp.net-mvc-3

我正在尝试创建一个RoomType记录。每个RoomType都有一个RoomTypeInfos集合,它们是每种语言的描述。然后,每个RoomTypeInfo都与语言记录相关联。

因此,要创建RoomType,我会为每种语言预加载一个RoomTypeInfo对象。

采取行动:

//
// GET: /RoomType/Create/IdHotel
[HttpGet]
public ActionResult Create(int id)
{
    List<Language> _Languages = __roomTypeRepository.GetLanguages().ToList<Language>();
    RoomType roomType = new RoomType { IdHotel = id };
    roomType.RoomTypeInfos = new System.Data.Linq.EntitySet<RoomTypeInfo>();
    foreach (Language Language in _Languages)
    {
        roomType.RoomTypeInfos.Add(new RoomTypeInfo { Language = Language });
    }
    return View(roomType);
}

发布行动:

//
// POST: /RoomType/Create/
[HttpPost]
public ActionResult Create(RoomType roomType)
{
    try
    {
        if (ModelState.IsValid)
        {
            __roomTypeRepository.InsertRoomType(roomType);
            return RedirectToAction("Index", new { id = roomType.IdHotel });
        }
        else
        {
            return View(roomType);
        }
    }
    catch
    {
        return View(roomType);
    }
}

因此,如果在post操作中模型无效或捕获到异常,则在视图中的@ Model.Language.Name中出现错误,因为Language现在为null。

RoomTypeInfo编辑器模板的代码:

@model DataAccess.RoomTypeInfo
@Html.HiddenFor(model => model.Id)
@Html.HiddenFor(model => model.IdRoomType)
@Html.HiddenFor(model => model.IdLanguage)
<fieldset>
    <legend>@Model.Language.Name</legend>
    <div class="editor-label">
        @Html.LabelFor(model => model.Name)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Name)
        @Html.ValidationMessageFor(model => model.Name)
    </div>
    <div class="editor-label">
        @Html.LabelFor(model => model.Descripcion)
    </div>
    <div class="editor-field">
        @Html.TextAreaFor(model => model.Descripcion, new { Class = "wysiwyg" })
        @Html.ValidationMessageFor(model => model.Descripcion)
    </div>
</fieldset>

RoomType编辑器模板:

@model DataAccess.RoomType
@Html.HiddenFor(model => model.Id)
@Html.HiddenFor(model => model.IdHotel)
<h3>
    Información Básica
</h3>
<div class="editor-field">
    @Html.EditorFor(model => model.RoomTypeInfos)
    @Html.ValidationMessageFor(model => model.RoomTypeInfos)
</div>

我通过查询“语言”表并将其再次设置为每个RoomTypeInfo.Language来修复它,但如果感觉像是一种解决方法。

在这种情况下,最佳做法是什么?

1 个答案:

答案 0 :(得分:2)

我们使用BeginCollectionItem HTML helper authored by Steve Sanderson来实现此目的。在局部视图中,我们将所有输入字段包装在@using(Html.BeginCollectionItem("RoomTypeInfos"))中。

在后台,这会更改输入元素名称和ID,以便默认模型绑定器识别它们并添加到根视图模型(在您的情况下为RoomType)。

代码示例:

@model DataAccess.RoomTypeInfo
@using (Html.BeginCollectionItem("RoomTypeInfos")) 
{
    Html.HiddenFor(model => model.Id)
    Html.HiddenFor(model => model.IdRoomType)
    Html.HiddenFor(model => model.IdLanguage)
    <fieldset>
        <legend>@Model.Language.Name</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Descripcion)
        </div>
        <div class="editor-field">
            @Html.TextAreaFor(model => model.Descripcion, new { Class = "wysiwyg" })
            @Html.ValidationMessageFor(model => model.Descripcion)
        </div>
    </fieldset>
}

另外,如果要确保POST后语言不为空,则应将其添加为隐藏字段:

@Html.HiddenFor(m => m.Language.Name)

这样,它就被默认的模型绑定器绑定到模型。如果您不通过HTTP POST(在某种输入字段中)发送数据,那么您的POST操作方法将必须重新填充它,然后才能返回模型&amp;视图。