Form field values aren't binding to model - asp.net-mvc-3

I've created a simple MVC application that takes information from a form and passes it to a controller
View:
#model MvcApplication1.Models.BetChargeModel
#using (Html.BeginForm())
{
<div>
#Html.TextBoxFor(m=>m.numerators[0]) / #Html.TextBoxFor(m=>m.denominators[0])
</div>
<div>
#Html.TextBoxFor(m => m.numerators[1]) / #Html.TextBoxFor(m => m.denominators[1])
</div>
<div>
<input type="submit" value="Calculate" />
</div>
}
Controller:
public ActionResult Index()
{
BetChargeModel model = new BetChargeModel();
model.numerators = new List<double>();
model.denominators = new List<double>();
model.denominators.Add(1);
model.denominators.Add(1);
model.numerators.Add(0);
model.numerators.Add(0);
return View(model);
}
[HttpPost]
public ActionResult Index(BetChargeModel model)
{
double odds1 = model.numerators[0] / model.denominators[0];
double odds = model.numerators[1] / model.denominators[1];
//other code
}
Model:
public class BetChargeModel
{
public List<double> numerators { get; set; }
public List<double> denominators { get; set; }
public double result { get; set; }
}
When I run this and try and post back information from the View the Model is coming back empty (full of null fields and zeros). Why is the data in my Textbox's not binding to the model?
(Edit: I've changed the model properties and reference to Numerators, Denominators and Result but haven't updated those here for sake of brevity)

Based on the names numerators and denominators it looks like you have implemented the lists as fields on the model.
You should use properties instead for the model binding to work properly (which I assume that #Raphael has done).
A working model would look like this:
public class BetChargeModel
{
public List<double> numerators { get; set; }
public List<double> denominators { get; set; }
}
... and to follow to naming conventions, make sure to rename numerators to Numerators and denominators to Denominators.
However, if this does not resolve your model binding issue, please elaborate and post your model implementation :)
-- UPDATE
As you have reported that the issue still persists I will post the code I have implemented based on your own provided samples - then you can cross check to make sure everything looks right on your machine - the code shown in the following is tested and works:
Model:
public class BetChargeModel
{
public List<double> numerators { get; set; }
public List<double> denominators { get; set; }
}
View:
#model Project.Models.BetChargeModel
#using (Html.BeginForm())
{
<div>
#Html.TextBoxFor(m=>m.numerators[0]) / #Html.TextBoxFor(m=>m.denominators[0])
</div>
<div>
#Html.TextBoxFor(m => m.numerators[1]) / #Html.TextBoxFor(m => m.denominators[1])
</div>
<div>
<input type="submit" value="Calculate" />
</div>
}
Controller:
public ActionResult Index()
{
var model = new BetChargeModel
{
numerators = new List<double> {0, 0},
denominators = new List<double> {1, 1}
};
return View(model);
}
[HttpPost]
public ActionResult Index(BetChargeModel model)
{
var odds1 = model.numerators[0] / model.denominators[0];
var odds = model.numerators[1] / model.denominators[1];
return null;
}

Related

#foreach model is null :System.NullReferenceException: Object reference not set to an instance of an object

