0
votes

I have the following controller:

 public class GamesController : Controller
    {
        private AppDBContext db = new AppDBContext();
        private ConsoleBuilder cb = new ConsoleBuilder();

        public ActionResult Create()
        {
            var gc = new GameCreation();
            gc.Consoles = cb.BuildList(db);       
            return View(gc);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "ID,Title,ReleaseDate,Genre,Console")] Game game)
        {
            if (ModelState.IsValid)
            {
                db.Games.Add(game);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(game);
        }

Relevant portion of create view:

@model MyOwnWebsiteASP4dot6.ViewModels.GameCreation

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>


@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Game</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">

        <div class="form-group">
            @Html.LabelFor(model => model.game.Genre, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.game.Genre, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.game.Genre, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.game.Console, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
              @*@Html.EditorFor(model => model.Console.Title, new { htmlAttributes = new { @class = "form-control" } })*@
                @Html.DropDownListFor(model => model.game.Console, Model.Consoles)
                @Html.ValidationMessageFor(model => model.game.Console.Title, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Now I put a breakpoint at the start of the [HttpPost] Create function. At this point I receive all data, except the Console is null. (note that cb.BuildList returns a simple selectlist built for testing this. The list is loaded correctly into the view).

Why does this not work?

Classes:

public class Game
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public Console Console { get; set; }
    }

public class Console
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public DateTime ReleaseDate { get; set; }
        public string Company { get; set; }
    }

public class GameCreation
    {
        public Game game { get; set; }
        public SelectList Consoles { get; set; }
    }

The sole reason for the GameCreation class is that I want to have access to the Consoles in my view, so that I can create a dropdownlist for the user to select one of the consoles

1
Please can you explain more clearly the expected behaviour and what isn't happening that you want to happen - Luke
Well I want to create new Game objects. So when I click the submit in the create view shown above, I expect to receive all the form's input fields as properties of the Game object which is the input for the HttpPost Create function. I do receive all form fields, except the Console property. I other words: The create view itself contains all data and is correct. It however does not send all the data back to the HttpPost create method. - Kai
The model in your view is GameCreation which means the model in your post method also needs to be GameCreation, not Game. - user3559349
And read my comments to your last question. You model requires a property int SelectedConsole to bind the selected Console to. You cannot bind a <select> (which posts back a single value) to a complex object. - user3559349
GameCreation should contain properties string Title, DateTime ReleaseDate, string Genre, int SelectedConsole and SelectList Consoles (and int? ID if you aslo use it for editing) - user3559349

1 Answers

0
votes

Change your model in the create post method to GameCreation. Like the code below

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "ID,Title,ReleaseDate,Genre,Console")] GameCreation game)
        {
            if (ModelState.IsValid)
            {
                db.Games.Add(game);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(game);
        }

because you are sending GameCreation model from create get method and in view page you are using the same model. but in the post method you are using different model Game. Thats the problem.