Почему моя ViewModel пуста на [HttpPost]? .NET МВК 3

Я изо всех сил стараюсь правильно использовать ViewModels в своем веб-приложении, но сталкиваюсь с различными проблемами. Один из них: если я устанавливаю точку останова сразу после публикации с помощью действия «Создать», моя модель представления не сохраняет никаких значений моей формы. Должно быть, я делаю что-то не так, но я пробовал несколько вещей. Включая приведенный ниже код, где я называю элементы формы так же, как и поля 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>
}   

person Kiada    schedule 22.10.2011    source источник


Ответы (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, чтобы оно было отправлено обратно с другими данными.

person StriplingWarrior    schedule 22.10.2011
comment
Спасибо, но значит ли это, что мне все равно придется получать значения из POST, используя Request.Form для заполнения ServerCreatePostViewModel? - person Kiada; 22.10.2011
comment
Нет, свойства ServerCreatePostbackModel должны автоматически привязываться к предоставленным значениям формы. Вам не нужно напрямую обращаться к данным формы. - person StriplingWarrior; 22.10.2011
comment
Я думаю, что понял вас, поэтому типы свойств в моей модели обратного сообщения должны быть такими же, как и типы, которые будет публиковать моя форма. То есть раскрывающийся список вернет строковое значение, поэтому соответствующее свойство также должно быть строкой (хотя на самом деле строка представляет собой идентификатор ссылки int, скажем, для компании). Таким образом, хотя модель представления захватит строку, мне придется разобрать ее в целое число, чтобы найти правильную компанию для ссылки (или игру, или что-то еще). Спасибо! - person Kiada; 22.10.2011
comment
Последний комментарий, проверил его, и он отлично работает. Спасибо, что помогли мне понять! - person Kiada; 22.10.2011
comment
@CraigWhitley: На самом деле, если свойство имеет тип int, связыватель модели будет достаточно умен, чтобы автоматически преобразовать его в int (например, для NumberOfPlayers в опубликованном мной коде). - person StriplingWarrior; 22.10.2011