Model Id Property Null in ASP.NET MVC C#

MVC Property of object in model is null on post

Answer from Comment

its to do with your object initialiser in the CompanySettingView. Change those to properties and initialise them in your constructor (make sure the class has a default constructor) and all should be golden

Something like this:

public class CompanySettingView
{
public List<CompanySetting> Settings { get; set; }
public CompanySetting NewSetting { get; set; }

public CompanySettingView()
{
this.Settings = new List<CompanySetting>();
this.NewSetting = new CompanySetting();
}
}

List item inside model always null on post - Asp.net MVC

But On post, all properties have the value except AllFeatures list item property which always shows count = 0.

AllFeatures is a generic list of Feature. When you do this:

@Html.HiddenFor(model => model.AllFeatures) 

The Razor view engine will render this:

<input id="AllFeatures" 
name="AllFeatures"
type="hidden"
value="System.Collections.Generic.List`1[Namespace.Feature]">
<!--Where Namespace is the Namespace where Feature is defined. -->

In other words, HiddenFor calls the ToString() on the item and simply puts that into the input tag's value attribute.

What happens upon POST

When you post the form, the DefaultModelBinder is looking for a property named AllFeatures but of type string so it can assign this to it:

System.Collections.Generic.List`1[Namespace.Feature]

It does not find one since your model does not have AllFeatures of type string, so it simply ignores it and binds all the other properties.

AllFeatures list item property which always shows count = 0.

Yes, it will and this is not the AllFeatures list which you posted but the one from the constructor which clearly is an empty list with a count 0:

public AddSubscriptionPlanModel()
{
AllFeatures = new List<Feature>();
}

I am not sure why you are sending all the features to the client (browser) and then you need to post it back to the server.

Solution

To fix the issue, simply remove this line:

@Html.HiddenFor(model => model.AllFeatures)

Now it will not cause any confusion during binding and MVC will bind the items in the loop to the AllFeatures property.

In fact, the only code you really need, as far as I can tell from your question is this(I could be wrong if you need the hidden fields for some other reason. But if you just want the user to edit the AllFeatures, you do not need any of the hidden fields):

@for (int i = 0; i < Model.AllFeatures.Count; i++)
{
<tr>
<td>
@Html.TextBoxFor(model => model.AllFeatures[i].Id)
</td>
<td>
@Html.TextBoxFor(model => model.AllFeatures[i].Name)
</td>
<td>
@Html.EditorFor(model => model.AllFeatures[i].IsActive)
</td>
</tr>
}

ASP.NET MVC one particular view model property becoming null on returning to view

Now that I see you are setting the Form.Id in the POST request, your issue is that you are not following the PRG (Post, Redirect, Get) pattern. You are returning the same view from your POST method without any type of redirect. As a result, the model binder is holding on to the previous value of Form.Id, which was null. The reason that the model binder holds on to previous values is mainly for validation purposes (if the ModelState has an error, you can return the view, the properties remain as the user entered them along with the ModelState errors collection)

To fix this, you either need to redirect to another action or issue ModelState.Clear() in your code before you return the view.

   m.formID = form.Id;  // form.Id is valid because the form has been 
//updated with its Id after being added to the database
m.p = form.p;
m.c = form.c;
ModelState.Clear();

return View(m);

Why are my model properties null when trying to POST?

You are not really submitting the form, unless some javascript event does that for you.

Try changing

<a href="Verify" type="submit" class="btn btn-primary btn-user btn-block" >
Login
</a>

to a submit button instead

<button type="submit" class="btn btn-primary btn-user btn-block" >
Login
</button>

When you use a link then you are making a GET request which wont post your form data to the controller, in chrome you can see that for yourself in developer tools/network, open that and then click Login, this should result in the Verify request showing up in the list of requests.

If you really want to use a link and not a submit button, then you can add a bit of javascript to submit your form, either by adding a event handler or submitting the form directly from the link's onClick method.

<a href="Verify" onclick="document.getElementById('form1').submit();" class="btn btn-primary btn-user btn-block" >
Login
</a>

Controller not getting ID from model, returning null

The ID you are testing for is not part of the object. carrepos.ID is null because you are creating the object in your first executable line sobj.carrepos = new CarRepository();. At this point, all its properties are null.

You can create it this way sobj.carrepos = new CarRepository { ID = ID}; and that should fix it

Update

After looking at your updated question, I would say the problem is that your parameter ID is shadowing your property ID and thus the property never gets set. You can solve it in one of 2 ways

// Fully qualify your property
this.ID = (int)reader[0];

Or redefine the argument like so

public void getCarToUpdate(int? id)
{
try
{
if (dbConn.State != ConnectionState.Open)
{
dbConn.Open();
MySqlCommand cmd = new MySqlCommand();

cmd.Connection = dbConn;
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "SELECT ID, carMake, carModel, engine, deleteStatus FROM myprojectdb WHERE ID = ?ID";

cmd.Parameters.Add("?ID", MySqlDbType.Int16).Value = id;
MySqlDataReader reader = cmd.ExecuteReader();

if (reader.HasRows)
{
while (reader.Read())
{
ID = (int)reader[0];
carMake = (string)reader[1];
carModel = (string)reader[2];
Engine = (string)reader[3];
deleteStatus = (string)reader[4];
}
}
reader.Close();
dbConn.Close();

}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}

dbConn.Close();

}

Note that I have changed the parameter to the small id and that way the property can be visible from within the method.

ASP MVC - Model is Null

Thank you @freedomn-m , I think you were right.
Anyway I would like to know how to use HiddenFor with Model as Single Object (string/int), because if I use I can't dynamycally set the id right? because it's not an asp control but an html one.

I got it fixed using the following solution (I was trying to avoid a Model Class, because I really just the single int/string id attribute).

CSHTML

@model MyNameSpace.Models.FrontendModel 
@Html.HiddenFor(model => model.categoryId, new { id = "DetailCategoryId" });

CONTROLLER

public ActionResult GetCategoryDetail(int id)
{
return View(new FrontendModel() { categoryId = id});
}

MODEL

public class FrontendModel
{
public int categoryId { get; set; }
}

PS: If anyone knows how to use single object (string or int) has model please explain me, I would really appreciate. Thanks!

Model within a model is returned as null

if your using entity framework and a your data tables have relations then you can use eager loading to load vendor data for each item in your item list.look at the below Data Model as an Example

public class Vendor_Details
{
public Vendor_Details()
{
Items = new HashSet<Items_List>();
}

public int Id { get; set; }
public string Vendor_Name { get; set; }
public string Vendor_Code { get; set; }
public string Vendor_Email { get; set; }

public ICollection<Items_List> Items { get; set; }

}

public class Items_List
{
public int Id { get; set; }
public string Item_Name { get; set; }
public string Description { get; set; }
public decimal Item_Price { get; set; }
public int Vendor_Id { get; set; }

[ForeignKey("Vendor_Id")]
public Vendor_Details Vendor { get; set; }
}

And Below is the Example Ef Query to Load Data

var itemList = databaseContext.Items_List.Include("Vendor").ToList();

this way You can Load both Vendors and their items at the same time and then be cached to improve the Application performance as well reducing database round trips.



Related Topics



Leave a reply



Submit