【问题标题】:Why is my ViewModel empty on [HttpPost]? .NET MVC 3为什么我的 ViewModel 在 [HttpPost] 上是空的? .NET MVC 3
【发布时间】:2011-10-22 08:03:56
【问题描述】:

我正在尽最大努力在我的 Web 应用程序中正确使用 ViewModel,但我遇到了各种问题。其中之一是,如果我在使用 Create 操作发布后设置断点,我的 viewModel 没有存储我的任何表单值。我一定做错了什么,但我已经尝试了一些事情。包括下面的代码,我将表单项命名为与 viewModel 字段相同的名称,看看是否有帮助。

我还想知道您的视图模型中的确切属性应该代表什么。我看到人们在博客文章中使用不同的东西等等。

如果视图要呈现一个选择列表,我的印象是视图模型应该为此保存一个 IEnumerable SelectListItem,如下所示。然而,我看到人们使用 IEnumerable Entity 来表示选择列表所代表的类型。

有人可以帮我解释一下吗?昨晚我放弃了我的整个业务逻辑,所以我可以重新开始并尝试正确地做。

我的视图模型:

public class ServerCreateViewModel
{
    public int Id { get; set; }

    // CompanyName represents a field in the Company model. I did this to see if
    // it would help with model binding. Beforehand it was Companies to represent the type. I've done the same for the rest of them, so I wont comment on this again.
    public IEnumerable<SelectListItem> CompanyName { get; set; }

    // Represents the Game model.
    public IEnumerable<SelectListItem> GameTitle { get; set; }

    //Represents the Location model, etc...
    public IEnumerable<SelectListItem> City { get; set; }
    public IEnumerable<SelectListItem> NumberOfPlayers { get; set; }
    public IEnumerable<SelectListItem> CurrencyAbbreviation { get; set; }
}

我的控制器操作:

    public ActionResult Create()
    {
        var viewModel = new ServerCreateViewModel();

        viewModel.CompanyName = new SelectList(_dataService.Companies.All(), "Id", "CompanyName");
        viewModel.GameTitle = new SelectList(_dataService.Games.All(), "Id", "GameTitle");
        viewModel.City = new SelectList(_dataService.Locations.All(), "Id", "City");
        viewModel.NumberOfPlayers = new SelectList(_dataService.ServerPlayers.All(), "Id", "NumberOfPlayers");

        return View(viewModel);
    } 

    [HttpPost]
    public ActionResult Create(FormCollection collection, ServerCreateViewModel viewModel)
    {
        try
        {      // I put a breakpoint in here to check the viewModel values.
               // If I dont pass the viewModel into the constructor, it doesnt exist.
               // When I do pass it in, its empty.
            return Content("Success");
        }
        catch
        {
            return Content("Fail");
        }
    }  

我的观点:

@model GameserverCompare.ViewModels.Server.ServerCreateViewModel


@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
    <legend>Server</legend>
    @Html.HiddenFor(m => m.Id)
     <div class="editor-label">
        @Html.LabelFor(model => model.CompanyName)
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(m => Model.CompanyName, Model.CompanyName)
        @Html.ValidationMessageFor(model => model.CompanyName)
    </div>
     <div class="editor-label">
        @Html.LabelFor(model => model.GameTitle)
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(m => Model.GameTitle, Model.GameTitle)
        @Html.ValidationMessageFor(model => model.GameTitle)
    </div>
    <div class="editor-label">
        @Html.LabelFor(model => model.City)
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(m => Model.City, Model.City)
        @Html.ValidationMessageFor(model => model.City)
    </div>
    <div class="editor-label">
        @Html.LabelFor(model => model.NumberOfPlayers)
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(m => Model.NumberOfPlayers, Model.NumberOfPlayers)
        @Html.ValidationMessageFor(model => model.NumberOfPlayers)
    </div>
    <p>
        <input type="submit" value="Create" />
    </p>

</fieldset>
}   

【问题讨论】:

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


    【解决方案1】:

    由于您在表单模型中使用 SelectList 属性,因此您需要使用不同的模型来表示这些列表中的选定值:

    public class ServerCreatePostbackModel
    {
        public int Id { get; set; }
    
        // CompanyName represents a field in the Company model. 
        public string CompanyName { get; set; }
    
        // Represents the Game model.
        public string GameTitle { get; set; }
    
        //Represents the Location model, etc...
        public string City { get; set; }
        public int NumberOfPlayers { get; set; }
        public string CurrencyAbbreviation { get; set; }
    }
    

    让您的 HttpPost 操作将其中之一作为参数。

    哦,请务必将HiddenFor 用于Id 属性,以便它与其他数据一起发回。

    【讨论】:

    • 谢谢,但这是否意味着我仍然需要通过使用 Request.Form 从 POST 中获取值来填充 ServerCreatePostViewModel?
    • 不,ServerCreatePostbackModel 的属性应该自动绑定到提供的表单值。您不必直接访问表单数据。
    • 我想我明白了,所以我的回发模型中的属性类型必须与我的表单将发布的类型相同。即,下拉列表将返回一个字符串值,因此相应的属性也应该是一个字符串(尽管实际上该字符串表示一个 int 引用 Id,例如..公司)。因此,尽管视图模型将捕获字符串,但我必须将其解析为 int 以找到要引用的正确公司(或游戏,或其他)。谢谢!
    • 最后一条评论,经过测试,效果很好。感谢您帮助我理解!
    • @CraigWhitley:实际上,如果属性是 int,模型绑定器将足够智能,可以自动将其转换为 int(例如,在我发布的代码中的 NumberOfPlayers 上)。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 1970-01-01
    • 2013-05-29
    • 2012-06-19
    • 2012-03-08
    相关资源
    最近更新 更多