NullReferenceException in the cshtml page [duplicate] - c#

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 7 years ago.
I am starting on ASP.net and I can not resolve the next problem.
System.NullReferenceException: La référence d'objet n'est pas définie à une instance d'un objet.
I forwards a User Id from User controller to this Action, who belongs to Email Controler. Then I want to give this Id to a new parameter.
public ActionResult Create(Guid? id)
{
ViewBag.Key_Destinataire = id;
return View();
}
Le code de ma page HTML :
#model ProjetWeb.Models.Email
////
#Html.LabelFor(model => model.Objet, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Objet, new { htmlAttributes = new { #class = "form-control" } })
///
<div class="form-group">
#Html.LabelFor(model => model.Key_Destinataire, "Key_Destinataire", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Model.Key_Destinataire.Value=ViewBag.Key_Destinataire;
#Html.ValidationMessageFor(model => model.Key_Destinataire, "", new { #class = "text-danger" })
</div>
</div>
English Translation;
Hello,
I start on ASP.net and I can not resolve the error below:
System.NullReferenceException : Object reference not set to an instance of an object.
my code below: I transmits the ID of a user of controller User controller in this action the Email. Then I want to assign the id to a new setting.

Your '#Model' is null. You didn't pass any model in controller to view.
Some reading: check this

You will need to pass the id from the controller action to the view in your return statement. For example:
public ActionResult Create(Guid? id)
{
return View(id);
}
This will now be available to you in your view if you declare #model Guid?. For example:
#model Guid?
<div class="form-group">
#Html.LabelFor(model => model, "Key_Destinataire", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.Value)
#Html.ValidationMessageFor(model => model, "", new {#class = "text-danger"})
</div>
</div>

Related

Form post failing to bind to strongly-typed model MVC4 [duplicate]

Hit a strange issue where my model is not binding and shows up on the controller as null.
I have a form doing a httppost. My breakpoint in the controller is hit and the parameter I expect to be my model is null.
Looking at some example code on another page that works, I copied and pasted it and the only difference was the name of the parameter was 'model' instead of message.
View
#model Site.Models.ContactMessage
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>ContactMessage</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Message, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Message, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Message, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.To, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.To, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.To, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Controller
public ActionResult Contact()
{
return View();
}
[HttpPost]
public ActionResult Contact(ContactMessage message)
{
var m = message;
return View();
}
and it worked. I thought I must have entirely missed something about naming convention. Found you can use Bind, from reading a heap of other posts, to change the prefix like;
public ActionResult Contact([Bind(Prefix = "model")] ContactMessage message)
but that didn't work, still null. Going to rename it to model so it works and I can move on but would like to know why it's not binding if not called model.
public ActionResult Contact(ContactMessage message)
Changed back to this as above but still returns a null.
Interestingly, if I open up another MVC app, that one has whatever parameter names I want and works fine. It's using an older version of MVC 5 (not updated it yet but I will do that and see if anything happens. I don't expect it will.)
Your problem is that you model contains a property named Message and you also have a parameter named message The DefaultModelBinder reads the form values which will include message = "someTextValue" and searches for model properties that have the name message. It finds the one in you model and sets it value (all OK so far) but then it finds another one (your parameter) and tries to set the value of a complex object string value (in effect ContactMessage message = "someTextValue";) which fails so the model becomes null

Foolproof required value based on Dropdown value [duplicate]

