0

I have been spending all day on and issue searching the web for a solution, however I couldn't find one for my error. It is getting quite frustrating and I have a feeling its one one those facepalm mistakes. I hope you guys can find the time to help me out.

I am working on a Create View which uses a ViewModel. I am using a BeginForm and submit input type button. Now it passes the first property in the ViewModel but every other property passes as null.

Here is my ViewModel + Models

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using FitnessSundhed.Models;
namespace FitnessSundhed.ViewModels
{
    public class WorkoutViewModel
    {
        public Workouts Workout { get; set; }
        public Sets Sets { get; set; }
        public Execises Execises { get; set; }
    }
}

Some of these property are supposed to lists, but I choose not make them lists untill I had tried this in case of issues. Dont mind it.

Heres the Workouts Model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace FitnessSundhed.Models
{
    public class Workouts
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public string Author { get; set; }

        public string Description { get; set; }

        public string Equipment { get; set; }

        public string Targets { get; set; }

        public List<Sets> Sets { get; set; }


    }

}

Sets Model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace FitnessSundhed.Models
{
    public class Sets
    {
        public int Id { get; set; }
        public string SetName { get; set; }
        public string SetDesc { get; set; }

        public List<Execises> Execises { get; set; }
    }
}

Execises Model

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace FitnessSundhed.Models
{
    public class Execises
    {
        public int Id { get; set; }
        public string ImagePath { get; set; }
        public string Name { get; set; }
        public int Reps { get; set; }
        public string Note { get; set; }

    }
}

Basically Workouts contains a list of Sets which contains a list of execises.

View

@model FitnessSundhed.ViewModels.WorkoutViewModel

@{
    ViewBag.Title = "Action";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Action</h2>

@using (Html.BeginForm("Create", "Workouts", FormMethod.Post, null))
{
    @Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>Workouts</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(model => model.Workout.Name, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Workout.Name, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Workout.Name, "", new { @class = "text-danger" })
        </div>
    </div>

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

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

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

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


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

    <div class="form-group">
        @Html.LabelFor(model => model.Sets.SetDesc, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Sets.SetDesc, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Sets.SetDesc, "", 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>

Controller

[HttpPost]
        public ActionResult Create(WorkoutViewModel model)
        {
            Workouts workout = new Workouts();
            workout = model.Workout;
            workout.Sets.Add(model.Sets); // NullReferenceException here.
            _context.Workoutss.Add(workout);
            _context.SaveChanges();
            return RedirectToAction("Library", "Workouts");
        }

Execises hasn't been coded in yet.

So all in all. It is possible for the view to pass the ViewModel and I can add Workout to the database ( I have previous done it), however when I try and use Sets or Execises I get the ''System.NullReferenceException: 'Object reference not set to an instance of an object.'' error when I try and add the set to the workout in the controller.

I hope I have described it in somewhat good details. If not please do ask for more information.

Eco Leikr
  • 3
  • 2
  • Does this answer your question? [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Heretic Monkey Dec 18 '19 at 21:29

1 Answers1

1

Your model starts out as a blank slate here.

Workouts workout = new Workouts();

That means you can't Add to a List unless it exists. So when you call

workout.Sets.Add(model.Sets); // NullReferenceException here.

workout.Sets is null. Your object never initializes it.

Do this in your model.

public List<Sets> Sets { get; set; } = new List<Sets>();

Conversely, if there are times you don't want it initialized (ORM bindings being angry or whatever), make sure you call it before you use it, like so.

 Workouts workout = new Workouts();
            workout = model.Workout;
            workout.Sets = new List<Sets>();
            workout.Sets.Add(model.Sets); 
Nikki9696
  • 6,260
  • 1
  • 28
  • 23