【问题标题】:Strongly typed ViewModel in POST action method contains only null valuesPOST 操作方法中的强类型 ViewModel 仅包含空值
【发布时间】:2009-04-14 16:14:57
【问题描述】:

我正在尝试使用接收自定义形状的 ViewModel 类的强类型视图来实现我的编辑操作方法。换句话说,我想要一个强类型的 ViewModel,它包含应该编辑的 Linq 实体以及应该在视图中显示的一些其他对象。

我可以在调用 GET Edit 操作方法时看到视图,但是强类型的 POST 操作方法只接收一个带有空参数的 ViewModel 类,我不知道如何检索 POST 参数。

视图模型如下所示:

//my custom-shaped ViewModel
public class CustomersFormViewModel
{
    public SelectList AccountTypesDropDownBox;
    public SelectList CountriesDropDownBox;
    public Customer Customer;
}

动作方法如下:

//
// GET: /CustomersController/Edit   

public ActionResult Edit(int ID)
{
   var model = new CustomersFormViewModel
                    {
                        Customer = repository.Load(ID.Value),
                        CountriesDropDownBox = GetCountries(),
                        AccountTypesDropDownBox = GetAccountTypes()
                    };
    return View(model);
}

//
// POST: /CustomersController/Edit  

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(CustomersFormViewModel model)
{
    //THE NEXT LINE THROWS!!!
    Debug.Assert(Model.Customer!=null);
    return View(model);
}

这是我的编辑视图:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/CustAdminMaster.master"
    Inherits="System.Web.Mvc.ViewPage<Zeiterfassung.Controllers.CustomersController+CustomersFormViewModel>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    NewEdit
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>
        NewEdit</h2>
    <%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
    <% using (Html.BeginForm())
       {%>
    <fieldset>
        <legend>Fields</legend>
        <p>
            <label for="FirstName">FirstName:</label>
            <%= Html.TextBox("FirstName",Model.Customer.FirstName) %>
            <%= Html.ValidationMessage("FirstName", "*") %>
        </p>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
    <% } %>
    <div>
        <%=Html.ActionLink("Back to List", "Index") %>
    </div>
</asp:Content>

我也尝试了带有 formValues 参数的 POST 操作方法,但视图模型仍然不包含发布的参数:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int ID, FormCollection formValues)
{
      CustomersFormViewModel model = new CustomersFormViewModel();            
      UpdateModel(model);
      //THE NEXT LINE STILL THROWS
      Debug.Assert(model.Customer!=null);
      return View("NewEdit",model);
}

到目前为止,我发现的唯一方法是编写自己的代码,从 FormCollection 中获取发布的参数并相应地更新我的自定义 ViewModel。但这种方法似乎有点原始。真的没有更好的方法吗?

编辑:我刚刚按照 tvanfosson 的建议在视图中尝试了不同的语法,但问题仍然没有改变:

<label for="Customer.FirstName">FirstName:</label>
    <%= Html.TextBox("Customer.FirstName") %>
    <%= Html.ValidationMessage("Customer.FirstName", "*") %>

【问题讨论】:

    标签: asp.net-mvc


    【解决方案1】:

    您需要根据模型中的前缀来命名您的字段。此外,您需要修改视图模型以使用属性而不是字段。默认模型绑定器仅在绑定时查看模型上的公共属性。

        <label for="Customer.FirstName">FirstName:</label>
        <%= Html.TextBox("Customer.FirstName") %>
        <%= Html.ValidationMessage("Customer.FirstName", "*") %>
    

    这样模型绑定器就知道如何将表单参数与模型的适当组件和相关属性相关联。

    【讨论】:

    • 感谢您的回复! “Customer.FirstName”不起作用,因为 Customer 是我的模型的一部分,但不是模型的一部分。我假设您的意思是 Model.Customer.FirstName 并且我已经尝试过了(请参阅我的帖子编辑),但问题仍然没有改变。
    • 客户是模型​​的属性,因此使用“Customer.FirstName”是合适的。它将使用反射来查找模型上的“客户”属性,然后是其上的“名字”属性。如果找到匹配的属性,您也不需要提供将从模型中检索到的值
    • 我刚刚将您帖子中的确切行粘贴到我的视图中。问题没有改变。另外,我尝试在 GET 操作方法中将 FirstName 设置为“test”。在浏览器中查看视图时输入字段为空,因此您建议的语法一定有问题
    • 我在我的一个观点中正是使用这种方法。我的视图模型包括参与者、自我联系人和紧急联系人。我将 Participant.UserName 用于模型的 Participant 元素上的 UserName 属性,所以我知道它有效。
    • 注意:在 Create() 上,我确实使用模型作为输入参数。在更新时,我将 id 作为参数传递并使用 UpdateModel 而不是模型绑定。我使用 LINQ,所以无论如何我都必须从数据库中获取相应的模型,并且使用 UpdateModel 比从模型参数更新更容易。
    【解决方案2】:

    已经有一段时间了,但这个问题确实没有答案。

    在我发现我的 viewmodel 上的 auto 属性有一个私有集之前,我一直在篡改同样的问题。

    查看您的视图模型,您缺少自动属性 ​​get 和 setter!

    因此相应地更改您的视图模型:

    public class CustomersFormViewModel
    
        {
            public SelectList AccountTypesDropDownBox {get; set;}
            public SelectList CountriesDropDownBox {get; set;}
            public Customer Customer {get; set;}
        }
    

    【讨论】:

    • 你是对的,但是,tvanfosson 大约早 8 个月 ;-)
    • 也偶然发现了这一点,尽管我没有看到 tvanfosson 建议在哪里检查私人二传手。无论如何,从私人设置切换到设置工作。谢谢伊泰语。
    【解决方案3】:

    试试

    UpdateModel(model, "Customer");
    

    也可以看看这里:

    UpdateModel prefix - ASP.NET MVC

    如果还是不行,在UpdateModel之后设置断点。如果它没有完成这项工作,请在 quickWatch(ctrl+alt+q) 中尝试调用 UpdateModel 的不同组合。

    如果它仍然不起作用,请连接源并调试一下:)。你会学到一些新东西,然后你会告诉我们:)。然后大家就开心了。

    祝你好运。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-01
      • 1970-01-01
      • 2010-11-30
      • 2023-03-30
      • 2011-03-08
      • 1970-01-01
      相关资源
      最近更新 更多