0

Suppose the following domain model.

public class SystemRequirement
{
   public int SystemRequirementID { get; set; }
   public Platforms Platform { get; set; }
   public string CPU { get; set; }
   public string RAM { get; set; }
   public string Dsiplay { get; set; }
   public string Discription { get; set; }

   public int GameID { get; set; }
   public virtual Game Game { get; set; }
}


public class Game
{
    public int GameID { get; set; }
    public string Name { get; set; }
    public Genres Genre { get; set; }
    public DateTime ReleaseDate { get; set; }
    public bool Multiplay { get; set; }
    public string About { get; set; }

    public virtual List<SystemRequirement> SystemRequirements { get; set; }
}

public class GameSystemViewModel
{
    public Game Game { get; set; }
    public SystemRequirement SystemRequirement { get; set; }
}

I want to make make a form which allows to add a new game which contains its system requirement too.

enter image description here

@model KeyStore.WebUI.Models.GameSystemViewModel

@{
    ViewBag.Title = "Add";
    Layout = "~/Views/Shared/_AdminLayout.cshtml"; 
}


<div class="container">
    @using (Html.BeginForm("Add", "GameAdmin", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        <div class="panel">
            <div class="panel-heading">
                <h3>Add New Game</h3>
            </div>

            <div class="panel-body">

                @Html.LabelFor(m => m.Game.Name)
                @Html.TextBoxFor(m => m.Game.Name)

                @Html.LabelFor(m => m.Game.Genre)
                @Html.TextBoxFor(m => m.Game.Genre)

                @Html.LabelFor(m => m.Game.ReleaseDate)
                @Html.TextBoxFor(m => m.Game.ReleaseDate)

                @Html.LabelFor(m => m.Game.Multiplay)
                @Html.CheckBoxFor(m => m.Game.Multiplay)

                @Html.LabelFor(m => m.Game.About)
                @Html.TextAreaFor(m => m.Game.About)


            </div>
        </div>

        <div class="panel">
            <div class="panel-heading">
                <h3>System Requirements</h3>
            </div>

            <div class="panel-body">

                @Html.LabelFor(m => m.SystemRequirement.Platform)
                @Html.TextBoxFor(m => m.SystemRequirement.Platform)

                @Html.LabelFor(m => m.SystemRequirement.CPU)
                @Html.TextBoxFor(m => m.SystemRequirement.CPU)

                @Html.LabelFor(m => m.SystemRequirement.RAM)
                @Html.TextBoxFor(m => m.SystemRequirement.RAM)

                @Html.LabelFor(m => m.SystemRequirement.Dsiplay)
                @Html.TextBoxFor(m => m.SystemRequirement.Dsiplay)


                @Html.LabelFor(m => m.SystemRequirement.Discription)
                @Html.TextAreaFor(m => m.SystemRequirement.Discription)


            </div>
        </div>

        <div class="panel-footer">
            <input type="submit" value="Save" class="btn btn-primary" />
        </div>

    }
</div>

My controller class has these three actions.

  1. Add: to make game view
  2. [HttpPost]Add: to get the object and save them in a db using linq

Controller code:

public ViewResult Add()
{
  GameSystemViewModel g = new GameSystemViewModel();
  g.Game = new Game();
  g.SystemRequirement = new SystemRequirement();
  return View(g);
}


[HttpPost]
public ActionResult Add(GameSystemViewModel g)
{
  Game mygame = new Game();
  mygame = g.Game;
  mygame.SystemRequirements.Add(g.SystemRequirement);
  gameRepository.Save(mygame);
  return RedirectToAction("Add");
}

but when the form is posted the following error occurs. As you see in Locals SystemRequirement is NOT NULL.

enter image description here

What is the problem and how can I fix it?

  • 2
    You may need to create a ViewModel which will the combination of both models and then use it in your View and Controller – Amal Dev May 19 '15 at 06:36
  • have a look at http://stackoverflow.com/questions/30196865/mvc-model-properties-and-multiple-forms-on-one-view/30197026#30197026 – Tushar Gupta May 19 '15 at 06:40
  • `@foreach (var property in ViewData.ModelMetadata.Properties)`? Use strongly typed helpers for each property so your get proper 2-way model binding! (and in any case you have actually written more bad code that you would have if you had done it correctly) –  May 19 '15 at 07:01
  • Thanks for your good answers. Maybe that was my bad that I didn't mentioned that my main question is when the models is posted how can I save the game and its system requirement using LINQ? why I'm getting NullReferenceExeption ? – Abbas Foroughi May 19 '15 at 07:36
  • You are getting a `NullReferenceExeption` because the value of `SystemRequirements` is `null`! –  May 19 '15 at 08:11
  • possible duplicate of [What is a NullReferenceException and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) –  May 19 '15 at 08:18
  • You have now completely change the code in your question making the answers meaningless. You need to roll back you changes! (and read my last comment and then learn to debug your code) –  May 19 '15 at 09:16

1 Answers1

3

You need to create a composite view model that contains both (SystemRequirement) and (Game) classes as following:

public class CombinedViewModel{

public SystemRequirement { get; set; }
public Game { get; set; }

}

and your controller:

public ViewResult Add(){
    CombinedViewModel MyModel = new CombinedViewModel();
    MyModel.SystemRequirement = new SystemRequirement();
    MyModel.Game = new Game();
    return View(MyModel);
}


    [HttpPost]
    public ActionResult Add(CombinedViewModel pModel){
        Game game = new Game();
        game = pModel.Game;
        game.SystemRequirements = new List<SystemRequirement>();
        game.SystemRequirements.Add(pModel.SystemRequirement);
        gameRepository.Save(game);
        return RedirectToAction("Add");
    }

The View will be:

@model CombinedViewModel

@{
    ViewBag.Title = "Add";
    Layout = "~/Views/Shared/_AdminLayout.cshtml"; }


<div class="container">
    @using (Html.BeginForm("Add", "GameAdmin", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        <div class="panel">
            <div class="panel-heading">
                <h3>Add New Game</h3>
            </div>

            <div class="panel-body">

                @Html.LabelFor(m => m.Game.Name)
                @Html.TextBoxFor(m => m.Game.Name)

                @Html.LabelFor(m => m.Game.Genre)
                @Html.TextBoxFor(m => m.Game.Genre)

                @Html.LabelFor(m => m.Game.ReleaseDate)
                @Html.TextBoxFor(m => m.Game.ReleaseDate)

                @Html.LabelFor(m => m.Game.Multiplay)
                @Html.CheckBoxFor(m => m.Game.Multiplay)

                @Html.LabelFor(m => m.Game.About)
                @Html.TextAreaFor(m => m.Game.About)


            </div>
        </div>

        <div class="panel">
            <div class="panel-heading">
                <h3>System Requirements</h3>
            </div>

            <div class="panel-body">

                @Html.LabelFor(m => m.SystemRequirements.Platform)
                @Html.TextBoxFor(m => m.SystemRequirements.Platform)

                @Html.LabelFor(m => m.SystemRequirements.CPU)
                @Html.TextBoxFor(m => m.SystemRequirements.CPU)

                @Html.LabelFor(m => m.SystemRequirements.RAM)
                @Html.TextBoxFor(m => m.SystemRequirements.RAM)

                @Html.LabelFor(m => m.SystemRequirements.Dsiplay)
                @Html.TextBoxFor(m => m.SystemRequirements.Dsiplay)


                @Html.LabelFor(m => m.SystemRequirements.Discription)
                @Html.TextAreaFor(m => m.SystemRequirements.Discription)


            </div>
        </div>

        <div class="panel-footer">
            <input type="submit" value="Save" class="btn btn-primary" />
        </div>

    } </div>
Ala
  • 1,505
  • 1
  • 20
  • 36
  • I did exactly as you mentioned and my view is very clean. but my question is when the models is posted how can I save the game and its system requirement using LINQ? why I'm getting NullReferenceExeption ? – Abbas Foroughi May 19 '15 at 07:40
  • You mean that you get nullRefrence exception inside the POST action of the (Add) function in your controller? I have editied the (Add) function in the controller so you do not have null exception – Ala May 19 '15 at 08:00
  • The exception occurs at game.SystemRequirements.Add(pModel.SystemRequirement) – Abbas Foroughi May 19 '15 at 08:23
  • I have edited the (Add) function in the controller so you do not have null exception :) – Ala May 19 '15 at 08:39
  • Thanks for spending time to help. but see the question again I changed every things as you told but the error occurs. – Abbas Foroughi May 19 '15 at 08:58