This question already has answers here:
The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'
(6 answers)
Closed 7 years ago.
I have discovered the Foolproof library that seems very nice but I am having problems to put it working.
I want to create a required field only if the dropdown has the selected value = 7.
Simple Model:
[RequiredIf("LeadSource_Id","7", ErrorMessage = "Campo obrigatório")]
public string SourceDescription { get; set; }
[Display(Name = "Origem")]
public virtual int LeadSource_Id { get; set; }
The way I create the Dropdown in the Controller:
ViewBag.LeadSource_Id = new SelectList(db.LeadSources.ToList(), "Id", "Name");
The View:
<div class="form-group">
#Html.LabelFor(model => model.LeadSource_Id, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("LeadSource_Id", null, htmlAttributes: new { #class = "form-control ld-lead-source" })
#Html.ValidationMessageFor(model => model.LeadSource_Id, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group collapse">
#Html.LabelFor(model => model.SourceDescription, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.SourceDescription, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.SourceDescription, "", new { #class = "text-danger" })
</div>
</div>
When I try to see if the validation is working when I select the value 7, I get the error:
The ViewData item that has the key 'LeadSource_Id' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'.
EDIT:
The libraries I include are:
<script src="~/Scripts/jquery/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery/jquery.validate.unobtrusive.min.js"></script>
<script src="~/Scripts/jquery/jquery.validate.globalize.min.js"></script>
<script src="~/Scripts/mvcfoolproof.unobtrusive.min.js"></script>
The error occurs because the value ofViewBag.LeadSource_Id is null. Since you have set its value in the GET method, then presumably this error is occurring when you return the view in your POST method (which you have omitted) but have not reassigned the value. In addition you cannot give the ViewBag property the same name as your model property.
Change your controller code to (say)
ViewBag.LeadSourceList = new SelectList(db.LeadSources.ToList(), "Id", "Name");
and ensure this code appears in both the GET method and POST method is you return the view, and modify the view to
#Html.DropDownList("LeadSource_Id", IEnumerable<SelectListItem>ViewBag.LeadSourceList , { #class = "form-control" })
However the recommended approach is to use a view model containing a property public IEnumerable<SelectListItem> LeadSourceList { get; set;}

C# Databinding does not contain property with name

I am creating a ListBoxFor with a MultiSelectList, but I get the following error: DataBinding: *.Models.Facilities does not contain a property with the name FacilitiesList.
Here's my view:
#model *.Models.Reservation
<div class="form-group">
#Html.LabelFor(model => model.FacilitiesList, "Facilities", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.ListBoxFor(model => model.FacilitiesList, ViewBag.FacilitiesList as MultiSelectList, htmlAttributes: new { #class = "form-control" })
</div>
</div>
The viewbag FacilitiesList is populated as follows:
public ActionResult Create()
{
ViewBag.FacilitiesList = new SelectList(_facilityrepository.GetAll(), "FacilitiesList", "FacilityType");
return View();
}
Solved it. Simple solution:
I changed this:
ViewBag.FacilitiesList = new SelectList(_facilityrepository.GetAll(), "FacilitiesList", "FacilityType");
to this:
ViewBag.FacilitiesList = new SelectList(_facilityrepository.GetAll(), "FacilityId", "FacilityType");

Viewmodel values not being returned to controller