I have this error on read my view on #foreach.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object. Model is null.
this is my userprofile model.
public class UsersContext : DbContext
{
public UsersContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<Secretarias> Secretarias { get; set; }
public DbSet<Secretarias_Direcciones> Secretarias_Direcciones { get; set; }
}
[Table("UserProfile")]
public class UserProfile
{
[Key]
public int UserId { get; set; }
[Required]
public string Nombre { get; set; }
[Required]
public int SecretariaId { get; set; }
[Required]
public int DireccionId { get; set; }
[Required]
public string UserName { get; set; }
}
this is my control
public ActionResult ListaUsuarios()
{
UsersContext db = new UsersContext();
var model = from usrs in db.UserProfiles
select new { usrs.UserId, usrs.Nombre, usrs.UserName, usrs.SecretariaId, usrs.DireccionId };
ViewBag.Model = model.ToList();
return View();
}
this is my view
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.UserId)
</td>
<td>
#Html.DisplayFor(modelItem => item.Nombre)
</td>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
#Html.DisplayFor(modelItem => item.SecretariaId)
</td>
<td>
#Html.DisplayFor(modelItem => item.DireccionId)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.UserId }) |
#Html.ActionLink("Details", "Details", new { id=item.UserId}) |
#Html.ActionLink("Delete", "Delete", new { id=item.UserId })
</td>
</tr>
}
Here are the Exception Details:
System.NullReferenceException: Object reference not set to an instance
of an object. Model is null.
You're getting the NullReferenceException because you haven't passed a strongly-typed model to your view. So in your foreach loop, Model is null. The normal way of doing that is like so:
return View(model);
The real problem is that you're mixing different concepts here. You're trying to access the properties of a model in a strongly-typed way, and yet you're defining a ViewBag.Model property, which is dynamic and has no relation whatsoever to the Model property within a view.
If you want to access your model in a strongly-typed way, and that's certainly the way I'd suggest you do it, you need to make several changes. I'd suggest you first define a view model to represent the data for a UserProfile:
public class UserProfileViewModel
{
public int UserId { get; set; }
public string Nombre { get; set; }
public int SecretariaId { get; set; }
public int DireccionId { get; set; }
public string UserName { get; set; }
}
Now, change your action to create a list of these:
public ActionResult ListaUsuarios()
{
using (UsersContext db = new UsersContext())
{
var model = from usrs in db.UserProfiles
select new UserProfileViewModel
{
UserId = usrs.UserId,
Nombre = usrs.Nombre,
UserName = usrs.UserName,
SecretariaId = usrs.SecretariaId,
DireccionId = usrs.DireccionId
};
return View(model.ToList());
}
}
Notice that I've made several changes here. Firstly, I've added the using statement to ensure UsersContext is disposed properly. Next, I've changed the query to instantiate UserProfileViewModels, instead of anonymous types. Lastly, I'm directly passing model as a parameter to View(), making sure to call ToList() on it, in order to evaluate the query before UsersContext gets disposed.
Finally, you just need to make one change to your view:
#model List<UserProfileViewModel>
#foreach (var item in Model)
{
// rest of code goes here
}
The #model directive specifies the exact model type that the view should expect to receive, thus making it strongly-typed.
Obviously - check the data types of each of the Ids that you are using to perform your joins in your database. Also ensure the database data types were mapped to the correct .Net data types.
If the data types of your ID fields appear to be ok, I would suggest narrowing down which join is causing the error. Modify you LINQ expression to have a single join and ensure there is no error. Add the other joins in one at a time until the error appears.
For your model, please check that it is being populated.
Depending on whatever is happening, it could be that your model is just null
and possibly its type might be something that it is not expected.
-- in the controller a foreach loop on the model context reference will let you see the values

How to bind data to Model's "Display" property with MVC3?

I have a model:
public class TestModel {
[Display(Name = "Date")]
public DateTime Date { get; set; }
}
with Html.LabelFor helper method in Test.cshtml page
#Html.LabelFor(m => m.Date )
and use this page with 2 MVC action methods: Create and Update.
Example:
public virtual ViewResult Create() {
return View("Test");
}
public virtual ViewResult Update() {
return View("Test");
}
and I want to display #Html.LabelFor(m => m.Date ) with Create page: "Date" and Update page: "Update Date" . I know if the normal way of MVC3 can't do this. I hope your ideal can edit Html.LabelFor hepler method or anything way to bind data to Html.LabelFor in action methods on the controller
Adding a hiddenFor field will bind the data to your Model.
#Html.HiddenFor(m=>m.Date);
For override, please just look this answer
https://stackoverflow.com/a/5196392/5557777
you can override editorfor like this How can I override the #Html.LabelFor template? but I think you can do it more easily with ViewBag:
public virtual ViewResult Create() {
ViewBag.Title = "Create";
return View("Test");
}
public virtual ViewResult Update() {
ViewBag.Title = "Update";
return View("Test");
}
in view:
#string.format("{0} Date" , ViewBag.Title )

