0

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

Kai
  • 732
  • 1
  • 7
  • 23
  • Please can you explain more clearly the expected behaviour and what isn't happening that you want to happen – Luke May 23 '16 at 08:46
  • 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 May 23 '16 at 09:07
  • Ok, cool so you're missing the Console data. Can you show the structure of `Game` and `Console` – Luke May 23 '16 at 09:09
  • 1
    The model in your view is `GameCreation` which means the model in your post method also needs to be `GameCreation`, not `Game`. –  May 23 '16 at 09:10
  • Well spotted that man! – Luke May 23 '16 at 09:13
  • Thanks! Indeed, but even if I return the GameCreation object, the returned data stays exactly the same (all params except Console). This problem arose from wanting a Game object, which has a Console object as a property. Perhaps Im not using the correct way to reference/bind objects together here? – Kai May 23 '16 at 09:23
  • You need to delete that awful bind attribute. Then read [What is ViewModel in MVC?](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc). A view model should not contain properties which are data models –  May 23 '16 at 09:45
  • 1
    And read my comments to your [last question](http://stackoverflow.com/questions/37343431/objects-referencing-each-other-in-net-mvc). You model requires a property `int SelectedConsole` to bind the selected `Console` to. You cannot bind a ` –  May 23 '16 at 09:49
  • @StephenMuecke: I did, that's why I created a viewModel in the first place. I guess my confusion comes from referencing the objects via an int instead of the objects. But now I see why (because of the binding which you just mentioned). Thanks for the clearance! – Kai May 23 '16 at 09:57
  • 1
    `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) –  May 23 '16 at 10:02

1 Answers1

0

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.

anand
  • 1,559
  • 5
  • 21
  • 45
  • Hey anad, I tried this (along with changing the Bind annotation to include the GameCreation's game and Consoles property. But I still do not receive the Console data. I do receive the other data. I will edit my main question to include the Console and game classes. – Kai May 23 '16 at 09:35