Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my ViewModel empty on [HttpPost]? .NET MVC 3

I'm trying my hardest to use ViewModels correctly in my web application, but I'm running into various problems. One of which, is if I set a breakpoint just after I post using a Create action, my viewModel hasn't stored any of my form values. I must be doing something wrong, but I've tried a few things. Including the code below, where I name the form items the same as the viewModel fields to see if that helps.

I'm also wondering what exactly properties in your viewmodel should represent. I've seen people use different things in blog posts and whatnot.

If the view is going to render a select list, I'm under the impression the viewmodel should hold an IEnumerable SelectListItem for this as below. Yet I've seen people use IEnumerable Entity instead, to represent the type the select list represents.

Can anybody shed some light on this for me? I scrapped my entire business logic last night so I could start a fresh and try and do it correctly.

My ViewModel:

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; }
}

My Controller action:

    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");
        }
    }  

My View:

@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>
}   
like image 251
Kiada Avatar asked Oct 10 '22 16:10

Kiada


1 Answers

Since you're using SelectList properties in the form model, you will need to have a different model to represent the selected values in those lists:

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; }
}

Have your HttpPost action take one of these as its argument.

Oh, and be sure to use HiddenFor for the Id property, so it gets sent back with the other data.

like image 54
StriplingWarrior Avatar answered Oct 13 '22 11:10

StriplingWarrior