I found some similar posts to mine, but I couldn't find an answer that suits my needs for this.
Problem is as follows:
I have a viewmodel like this:
public class PrefViewModel
{
public SelectList countries { get; set; }
public SelectList Provincies { get; set; }
public ApplicationUser user { get; set; }
public Preference MyPref{ get; set; }
public int mycountry { get; set; }
public int myprovince { get; set; }
}
my cshtml looks like this:
#using (Html.BeginForm("Index","Preferences", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(model => model.user.UserName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="control-label col-md-10">
<span class="textvak">
#Html.TextBoxFor(model => model.user.UserName, new { disabled = "disabled", #readonly = "readonly" })
</span>
#Html.ValidationMessageFor(model => model.user.UserName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.user.Email, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="control-label col-md-10">
<span class="textvak">
#Html.TextBoxFor(model => model.user.Email, new { disabled = "disabled", #readonly = "readonly" })
</span>
#Html.ValidationMessageFor(model => model.user.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.user.Unhashed, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.user.Unhashed, new { htmlAttributes = new { #class = "form-control", type = "password" } })
#Html.ValidationMessageFor(model => model.user.Unhashed, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.user.Provincie.Land, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="control-label col-md-10">
#Html.DropDownListFor(model => model.mycountry, Model.countries, new { Name = "ddlLand", id = "ddlLanden", #class = "textvak" })
#Html.ValidationMessageFor(model => model.user.Provincie.Land, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.user.Provincie, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="control-label col-md-10">
#Html.DropDownListFor(model => model.myprovince, Model.Provincies, new { #class = "textvak" })
#Html.ValidationMessageFor(model => model.user.Provincie, "", new { #class = "text-danger" })
</div>
</div>
<br />
<table>
<tr>
<td>
<input type="submit" value=#Resources.Wijzig class="btn btn-default" />
</td>
</tr>
</table>
}
and in my controller I try to get the posted PrefViewModel back as follows:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(PrefViewModel TestMymodel)
{
if (ModelState.IsValid)
{
int myCountry = TestMymodel.mycountry;
int myprovince = TestMymodel.myprovince;
}
return View();
}
My problem is that the PrefViewModel TestMymodel never is filled with the values I thought i'm posting back. Even more strange to me is the fact that I do get the Unhashed password back, but all other values are 0 or null.
I can put values inside the PrefViewModel to load the page and that works, but on Posting it's almost entirely empty.
Any ideas?
edit: Would it make any difference that I did change the default model to one that I made up myself? Cause when I Call the Create action for example, I do get the values back in my post (from create offcourse). I'm getting a bit desperate
edit2: this is what was posted:
__RequestVerificationToken:-JYcw0CH2zZ7WrGUiYJM6-R6VxfL41ykTD5EHUjgtyyFcN01AaUU61BYuaRNr4oPdEvDq09aYsOFdb8fObJTXMnTKulADVkGY8CrBG3U71QXw0g7Th86WKl1up4059Zy7mW0SlrWGJpehed586v_5g2
user.Unhashed:Jonas1234-
user.Unhashed:Jonas1234-
ddlLand:1
ddlProvincie:3
(can't add picture with my reputation, so here a link to the full post: http://postimg.org/image/id95wjcxp/ )
Ok, when I change the name of the dropdownlists to the PrefViewModel property name those values get returned correct.
It appears that you have overriden the names of the drop down lists to some values which are different than the property names in your view model. That's why the values are not successfully bound back. Make sure that your input fields respect the same names as the properties on your view model if you want the default model binder to be able to bind them back to the view model.
Also your username textbox has the disabled flag:
#Html.TextBoxFor(model => model.user.UserName, new { disabled = "disabled", #readonly = "readonly" })
so it will not be submitted back to the server. You might need to add an additional hidden field if you want those values to travel back. Or simply use readonly without disabled attribute. Both attributes prevent the user from modifying the value in the corresponding input field but in addition to that the disabled attribute strips it from the POST payload when the form is submitted.
So you may use:
#Html.TextBoxFor(model => model.user.UserName, new { #readonly = "readonly" })

UpdateModel not working (MVC)

I've been following the nerd dinner tutorial. I branched off to create my own project based on it and I'm having trouble getting UpdateModel to work. It seems pretty complicated so I'll try to explain it in as much detail below.
In ServersController.cs:
public ActionResult Create(FormCollection formValues)
{
Server server = new Server();
try
{
UpdateModel(server); <----- This is not working
// server.Name = "testAdd";
// server.OS = "2008 R2";
serverRepository.Add(server);
serverRepository.Save();
return RedirectToAction("Details", new { id = server.ServerID });
}
catch
{
**not important**
}
If I try to use UpdateModel(Server), nothing gets saved to the database table. However, If I comment out that line, and use the commented lines in the code that sets the server.Name and server.OS, this DOES save it to the table. However, any other form input that's being posted doesn't save..
For example, if I explicitly set the server.Name and server.OS as in the code above, but then set other properties such as LastBackedUp and Model through the form, none of the properties set from the form are saved to the database table, nor are they reflected in the "details" view when the page gets redirected.
Here's the code for the "Details" GET method, also in ServersController.cs:
public ActionResult Details(int id)
{
Server server = serverRepository.GetServer(id);
RackInfo rackInfo = rackRepository.GetRack(id);
if (server == null)
return View("NotFound");
else
return View(new ServerDetailViewModel(rackInfo, server));
}
Basically, After the new server is created and saved, it's supposed to load the above "Detail" view, which uses a "ServerDetailViewModel" class to generate some data to pass to the view.
Here's the ServerDetailViewModel() code:
public class ServerDetailViewModel
{
public RackInfo RackInfo { get; private set; }
public Server Server { get; private set; }
public string Name { get; private set; }
public ServerDetailViewModel(RackInfo rackInfo, Server server)
{
Server = server;
RackInfo = rackInfo;
*more code here that sets stuff*
}
}
I think my problem has something to do with how my form parameters are passed around.
It seems odd that I can explicitly code in some server properties, and then save those into the database table. But when I try to do anything with UpdateModel, nothing seems to go through. When I use UpdateModel, it will redirect me to the details page, but none of the values I input for the properties seem to appear. Additionally, none of the properties I put in through the form gets saved to the database table.
If any of you have walked through the Nerd Dinner tutorial (http://weblogs.asp.net/scottgu/archive/2009/04/28/free-asp-net-mvc-nerddinner-tutorial-now-in-html.aspx), that's what I've been using. When I got through about halfway, I decided to start a new project that implemented what I was using.
I was initially able to get Create to work, but after adding another separate repository to the controller, the create method broke..
Any input or insight on this would be much appreciated. Please let me know if you need any additional information.
Thanks S.O.!!
EDIT (Including the "Create" Form):
#model PACSSL.Models.ServerFormViewModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Server</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Server.Name, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Server.Name)
#Html.ValidationMessageFor(model => model.Server.Name)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Domain, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(x => x.Domain, Model.Domain)
#Html.ValidationMessageFor(model => model.Domain)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BackedUp, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(x => x.BackedUp, Model.BackedUp)
#Html.ValidationMessageFor(model => model.BackedUp)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Server.Role, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Server.Role)
#Html.ValidationMessageFor(model => model.Server.Role)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Server.GroupOwner, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Server.GroupOwner)
#Html.ValidationMessageFor(model => model.Server.GroupOwner)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Server.PatchNotes, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Server.PatchNotes)
#Html.ValidationMessageFor(model => model.Server.PatchNotes)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Server.LastPatched, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Server.LastPatched) Format: yyyy-mm-dd
#Html.ValidationMessageFor(model => model.Server.LastPatched)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PatchedBy, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(x => x.PatchedBy, Model.PatchedBy)
#Html.ValidationMessageFor(model => model.PatchedBy)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.VP, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(x => x.VP, Model.VP)
#Html.ValidationMessageFor(model => model.VP)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Server.VMHost, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Server.VMHost)
#Html.ValidationMessageFor(model => model.Server.VMHost)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Server.Location, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Server.Location)
#Html.ValidationMessageFor(model => model.Server.Location)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Server.PurchaseDate, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Server.PurchaseDate) Format: yyyy-mm-dd
#Html.ValidationMessageFor(model => model.Server.PurchaseDate)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Server.OS, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Server.OS)
#Html.ValidationMessageFor(model => model.Server.OS)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Server.Model, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Server.Model)
#Html.ValidationMessageFor(model => model.Server.Model)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Server.DellST, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Server.DellST)
#Html.ValidationMessageFor(model => model.Server.DellST)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Server.ServiceContract, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Server.ServiceContract) Format: yyyy-mm-dd
#Html.ValidationMessageFor(model => model.Server.ServiceContract)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Server.IsLive, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Server.IsLive)
#Html.ValidationMessageFor(model => model.Server.IsLive)
</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>
}
Here's your problem.
When you generate a form field with the expression model => model.Server.OS, you produce a field that has a 'name' attribute like this:
"Server.OS"
Then, when you try and bind it to a model, it will bind to a model property matching the expression "Server.OS" - so, if your model object is server, it will bind to the following:
server.Server.OS
When, I presume, you want to bind to server.OS. My suggestion would be to flatten out your view model so instead of having Model.Server.OS you just have Model.OS. Then when you do...
UpdateModel(server);
... it should bind the "OS" field to the "OS" property.
In short: your view model has an extra level of property nesting compared to your server object, so there is a mismatch in the generated field names and the properties you're trying to bind to.
Better still, bind back to the same view model by modifying your controller action to have the signature:
public ActionResult Create(ServerDetailViewModel model)
And then do the mapping manually in the controller (or some static mapping class) - your view models and domain model should be completely independent.
You are trying to update a "empty" Model. It is empty because you are creating a new instance.
Server server = new Server();
try
{
//At this point you have an empty model because you just
//created a new Instance of your Server class,
//It is updating the Model with all Null values because they aren't assigned to anything
UpdateModel(server); <----- This is not working
//Here you assign values to your model, hence why they are not null anymore
// Your other values aren't getting saved because they still don't have a value.
server.Name = "testAdd";
server.OS = "2008 R2";
serverRepository.Add(server);
serverRepository.Save();
return RedirectToAction("Details", new { id = server.ServerID });
}

Categories