I'm getting the following error:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
Microsoft.AspNetCore.Mvc.Razor.RazorPage.Model.get returned null.
I'm trying to pass an Id from a view to a controller HttpPost action method.
Here is my code:
Controller:
public class HomeController : Controller
{
...
[Authorize]
public IActionResult List()
{
var currentUserId = User.FindFirst(ClaimTypes.NameIdentifier).Value;
var currentCars = db.Cars.Where(x => x.CreatedByUserId == currentUserId)
.Select( x => new CarsListViewModel
{
CarId = x.Id,
CreatedOn = x.CreatedOn,
CreatedByUserId = x.CreatedByUserId,
CreatedByUserName = x.CreatedByUserName,
Firstname = x.PrimaryData.Firstname,
Lastname = x.PrimaryData.Lastname
}).
ToList();
return View(currentCars);
}
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public IActionResult List(int carId)
{
var Car = db.Cars.FirstOrDefault(x => x.Id == carId);
db.Cars.Remove(Car);
db.SaveChanges();
return View();
}
ViewModel:
public class CarListViewModel
{
public int CarId { get; set; }
public DateTime CreatedOn { get; set; }
public string CreatedByUserId { get; set; }
public string CreatedByUserName { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
}
}
View (List.cshtml):
#model List<CVBuilder.ViewModels.CarListViewModel>
#{
ViewData["Title"] = "List of current cars";
}
<div class="col-md-10 offset-md-1">
<table class="table table-hover text-nowrap">
<thead>
...
</thead>
<tbody>
#for (int i = 0; i < Model.Count; i++)
{
<tr>
<td>#Model[i].CreatedOn</td>
<td>#Model[i].CreatedByUserName</td>
<td>#Model[i].Firstname</td>
<td>#Model[i].Lastname</td>
<td>
<form method="post">
<input type="hidden" name="carId" value="#Model[i].CarId" />
<button type="submit" class="btn btn-danger btn-sm">Delete</button>
</form>
</td>
</tr>
}
</tbody>
</table>
#if (Model.Count == 0)
{
<div class="text-center"><p>No cars created.</p></div>
}
</div>
try it:
public IActionResult List([FromForm]int carId){
// return View(); remove
return RedirectToAction("List")
}
You can try this to pass a particular model id from view to controller in MVC
<button href="#Url.Action("List", "ControllerName", new { carId = #Model[i].CarId},null)" button>
in my journey of learning ASP.NET MVC I encounterd another difficulty:
I'm trying to POST a form with 3 checkboxes, the checkboxes are looped onto the form according to a bound PresentationModel.
I don't know what to fill in at the "asp-for" tag-helpers for the checkboxes in the view so they pass a boolean to the "Create()" ActionResult in the controller and to show the values in the "Overview" View.
Currently it passes NULL for al of them, the other aproaches I tried always resulted in an "InvalidCastException" as it has to be a boolean not an "int[]".
PresentationModel (PMRegistration.cs)
public class PMRegistration
{
public List<Device> Devices { get; set; }
}
View (Index.cshtml)
#model Week3_oef2_ITPro.PresentationModel.PMRegistration
<form asp-controller="Register" asp-action="Create" method="post">
<table>
<tr>
<td>Are you wearing any dangerous accessoires</td>
</tr>
#foreach (var item in Model.Devices)
{
<tr>
<td>#item.Name</td>
<td class="form-group">
<input type="checkbox" asp-for="#item.CheckState" value="#item.Id" class="form-control" />
</td>
</tr>
}
<tr>
<td>
<input type="submit" class="btn btn-default" />
</td>
</tr>
</table>
</form>
Model (Device.cs)
public class Device
{
public int Id { get; set; }
public string Name { get; set; }
public bool CheckState { get; set; }
}
Model (Data.cs, the Device objects get initialized here)
private static List<Device> devices = new List<Device>();
static Data()
{
devices.Add(new Device() { Id = 1, Name = "Laptop" });
devices.Add(new Device() { Id = 2, Name = "Tablet" });
devices.Add(new Device() { Id = 3, Name = "Apple Watch" });
}
public static List<Device> GetDevices()
{
return devices;
}
Controller (RegisterController.cs)
public class RegisterController : Controller
{
// GET: /<controller>/
[HttpGet]
public IActionResult Index()
{
PMRegistration pm = new PMRegistration();
pm.Devices = Data.GetDevices();
return View(pm);
}
public ActionResult Create(PMRegistration pm)
{
if (ModelState.IsValid)
{
return View("Overview", pm);
}
else
{
return RedirectToAction("Index");
}
}
}
------------ SOLVED -------------
With HTML-helpers:
#for (int i = 0; i < Model.Devices.Count; i++)
{
<tr>
<td>
#Model.Devices[i].Name
</td>
<td>
#Html.CheckBoxFor(m => Model.Devices[i].CheckState)
#Html.HiddenFor(m => Model.Devices[i].Id)
#Html.HiddenFor(m => Model.Devices[i].Name)
</td>
</tr>
}
C#, .Net 4.5, MVC 5
Referring to XX1 and XX2 below (Main View):
The object is initialized in the main controller. (Both the header and the Detial.)
I have added breakpoints at both XX1 and XX2 to confirm that that the initialized values are still there.
No problem with XX1. The initialized values are there and it is
passed to and received by the controller.
XX2 have a problem. The initialized values are still there and is
passed to, but a null object is somehow received by, the controller.
Why do the controller for the detail not pick up the passed parameters for it.
Model:
public class SampleNonRoutine
{
public HeaderNonRoutine SampleHeader { get; set; }
public List<DetailNonRoutine> SampleDetail { get; set; }
public string Comments { get; set; }
}
public class HeaderNonRoutine
{
public string Division { get; set; }
public string Name { get; set; }
public string Telephone { get; set; }
[DisplayName("Sample Title")]
public string SampleTitle { get; set; }
[DisplayName("Retain Sample for")]
public int RetainSample { get; set; }
}
public class DetailNonRoutine
{
public int ID { get; set; }
[DisplayName("Sample Reference #")]
public string SampleReference { get; set; }
[DisplayName("Sample Test")]
public string SamplesTested { get; set; }
[DisplayName("Sample Assays")]
public string SampleAssays { get; set; }
}
Controller:
For Parent View
public ActionResult NonRoutineSamples(string SaveSend)
{
SampleNonRoutine sample = new SampleNonRoutine();
sample.SampleHeader = new HeaderNonRoutine();
sample.SampleDetail = new List<DetailNonRoutine>();
sample.Comments = "Toets";
for (int i = 0; i < 10; i++)
{
sample.SampleDetail.Add(new DetailNonRoutine { ID = i + 1, SampleReference = "", SamplesTested = "", SampleAssays = "" });
}
return View(sample);
}
For Partial Views:
Header (Partial View):
public ActionResult _HeaderNonRoutineSamples(HeaderNonRoutine model)
{
//...some code
PersonDetail pDetail = _db.ListPerson(_MePerson.First().Number.ToString());
model.Name = pDetail.Name + " " + pDetail.Surname;
model.Telephone = pDetail.PhoneWork;
model.Division = pDetail.Division;
model.RetainSample = 30;
return PartialView(model);
}
Detail:
public ActionResult _DetailNonRoutineSamples(List<DetailNonRoutine> model)
{
return PartialView(model);
}
Views:
Main
#model LaboratorySampleRegistration.Models.SampleNonRoutine
#{
ViewBag.Title = "NonRoutineSamples";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<h4>Non-Routine Samples</h4>
<table>
<tr>
<td>
#Html.Action("_HeaderNonRoutineSamples", "Home", Model.SampleHeader) XX1
</td>
</tr>
<tr>
<td>
#Html.Action("_DetailNonRoutineSamples", "Home", Model.SampleDetail) XX2
</td>
</tr>
<tr>
<td>
<div>
#Html.LabelFor(model => model.Comments, htmlAttributes: new { #class = "control-label col-md-2" })
<div>
<span>
#Html.TextAreaFor(model => model.Comments, new { #class = "SampleRoutineComments" })
#Html.ValidationMessageFor(model => model.Comments, "", new { #class = "text-danger" })
</span>
</div>
</div>
</td>
</tr>
<tr>
<td>
<hr style="border-top:1px solid black !important;" />
<p>
<input id="SaveSend" name="SaveSend" type="submit" value="Send to Laboratory" class="btn btn-default" />
</p>
</td>
</tr>
</table>
}
I have a simple form with a list of items in it and I'd like to post them to the controller but funny thing is I just cant. Everything else goes through properly except the list. I checked the ajax call in firebug and the post values are there like this:
Answers[0].IsMissing False
Answers[0].Text Ja
Answers[0].Value 0
Answers[1].IsMissing False
Answers[1].Text Nein
Answers[1].Value 1
Id 1cd14b08-ce3b-4671-8cf8-1bcf69f12b2d
Name Ja/Nein
I have an AnwserScheme class with the following properties:
public string Name { get; set; }
public bool IsMissing { get; set; }
public List<AnswerDisplayItem> Answers { get; set; }
public AnswerScheme()
{
Answers = new List<AnswerDisplayItem>();
}
I have this view code:
#for (int i = 0; i < Model.Answers.Count; i++) {
<tr>
<td>
#Html.HiddenFor(model => Model.Answers[i].IsMissing)
#Html.TextBoxFor(model => Model.Answers[i].Value,
new { #class = "inputValue" })
</td>
<td>
#Html.TextBoxFor(model => Model.Answers[i].Text,
new { #class = "inputAnswer" })
</td>
<td>
<span class="span-delete"
data-answer-scheme-id="#Model.Id"
data-answer-id="#Model.Answers[i].Id" >x</span>
</td>
</tr>
}
I have this piece of ajax code that is responsible for posting:
$.ajax({
url: "/AnswerScheme/AddAnswer",
type: "post",
data: $("#formAnswerScheme").serialize(),
success: function (data) {
console.log(data);
$("#divAnswerSchemeContainer").html(data);
}
});
I have an add answer action in my controller:
[HttpPost]
public PartialViewResult AddAnswer(AnswerScheme answerScheme)
{
...some logic comes here
}
So in the end the controller recieves the model, but only the simple properties, not the list. Any help would be greatly appreciated! cheers.
I wish I could see more of your classes and code, because you don't have something set up right.
I recreated something from what you did provide, which works. I created an MVC 3 project for this sample.
Views/Shared/_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
</head>
<body>
#RenderBody()
</body>
</html>
Views/Shared/_Partial.cshtml
#model RazorListTest.Models.AnswerScheme
<table>
#for (int i = 0; i < Model.Answers.Count; i++) {
<tr>
<td>
#Html.HiddenFor(model => Model.Answers[i].IsMissing)
#Html.TextBoxFor(model => Model.Answers[i].Value, new { #class = "inputValue" })
</td>
<td>
#Html.TextBoxFor(model => Model.Answers[i].Text, new { #class = "inputAnswer" })
</td>
<td><span class="span-delete" data-answer-scheme-id="#Model.Id" data-answer-id="#Model.Answers[i].Id" >x</span></td>
</tr>
}
</table>
Models/AnswerDisplayItem.cs
using System.Collections.Generic;
namespace RazorListTest.Models
{
public class AnswerDisplayItem
{
public bool IsMissing { get; set; }
public string Text { get; set; }
public string Value { get; set; }
public string Id { get; set; }
}
public class AnswerScheme
{
public List<AnswerDisplayItem> Answers { get; set; }
public string Id { get; set; }
public AnswerScheme()
{
Answers = new List<AnswerDisplayItem>();
}
}
}
Home/Index.cshtml
#model RazorListTest.Models.AnswerScheme
#using (Html.BeginForm(null, null, FormMethod.Get, new { name="formAnswerScheme", id = "formAnswerScheme"}))
{
{Html.RenderPartial("_Partial");}
<div>
<input type="button" value="Click me" id="btnClick"/>
</div>
<div id="divAnswerSchemeContainer">
</div>
}
<script type="text/javascript">
$("#btnClick").click(function () {
$.ajax({
url: 'Home/AddAnswer',
type: 'POST',
dataType: 'json',
data: $("#formAnswerScheme").serialize(),
success: function (data) {
console.log(data);
$("#divAnswerSchemeContainer").html(data);
},
error: function (xhr, textStatus, exceptionThrown) { alert(JSON.parse(xhr.responseText)); }
});
});
</script>
Controllers/HomeController.cs
using System.Collections.Generic;
using System.Web.Mvc;
using RazorListTest.Models;
namespace RazorListTest.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
AnswerScheme a = new AnswerScheme();
a.Id = "1cd14b08-ce3b-4671-8cf8-1bcf69f12b2d";
List<AnswerDisplayItem> adi = new List<AnswerDisplayItem>();
AnswerDisplayItem a1 = new AnswerDisplayItem();
a1.IsMissing = false;
a1.Text = "Ja";
a1.Value = "0";
a1.Id = "1234";
AnswerDisplayItem a2 = new AnswerDisplayItem();
a2.IsMissing = false;
a2.Text = "Nein";
a2.Value = "1";
a2.Id = "5678";
adi.Add(a1);
adi.Add(a2);
a.Answers = adi;
return View(a);
}
[HttpPost]
public JsonResult AddAnswer(AnswerScheme answerScheme)
{
return Json("the list is in the Model.");
}
}
}
Its almost identical what TheGeekYouNeed posted, but i guess something is just missing. I have no clue what that could be.
AnswerScheme view:
#using System.Web.Mvc.Html
#using MetaDataPortal.Models
#model AnswerScheme
#{
ViewBag.Title = #Model.IsMissing ? "Missing" : "AnswerScheme";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#section CssContent{
<link href="../../Content/CSS/AnswerScheme.css" rel="stylesheet" />
}
#using (Html.BeginForm("Save", "AnswerScheme", FormMethod.Post, new { id = "formAnswerScheme" })) {
<div id="divAnswerSchemeContainer">
#{Html.RenderPartial("_AnswerScheme", Model);}
</div>
<input type="button" class="clear inputButton" id="buttonAddCode" value="Add #(Model.IsMissing ? "Missing" : "Answer")" />
<input type="submit" value="Save" />
}
#section Javascript{
<script type="text/javascript">
$(function () {
$("#buttonAddCode").click(function () {
$.ajax({
url: "/AnswerScheme/AddAnswer",
type: "post",
async: false,
data: $("#formAnswerScheme").serialize(),
success: function (data) {
console.log(data);
$("#divAnswerSchemeContainer").html(data);
}
});
return false;
});
});
</script>
<script type="text/javascript" src="~/Content/JavaScript/AnswerScheme.js"></script>
}
_AnswerScheme partialview
#model MetaDataPortal.Models.AnswerScheme
#Html.HiddenFor(model => model.Id, new { Id = "AnswerSchemeId" })
<ul class="ulGeneralForm">
<li>
#Html.LabelFor(model => model.Name, "Name", new { #class = "labelGeneral" })
#Html.TextBoxFor(model => model.Name, Model.Name, new { #class = "textBoxGeneral" })
</li>
<li>
#Html.Label(#Model.IsMissing ? "Missings" : "Answers", new { #class = "labelGeneral" })
<table class="textualData links downloadList">
<thead>
<tr>
<th>Value</th>
<th> #(Model.IsMissing ? "Missing" : "Answer")</th>
<th></th>
</tr>
</thead>
<tbody id="tbodyCodeContainer">
#for (int i = 0; i < Model.Answers.Count; i++) {
<tr>
<td>
#Html.HiddenFor(model => Model.Answers[i].IsMissing)
#Html.TextBoxFor(model => Model.Answers[i].Value, new { #class = "inputValue" })
</td>
<td>
#Html.TextBoxFor(model => Model.Answers[i].Text, new { #class = "inputAnswer" })
</td>
<td><span class="span-delete" data-answer-scheme-id="#Model.Id" data-answer-id="#Model.Answers[i].Id" >x</span></td>
</tr>
}
</tbody>
</table>
</li>
</ul>
AnswerScheme.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using Opit.Rogatus.DomainObjects;
namespace MetaDataPortal.Models
{
public class AnswerScheme : BaseModel
{
public string Name { get; set; }
public bool IsMissing { get; set; }
public List<AnswerDisplayItem> Answers { get; set; }
public AnswerScheme()
{
Answers = new List<AnswerDisplayItem>();
}
public AnswerScheme(CodeList codeList, bool isMissing) : this()
{
Id = codeList.Id;
Name = codeList.Name;
IsMissing = isMissing;
foreach (Code code in codeList.Codes.Where(code => code.Category.IsMissing == isMissing))
{
Answers.Add(new AnswerDisplayItem(code));
}
}
}
}
AnswerDisplayItem.cs:
using System;
using Opit.Rogatus.DomainObjects;
namespace MetaDataPortal.Models
{
public class AnswerDisplayItem
{
public Guid Id { get; private set; }
public short Value { get; private set; }
public string Text { get; private set; }
public Guid AnswerSchemeId { get; set; }
public bool IsMissing { get; private set; }
public AnswerDisplayItem()
{
}
public AnswerDisplayItem(Code code)
{
Id = code.Id;
Value = code.Value;
Text = code.Category.Name;
IsMissing = code.Category.IsMissing;
if (code.CodeList == null) return;
AnswerSchemeId = code.CodeList.Id;
}
}
}
And controller is pretty much the same.
You can do like this create model
public class ApplicationInfo
{
public List<ApplicationAccessRoles> ApplAccessRoleInfo { get; set; }
}
public class ApplicationAccessRoles
{
public int app_access_role_key { get; set; }
public int app_key { get; set; }
public string access_role { get; set; }
public bool inactive { get; set; }
}
put it in view
<div class="step-pane" id="step3">
<div class="form-horizontal" style="vertical-align:central;margin-left:150px">
<table id="RolesDetails" cellpadding="0" cellspacing="0" class="data_table">
<tr class="dataheader">
<td class="width5">
#Html.HiddenFor(m => m.app_access_role_key)
</td>
<td class="width200">
Access Roles Name
</td>
<td class="width10">
Inactive
</td>
</tr>
#if (Model.ApplAccessRoleInfo.Count!= 0)
{
var chk = Model.ApplAccessRoleInfo.Count;
for (int a = 0; a < Model.ApplAccessRoleInfo.Count; a++)
{
<tr class="exp_col_header top_border_nil">
#if ((chk - 1) == a)
{
<td></td>
}
else
{
<td></td>
}
<td>
#Html.HiddenFor(m => m.ApplAccessRoleInfo[a].app_access_role_key)
#Html.EditorFor(m => m.ApplAccessRoleInfo[a].access_role)
</td>
<td>
#Html.CheckBox("ApplTeamAccessInfo[" + a.ToString() + "].inactive", false, new { #class = "check-box"})
</td>
</tr>
}
}
else
{
<tr class="exp_col_header top_border_nil">
<td>
</td>
<td>
#*#Html.EditorFor(model => model.access_role)*#
#*#Html.EditorFor(m => m.ApplAccessRoleInfo[0].access_role)*#
#Html.EditorFor(model=>model.access_role)
</td>
<td>
#Html.CheckBoxFor(model => model.inactive)
</td>
</tr>
}
</table>
</div>
</div>
In Controller
var main = (from a in db.mas_app_access_roles
where a.app_key == AppInfo.app_key
select new ApplicationAccessRoles
{
app_access_role_key = a.app_access_role_key,
access_role = a.access_role,
inactive = a.inactive,
}).ToList();
access = main;
AppInfo.ApplAccessRoleInfo = access;
ViewBag.check = access;
return View(AppInfo);
The problem is with the name/id attribute of your text boxes and other input controls. You can use editor templates to make things seamless and reusable.. Another example here.
But if you still want to loop through things, your loop has to look something in these examples here or here.
Try changing either the controller parameter name to "answers" or the property name to AnswerScheme and if the partial controller in your post is supposed to be recieving the list then change the type to:
List<AnswerScheme> answers
I have a module which send data from controller to view. it has multiple rows and it shows correctly as i wanted. now after making some changes by user i am trying again to save changes in database with the help of actionresult. but when i try to fetch values it say my model is empty/null but it's not ...i am not getting what is the issue...Thanks in advance...
Here is my model:
public class ManageAppsModel
{
public string appname { get; set; }
public int id { get; set; }
public bool chkbillboard { get; set; }
}
Here is my view:
#model IEnumerable<Nd.Models.ManageAppsModel>
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<br />
<h2 style="color:#80afdd;font-size:14px;">
<strong> List of Existing Apps:</strong>
</h2>
<br />
<div class="section-copy">
<table>
#foreach (var item in Model)
{
<tr>
#if (Context.User.Identity.Name == "admin")
{
<td style="width:50px;">
#if (#item.chkbillboard == true)
{
<input name ="chk1" class="myCheckbox" type="checkbox" value="#item.chkbillboard" checked="checked" />
}
else
{
<input name ="chk2" class="myCheckbox" id="chkbox" type="checkbox" value="#item.chkbillboard" onclick="return chkbox();" />
}
</td>
}
<td style="width:200px;">
#item.appname
</td>
<td style="width:50px;">
#Html.ActionLink("Edit", "UpdateAPIForm", new { #id = item.id, appname = item.appname })
</td>
</tr>
}
</table>
</div>
<br/><br/>
if (Context.User.Identity.Name == "admin")
{
<div>
<input type="submit" name="Upload" value="Upload new flash info message" />
</div>
}
}
Here is my actionresult:
[Authorize]
public ActionResult ManageApps(String username)
{
var a = HttpContext.User.Identity.Name;
var context = new ndCorp_SiteEntities();
if (a == "admin")
{
var viewModel1 = from dc in context.DevContactInfoes
join dm in context.DevMarketplaceInfoes on dc.AppName equals dm.AppName
select new ManageAppsModel { appname = dc.AppName, id = dc.SNo, chkbillboard = dc.billboard.Value }
;
return View( viewModel1 );
}
else
{
var viewModel = from du in context.DevUserInfoes
join dc in context.DevContactInfoes on du.UserName equals dc.UserName
join dm in context.DevMarketplaceInfoes on dc.AppName equals dm.AppName
where du.UserName == a
select new ManageAppsModel { appname = dc.AppName, id = dc.SNo };
return View(viewModel);
}
}
[Authorize]
[HttpPost]
public ActionResult ManageApps(IEnumerable<ManageAppsModel> apps)
{
var user = HttpContext.User.Identity.Name;
var context = new ndCorp_SiteEntities();
foreach (var ManageAppsModel in apps)
{
if (ManageAppsModel.chkbillboard == true)
{
Response.Write("hello");
}
}
return RedirectToAction("ManageApps", new { username = user });
}
Your checkboxes are named chk1 and chk2, but your field is called chkBillboard. When you post your value, it uses the names of the input fields to match up the field names in your model.
I suggest using a helper, which makes sure you have the correct format.
#Html.CheckBoxFor(x => item.chkBillboard, new { #class="myCheckbox" })