【问题标题】:MVC 4 postback empty viewmodelMVC 4 回发空视图模型
【发布时间】:2014-08-15 10:30:08
【问题描述】:

好的,所以有很多关于这个的问题,但我似乎无法让它工作。应该很简单,但我摸不着头脑。

控制器:

[HttpPost]
public ActionResult Edit(BookingIndexViewModel vm) // Also tried BookingViewModel
{
    return View();
}

容器视图模型:

public class BookingIndexViewModel
{
    public int id { get; set; }

    public List<BookingViewModel> bookings { get; set; }
    public List<SelectListItem> allAttendances { get; set; }
}

预订视图模型(我真正感兴趣的虚拟机)

public class BookingViewModel
{
    public int id { get; set; }
    public int referralId { get; set; }
    public int attendanceId { get; set; }
}

观点

@model Project.ViewModels.BookingIndexViewModel
@using Project.ViewModels

<fieldset>
    <legend>Registered patients</legend>
    @if (Model.bookings.Count < 1)
    {
        <div>None currently registered</div>
    }
    else
    {
    <table>
        <tr>
            <th>
                <span class="display-label">@Html.LabelFor(model => model.bookings[0].forenames)</span>
            </th>
            <th>
                <span class="display-label">@Html.LabelFor(model => model.bookings[0].surname)</span>
            </th>
            <th>
                <span class="display-label">@Html.LabelFor(model => model.bookings[0].dob)</span>
            </th>
            <th>
                <span class="display-label">@Html.LabelFor(model => model.bookings[0].attendance</span>
            </th>
        </tr>

        @{
            foreach (BookingViewModel b in Model.bookings)
            {
                using (Html.BeginForm("Edit", "Booking"))
                {
                    @Html.HiddenFor(x => x.id)
                    <tr>
                        <td>
                            <span class="display-field">@b.forenames</span>
                        </td>
                        <td>
                            <span class="display-field">@b.surname</span>
                        </td>
                        <td>
                            <span class="display-field">@String.Format("{0:dd/MM/yyyy}", b.dob)</span>
                        </td>
                        <td>
                            @Html.DropDownListFor(model => b.attendanceStatusId, Model.allAttendances)
                        </td>
                        <td>
                            <input type="submit" value="Save" />
                        </td>
                    </tr>
                }
            }
        }
    </table>
    }
</fieldset>

因此视图接受容器视图模型BookingIndexViewModel 并为每个持有的BookingViewModel 创建一个表单。提交后,我希望它使用修改后的BookingViewModel 传回容器视图模型,但它始终为空。我也尝试过期待以相同结果修改的单个BookingViewModel。 MVC 是否提交与给定视图的类型或从表单块中推断的类型相同类型的水合视图模型?

我从视图中检索到的唯一重要值是修改后的 attendanceId(应由下拉帮助程序填充)和预订 ID。

【问题讨论】:

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


    【解决方案1】:

    这个问题几乎肯定与你如何渲染这个有关

    foreach (BookingViewModel b in Model.bookings)
    {
        @Html.HiddenFor(x => x.id);
        ...
        @Html.DropDownListFor(model => b.attendanceStatusId, Model.allAttendances)
    }
    

    上面的 HTML 看起来像

    <form ... >
    <input type="hidden" name="BookingIndexViewModel.id" ... />
    <select name="BookingViewModel.attendanceStatusId" ... />
    </form>
    ...
    <form ... >
    <input type="hidden" name="BookingIndexViewModel.id" ... />
    <select name="BookingViewModel.attendanceStatusId" ... />
    </form>
    ...
    

    MVC 模型绑定器使用name 字段将数据绑定到目标模型,在您的场景中您有BookingIndexViewModel,您应该找到至少您的id 字段已填充,但您的 List&lt;BookingViewModel&gt; 肯定会为空。

    不完全清楚您要做什么,我怀疑您想要显示整个预订信息,但只发回个人BookingViewModel?如果是这种情况,以下应该可以工作

    控制器

    [HttpPost]
    public ActionResult Edit(BookingViewModel model)
    {
        ...
    }
    

    查看

    foreach (BookingViewModel b in Model.bookings)
    {
        using (Html.BeginForm("Edit", "Booking"))
        {
            @Html.HiddenFor(b => b.id);
            @Html.HiddenFor(b => b.referralId);
            @Html.DropDownListFor(b => b.attendanceId, Model.allAttendances)
        }
    }
    

    【讨论】:

    • 小问题,如果已经在 foreach 中定义了“b”变量,如何为 HiddenFor 标签使用?
    【解决方案2】:

    在我看来 你应该知道模型绑定在 asp.mvc 中是如何工作的,这里有一个很好的链接,提供了关于 asp.mvc 模型绑定的详细信息 http://msdn.microsoft.com/en-us/magazine/hh781022.aspx 虽然文章很长,但它会帮助您了解模型绑定的工作原理

    除此之外,您还应该查看 html 页面以了解您的 html 控件是如何命名的 根据您在剃须刀页面中查看模型,由剃须刀助手提供

    【讨论】:

    • 感谢您提供的重要信息。
    【解决方案3】:

    在 ASP.NET MVC 中没有“回发”。它像 HTTP 一样是无状态的。 如果您想向服务器提交内容,则必须将其包含在表单中。

    我认为将整个对象列表从视图模型传回服务器并不是一个好主意。 您有一个Edit 操作。将其参数类型更改为BookingViewModel。这将允许您编辑单个预订项目。然后在表单中添加@Html.HiddenFor(x =&gt; x.referralId) 之类的内容。

    【讨论】:

    • 我了解 MVC 是无状态的,也许我使用了不正确的术语,但我在表单中包含了我想要的所有内容。此外,由于每个 BookingViewModel 都有自己的表单,我不会将整个列表发送回服务器 - 检查视图。
    • 明白。提交表单时,缺少哪个字段?
    • 一切都丢失了,它不会绑定提交数据中的任何属性 - 直到我用通常的 for 循环替换了 foreach!
    【解决方案4】:

    MVC 实际上并没有特别提交任何东西,也不知道您预期的ViewModel 将被提交给一个动作。它不会像“视图状态”一样重新发布您的ViewModel

    最终,它只会在表单中发布 html 中的任何输入元素,并且当调用 Action 方法时,它会尝试从 POST 中包含的值中提取(使用绑定器)您声明为参数的任何内容。

    在您的情况下,您似乎只会提交隐藏的 IdattendanceStatusId。如果您查看浏览器的实际网络流量,您会注意到正在发布的内容。

    因此,您的 Action 应该期望具有两个与这些输入字段名称匹配的属性的不同 ViewModel。

    【讨论】:

      【解决方案5】:

      在查看了一个类似的问题后,我尝试使用for(){} 而不是foreach(){},现在它可以工作了。我认为这与每种循环中元素的可变性有关。

      【讨论】:

      • 为什么是减号?至少有礼貌留下一个理由。
      猜你喜欢
      • 1970-01-01
      • 2015-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-13
      • 1970-01-01
      相关资源
      最近更新 更多