Passing multiple value tu ActionResult

I have this code in mvc 3 razor
#using (Html.BeginForm("MyAction", "MyController"))
{
<input type="text" id="txt" name="txt"/>
<input type="image" src="image.gif" alt="" />
}
in controller I have this code
[HttpPost]
public ActionResult MyAction(string text)
{
//TODO something with text and return value...
}
now, how to send a new value, for exemple id to Action result??? Thanks
You use a view model:
public class MyViewModel
{
public string Text { get; set; }
// some other properties that you want to work with in your view ...
}
and then pass this view model to the view:
public ActionResult MyAction()
{
var model = new MyViewModel();
model.Text = "foo bar";
return View(model);
}
[HttpPost]
public ActionResult MyAction(MyViewModel model)
{
// remove the Text property from the ModelState if you intend
// to modify it in the POST controller action or HTML helpers will
// use the old value
ModelState.Remove("Text");
model.Text = "some new value";
return View(model);
}
and then the view is strongly typed to this model:
#model MyViewModel
#using (Html.BeginForm("MyAction", "MyController"))
{
#Html.EditorFor(x => x.Text)
<input type="image" src="image.gif" alt="" />
}

view return empty model asp.net mvc3

I try to initialize the DataView.Model in a partial view. The Page works fine but when I return to the controller the model is empty.
some help(solution or an explanation why it is not right).
thanks!!
code:
In my Partial View:
ViewData.Model = new DiamondPrint();
ViewData.Model.Diamond = m_db.DiamondInfoes.Where(di => di.Id == id).SingleOrDefault();
In my Controller:
public ActionResult Preview(DiamondPrint d)//the properties in d = null
{
return View(d);
}
Here is a great article on Model Binding. Model Binding Make sure you are setting the name property in your html input fields.
Looking at the code you have included it seems that you are initialising the ViewData.Model in the partial view but in the controller action you are expecting the default model binder to recreate your model. For the model binder to recreate your model you will need to have created a strongly typed view.
For example:
Controller:
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(IndexModel model)
{
return View();
}
Model:
public class IndexModel
{
public string MyValue { get; set; }
}
View:
Note the #model definition at the top (ignore namespace)
#model MvcApplication14.Models.IndexModel
#using (Html.BeginForm())
{
#Html.Partial("_IndexPartial", Model)
<input type="submit" value="click"/>
}
Partial View:
#model MvcApplication14.Models.IndexModel
#Html.EditorFor(m => m.MyValue)

ASP.NET MVC 3 ListBox validation

I'm currently experiencing a weird issue with ASP.NET MVC 3 ListBox validation, as stated in the title. Basically, I have a List in my viewmodel, which I bind to a ListBox with multiple selection enabled.
The List is given an attribute [Required]. When I submit the form with single value selected, it passes validation with no hiccups. However, with more than one, validation would fail.
Any thoughts?
Weird, I am unable to reproduce your issue.
Model:
public class MyViewModel
{
[Required(ErrorMessage = "Please select at least one item")]
public string[] SelectedItems { get; set; }
public IEnumerable<SelectListItem> Items
{
get
{
return Enumerable.Range(1, 5).Select(x => new SelectListItem
{
Value = x.ToString(),
Text = "item " + x
});
}
}
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel());
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return View(model);
}
}
View:
#model MyViewModel
#using (Html.BeginForm())
{
#Html.ListBoxFor(x => x.SelectedItems, Model.Items)
#Html.ValidationMessageFor(x => x.SelectedItems)
<button type="submit">OK</button>
}
If you don't select any item in the list the validation error message is shown as expected. If you select one or more items the validation passes and no error message is displayed.

Resources