如何在MVC 3中将数据从View传递到Controller

时间:2012-02-14 09:16:05

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

我创建了一个包含两个东西的ViewModel,一个联系人和该联系人的电话列表。

我的目标是为新的联系人添加数据,添加一些电话,然后通过Controller操作进行保存。

我为我的联系人编辑了脚手架的Create.cshtml,为手机添加了一个网格。添加了用于创建手机的JavaScript。到目前为止一切都很好。

问题是当我点击“创建”按钮时,我回到控制器,我没有电话。我如何(在视图中)将电话行添加到我的IEnumerable?

修改 在这种情况下,在视图中找出不正确的代码。

我的ViewModel:

public class ContactViewModel
{
    public Contact Contact {get; set;}
    public IEnumerable<Phone> Phones { get; set; }    
}

我的观点:

@model PilotKibsNet.Controllers.ContactViewModel      
<script type="text/javascript" src="../../Scripts/jquery-1.5.1.js"></script>

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

<script type="text/javascript">

    function Add() {
        $("#tbl > tbody:last").append("<tr><td>" + $("#Number").val() + "</td><td>" + $("#Kind").val() + "</td><td></td></tr>");

        $("#Number").val("");
        $("#Kind").val("");
    }

</script>
@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Contact</legend>

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

        <div class="editor-label">
            @Html.LabelFor(model => model.Contact.Address)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Contact.Address)
            @Html.ValidationMessageFor(model => model.Contact.Address)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Contact.City)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Contact.City)
            @Html.ValidationMessageFor(model => model.Contact.City)
        </div>


        <legend>Phone numbers</legend>
        <label>Number :</label>            
        @Html.TextBox("Number")
        <label>Kind :</label>
        @Html.TextBox("Kind")
        <input type="button" value="Add" onclick="Add()" />

        <table id="tbl">
            <tr>
                <th>
                    Phone
                </th>
                <th>
                    Kind
                </th>
                <th></th>
            </tr>

         <tbody>
        </tbody> 
        </table>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

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

然后,在Controller操作中,Contact有数据,但Phone是一个空列表。

    [HttpPost]
    public ActionResult Create(ContactViewModel contactViewModel)
    {
        if (ModelState.IsValid)
        {
            contactViewModel.Contact.id = Guid.NewGuid();

            db.Contacts.AddObject(contactViewModel.Contact);
            db.SaveChanges();
            return RedirectToAction("Index");  
        }

        return View(contactViewModel.Contact);
    }

如何将手机送回服务器?!?

1 个答案:

答案 0 :(得分:2)

您只有那些电话集合的显示模板。根本没有任何值将被发送到服务器。如果用户不应该编辑值或文本框,则可以使用隐藏字段。

另外,我会在视图中用编辑器模板替换这个foreach循环:

if (Model != null)
{
    @Html.EditorFor(x => x.Phones)
}

然后我将定义一个编辑器模板,该模板将为Phones集合的每个元素(~/Views/Shared/EditorTemplates/Phone.cshtml)呈现:

@model Phone
<tr>
    <td>
        @Html.DisplayFor(x => x.Number)
        @Html.HiddenFor(x => x.Number)
    </td>
    <td>
        @Html.DisplayFor(x => x.Type)
        @Html.HiddenFor(x => x.Type)
    </td>
    <td>
        @Html.ActionLink("Edit", "Edit", new { id = Model.id }) |
        @Html.ActionLink("Details", "Details", new { id = Model.id }) |
        @Html.ActionLink("Delete", "Delete", new { id = Model.id })
    </td>
</tr>

我在这里使用了隐藏字段来保留模型的值,这样当您将表单发布到服务器时,它们就会被发送。

如果用户不应该在表中编辑这些值,那么另一个和IMHO更好的方法是简单地从数据库中的POST操作中重新获取它们。