An optional parameter must be a reference type

When I create a new record, I get the following error:
For clarity, I have listed the code I have so far.
Thanks in advance.
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Create(Nop.Web.Models.User.User, Int32)' in 'Nop.Web.Controllers.MyUsersController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters

Open in new window

MyUsersController.cs
public class MyUsersController : Controller
    {
        private mvcDBContext db = new mvcDBContext();
        // GET: /MyUsers/
        public ViewResult Index()
        {
            return View(db.Users.ToList());
        }
        // POST: /MyUsers/Create
        [HttpPost]
        public ActionResult Create(User user, int id)
        {
            if (ModelState.IsValid)
            {
                db.Users.Add(user);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(user);
        }

Open in new window

User.cs
public class User
    {
        public int UserId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    public class mvcDBContext : DbContext
    {
        public DbSet<User> Users { get; set; }
    }

Open in new window

Create.cshtml
@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>User</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.FirstName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.FirstName)
            @Html.ValidationMessageFor(model => model.FirstName)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.LastName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.LastName)
            @Html.ValidationMessageFor(model => model.LastName)
        </div>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

Open in new window

homeshopperAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

draekCommented:
The parameter 'id' from the class 'MyUserController' from the function 'ActionResult Create(User user, int id)' is not a nullable type (Int32 is a value type). You can use as a parameter a reference type(reference types are Strings,arrays,classes and delegates) or a nullable type.
0
homeshopperAuthor Commented:
Thank you for your response.
You are correct in what you say,
but 'How can I use as a parameter a reference type'
UserId is int and the primary key (does not accept Null).
Thanks in advance.
0
draekCommented:
A string is a reference type so you can use that and pass it as int.
0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

homeshopperAuthor Commented:
I have now tried the following:
[HttpPost]
        public ActionResult Create(User user, string id)
        {

Open in new window

I get new error as below:
Thanks in advance for the help.
Exception Details: System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'UserId', table 'mvcDBs.dbo.Users'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Source Error: 
Line 25:             {
Line 26:                 db.Users.Add(user);
Line 27:                 db.SaveChanges();
Line 28:                 return RedirectToAction("Index");
Line 29:             }

Open in new window

0
draekCommented:
You need to allow nulls in your table or configure your data source to not insert anything in this column and let server generate the value.
0
homeshopperAuthor Commented:
If I try [HttpPost]
        public ActionResult Create(User user)
        {
I get same error.
If I change public int UserId { get; set; } to public string UserId { get; set; }
get validation errors.
If I take out UserId, still get errors.
I am not sure what to try next.
I probably do not fully understand your response.
Thanks in advance.
0
draekCommented:
You can allow nulls on the table by using management studio.
Right click on the table and choose design, and check the box under the 'Allow Nulls' next to the column name you want to allow nulls on.
0
homeshopperAuthor Commented:
Yes, in this instance it would work if UserId was changed to type string & allow nulls;
but this is a prelude to building a more complex form connected to an existing table where
the UserId is (PK,int, not null).
How can this be done programmatically?
0
draekCommented:
[HttpPost]
        public ActionResult Create(User user)
        {
            if (ModelState.IsValid)
            {
                db.Users.Add(user);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(user);
        }

Open in new window


In the User class you have all those informations (id, firstname, lastname) so when you pass the class to the create function all those informations will be taken and inserted in db.Why you need the parameter id?
0
homeshopperAuthor Commented:
Thankyou, I understand what you say.
So now have the following, I have taken out UserId as suggested.
public class User
    {
        //public int UserId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
This now gives, yet another, different error:

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.Entity.ModelConfiguration.ModelValidationException: One or more validation errors were detected during model generation:
\tSystem.Data.Entity.Edm.EdmEntityType: : EntityType 'User' has no key defined. Define the key for this EntityType.
\tSystem.Data.Entity.Edm.EdmEntitySet: EntityType: EntitySet 'Users' is based on type 'User' that has no keys defined.
Source Error:
Line 24:             if (ModelState.IsValid)
Line 25:             {
Line 26:                 db.Users.Add(user);
Line 27:                 db.SaveChanges();
Line 28:                 return RedirectToAction("Index");
Source File: C:\Users\Ian\aaaNopComProjects\webApp-AltSourceFinal\Presentation\Nop.Web\Controllers\MyUsersController.cs    Line: 26
0
draekCommented:
No you don't. I said why you need to add that id parameter on the function create?
Use like this:

public class User
    {
        public int UserId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

[HttpPost]
        public ActionResult Create(User user) //only here you take out 
        {
            if (ModelState.IsValid)
            {
                db.Users.Add(user);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(user);
        }

Open in new window

0
homeshopperAuthor Commented:
I had already tried that, it was the start of the ever increasing circle of errors.
The error given is below:
Cannot insert the value NULL into column 'UserId', table 'mvcDBs.dbo.Users'; column does not allow nulls. INSERT fails.
The statement has been terminated.
0
draekCommented:
Have you set UserId as primary in your table?
0
homeshopperAuthor Commented:
I have just doubled checked.
Yes, UserId is set to Primary key.
0
käµfm³d 👽Commented:
Why not simply set the parameter as having a default value?

public ActionResult Create(User user, int id = -1)

Open in new window

0
homeshopperAuthor Commented:
Thank you for the suggestion, I thought it had been cracked, but sadly not.
I even stried id= 0 & id=1.
Very strange, still gives 'cannot insert the value null into column UserId'
0
käµfm³d 👽Commented:
OK, my suggestion is to solve the original error regarding the null value dictionary (yadda yadda). This is a new error, and it is related to the state of your model. What was the id parameter supposed to represent? Is it the UserId? If so, then why do you have a UserId on your model? Why not just have one rather than two?
0
homeshopperAuthor Commented:
Yes, the column or field name is UserId.
So now in model:
public class User
    {
        public int UserId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
and in Controller:
public class MyUsersController : Controller
    {
        private mvcDBContext db = new mvcDBContext();
        // GET: /MyUsers/
        public ViewResult Index()
        {
            return View(db.Users.ToList());
        }
        // POST: /MyUsers/Create
        [HttpPost]
        public ActionResult Create(User user, int UserId = 0)
        {
            if (ModelState.IsValid)
            {             
                db.Users.Add(user);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(user);
        }
        // GET: /MyUsers/Create
        public ActionResult Create()
        {
            return View();
        }
        // GET: /MyUsers/Edit/5
        public ActionResult Edit(int id)
        {
            User user = db.Users.Find(id);
            return View(user);
        }
        // POST: /MyUsers/Edit/5
        [HttpPost]
        public ActionResult Edit(User user)
        {
            if (ModelState.IsValid)
            {
                db.Entry(user).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(user);
        }

Open in new window

The Edit action works fine, just Create new causes error.
Thanks in advance.
0
käµfm³d 👽Commented:
What does the HTML look like--specifically the <form>?
0
homeshopperAuthor Commented:
The code for Create.cshtml is below:
@model Nop.Web.Models.User.User
@{
    ViewBag.Title = "Create";
    Layout = "~/Themes/CorpWear2/Views/Shared/_ColumnsThree.cshtml";
}
<br /><br />
<h2>Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>User</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.FirstName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.FirstName)
            @Html.ValidationMessageFor(model => model.FirstName)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.LastName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.LastName)
            @Html.ValidationMessageFor(model => model.LastName)
        </div>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Open in new window

0
käµfm³d 👽Commented:
I do not see where you have either User.UserId or id present in that HTML. How were you intending they be populated (for when they get sent to the server)?
0
homeshopperAuthor Commented:
I have now added: @Html.HiddenFor(model => model.UserId) to Create.cshtml
and in the controller:
[HttpPost]
        public ActionResult Create(User user, int UserId = 1)
It does not crash, but also does not update or create a new record.
0
käµfm³d 👽Commented:
Can we try this:  I think that the second UserId parameter is extraneous--you've already got a UserId parameter on your model class. Can we change the controller to:

[HttpPost]
public ActionResult Create(User user)

Open in new window


The .cshtml bit should be fine as-is.

Now, set a breakpoint on the first line of your Create action. Run your project and click the button. Is the breakpoint hit? If so, mouse over the user variable. Is the UserId set?
0
homeshopperAuthor Commented:
Thank you for your response, sorry not to have replied earlier.
Ok, I put a break at public ActionResult Create(User user)
When the button is clicked it does not hit the break point.
When mousing over User,
FirstName = aa
LastName = bb
UserId      = 0
Thanks in advance for any help.
0
homeshopperAuthor Commented:
sorry, meant to say when the break point is hit.
0
homeshopperAuthor Commented:
I have pressed F11 several times and UserId = 0
untill it executes db.SaveChanges();
The error message is then displayed:
Cannot insert the value NULL into column 'UserId', table 'mvcDBs.dbo.Users';
column does not allow nulls. INSERT fails.The statement has been terminated.
Not sure what to try next.
0
homeshopperAuthor Commented:
I have now been able to get my solution to work.
I would like to thank the experts and their responses for the help.
Below for clarity and to help others, is the solution and code.
This time I started without a database and in the Web.Config
<connectionStrings>
    <add name="dBaseDBContext"   connectionString="Data Source=(local);Initial Catalog=dBase;User ID=sa;Password=xxxxxx;" providerName="System.Data.SqlClient"/>
</connectionStrings>

Open in new window

Next is Models.dBaseTable.dBaseTable.cs
This time I added [Key] before the first table field with Primary Key
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations.Schema;

namespace Nop.Web.Models.dBaseTable
{
    public class dBaseTable
    {
        [Key]
        public int      dBaseId { get; set; }         
        public string FirstName { get; set; }
        public string LastName  { get; set; }
    }
    public class dBaseDBContext : DbContext
    {
        public DbSet<dBaseTable> dBaseTables { get; set; }
    }
}

Open in new window

Then finally,  to generate the dBaseController.cs
First, compile the code sofar, then using template to generate controller dBaseController.cs
The dBase database with table dBaseTables is created and when the solution is run
it enters records successfully.

Controllers.dBaseController.cs
Controller with read/write actions and views, using Entity Framework
dBaseTable (Nop.Web.Models.dBaseTable)
dBaseDBContext (Nop.Web.Models.dBaseTable)
Razor (CSHTML)
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Nop.Web.Models.dBaseTable;

namespace Nop.Web.Controllers
{ 
    public class dBaseController : Controller
    {
        private dBaseDBContext db = new dBaseDBContext();
        // GET: /dBase/
        public ViewResult Index()
        {
            return View(db.dBaseTables.ToList());
        }
        // GET: /dBase/Details/5
        public ViewResult Details(int id)
        {
            dBaseTable dbasetable = db.dBaseTables.Find(id);
            return View(dbasetable);
        }
        // GET: /dBase/Create
        public ActionResult Create()
        {
            return View();
        } 
        // POST: /dBase/Create
        [HttpPost]
        public ActionResult Create(dBaseTable dbasetable)
        {
            if (ModelState.IsValid)
            {
                db.dBaseTables.Add(dbasetable);
                db.SaveChanges();
                return RedirectToAction("Index");  
            }
            return View(dbasetable);
        }
        // GET: /dBase/Edit/5
        public ActionResult Edit(int id)
        {
            dBaseTable dbasetable = db.dBaseTables.Find(id);
            return View(dbasetable);
        }
        // POST: /dBase/Edit/5
        [HttpPost]
        public ActionResult Edit(dBaseTable dbasetable)
        {
            if (ModelState.IsValid)
            {
                db.Entry(dbasetable).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(dbasetable);
        }
        // GET: /dBase/Delete/5
        public ActionResult Delete(int id)
        {
            dBaseTable dbasetable = db.dBaseTables.Find(id);
            return View(dbasetable);
        }
        // POST: /dBase/Delete/5
        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {            
            dBaseTable dbasetable = db.dBaseTables.Find(id);
            db.dBaseTables.Remove(dbasetable);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}

Open in new window

This generates the following Views:
Views.dBase.Index.cshtml
Views.dBase.Create.cshtml
Views.dBase.Details.cshtml
Views.dBase.Edit.cshtml
Views.dBase.Delete.cshtml
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
homeshopperAuthor Commented:
I found the solution myself, but would like to thank the experts for their help.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.