ModelState.IsValid is false due to hidden id field - asp.net-mvc

ModelState.Isvalid always shows false.
I have the below model
public class MyModel: MyEntity
{
[Key]
public int MyModelID { get; set; }
[Required]
[StringLength(255)]
public string Forename { get; set; }
[Required]
[StringLength(255)]
public string Surname { get; set; }
}
And I have this viewmodel
public class MydatabaseVM
{
public MyModel myMode { get; set; }
public virtual Tab2 tab2 { get; set; }
public virtual Employee employee { get; set; }
public virtual Student student { get; set; }
}
Am using this in a view
<div id="email" class="tab-pane fade">
#Html.HiddenFor(model => model.MyModel.MyModelID )
</div>
In my view I have the MyModelID in a hidden field, because I have several tabs in my page, and I want to retain the id to pass to the other tabs.
Once I save, I need the MyModelID in the hidden field. Here if I click on save and when it come to the post action the ModelState.IsValid always return false.
I tried removing the hidden field and it is coming as true. Can you help me what I am doing wrong here? My actual requirement is in a page i have multiple tabs and the main tab has some basic detials .When i save the data on the first tab the details should go to database and should generate and id .when i click on other tabs(using ajax and jquery) the is should pass to those and the data should save to the tables tab2

ModelState is invalid because your are using a data model in your view which contain 2 properties (Forename and Surname) which are decorated with the [Required] attribute and you have not posted values for them.
When you remove the hidden input, the DefaultModelBinder initializes a new instance of MydatabaseVM but the value of myMode is the default (null) so there is nothing to validate.
But when you include the hidden input, its value is posted, which forces the DefaultModelBinder to initialize a new instance of MyModel and set the MyModelID. So now all properties of MyModel are validated and errors are added for the other 2 properties.
Rule 1: Always use ViewModels when editing data. In your case it should be
public class MydatabaseVM
{
public int MyModelID { get; set; }
public virtual Tab2 tab2 { get; set; }
}
and in the view
#Html.HiddenFor( m=> m.MyModelID )

Related

DropDownListFor not returning a Selected Value in Modified Scaffold Razor Page

I am rather new to Razor and I'm using the default templates. I have a ViewModel which contains three models:
public class CarAndOwnerViewModel
{
public IEnumerable<SelectListItem> Cars { get; set; }
public SelectListItem SelectedCar { get; set; }
public OwnerModel Person{ get; set; }
}
I am using this ViewModel in my create method. To get the list of Cars I use:
#Html.DropDownListFor(Model => Model.SeletedCar, new SelectList(Model.Cars, "Value", "Text", Model.Cars))
When I submit this drop down list the value of CarAndOwnerViewModel.SelectedCar is null. I Have a textbox that contains the following and it has it in CarAndOwnerViewModel.Owner.Name:
<input asp-for="Owner.Naame" class="form-control" />
What I filled out in that input box is passed on. I am not sure why the Input Boxes are working but the Select box isn't.
The issue was that the SelectedCar should be an int instead of a SelectedItem
Changing the class to
public class CarAndOwnerViewModel
{
public IEnumerable<SelectListItem> Cars { get; set; }
public int SelectedCar { get; set; }
public OwnerModel Person{ get; set; }
}
Fixed the issue.

Cannot pass new selected dropdown value to the controller

I have an MVC application. Here is a part of my code:
View Model:
public class StudentViewModel
{
public int Id { get; set; }
public int? DepartmentId { get; set; }
public string Name { get; set; }
public string Department { get; set; }
public IEnumerable<SelectListItem> AllDepartments { get; set; }
}
View:
#Html.DropDownListFor(model => model.DepartmentId, Model.AllDepartments)
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(StudentViewModel studentViewModel)
{
After the user changes the department selection in the dropdown and submits, for some reason the studentViewModel.DepartmentId contains the old DepartmentId. studentViewModel.Name does contain the new value. What am I missing?
From the comments, you have included another control for property DepartmentId before the dropdownlist. The DefaultModelBinder reads all form values in order (plus route values, query string values etc). Once a property value has been set, any subsequent values for the same property are ignored.

Add data to different tables using same view and controller in mvc4

I am new to asp.net mvc4 and creating a project in it. I am stuck on the way.
First let me describe about my project. I am creating a product table and each product has some attributes. I have created a ProductAttribute Model and a AttributeValue Model to add attributes and their values. Then I have created a ProductAttributeValue Model to assign the attributes and their values to the Product.
Now my problem is that I want to use the same view to add Attribute and their values. Below are my models:
[Table("ProductAttribute")]
public class ProductAttribute
{
[Key]
[MaxLength(20)]
public string AttributeId { get; set; }
[Required]
[Display(Name = "Attribute Name")]
[MaxLength(100)]
public string AttributeName { get; set; }
[Required]
[Display(Name = "Datatype")]
[MaxLength(50)]
public string AttributeDatatype { get; set; }
[Required]
[Display(Name = "Is Active")]
public bool IsActive { get; set; }
[Required]
[Display(Name = "Attribute Type")]
[MaxLength(30)]
public string AttributeType { get; set; }
}
[Table("AttributeValue")]
public class AttributeValue
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[MaxLength(20)]
public string AttributeId { get; set; }
[Required]
[MaxLength(100)]
public string AttributeName { get; set; }
[Required]
[MaxLength(200)]
public string AttributeVal { get; set; }
public virtual ProductAttribute ProductAttribute { get; set; }
}
How can I insert values to different tables using one view and controller? If there is another way to do the same then please help me about that.
Thanks
I think I understand what you are getting at. First you are going to want to build a View Model. Something like
public Class Tables
{
public List<ProductAttribute> Products { get; set; }
public List<AttributeValue> Values { get; set; }
}
Set those lists from your controller and pass them to the view. On the view you will define the model like
#model Tables
and then in the view build your table in your manner of preference. I have used Html.WebGrid in the past but have been using just foreach loops recently
<table>
foreach(var temp in Model.Products)
{
<tr>
<td>
temp.Name, etc
</td>
</tr>
}
</table>
as for adding and creating I have never been a fan of creating or adding directly in the table and generally what I am showing in the table isn't all of the information that I want from them so I use context menus or edit buttons on the rows and then a add button in a context menu or just outside of the table that will redirect to an edit/add page and then navigate back. Then you can refresh the table with a post back, jquery, refresh a partial view, whatever way fits your situation best. Hopefully this helps :)
Oh, here is a link to people discussing best how to edit a table
How to edit tabular data (ASP MVC)
Update:
Any information passed to the view through the model and used on the page with a for (html.textboxfor, textareafor, etc) will be passed back to the controller. If those fields are changed then the changed value will be passed back.
public ActionResult Index(){
(build your table class)
return View(Tables);
}
[HttpPost]
public ActionResult Index(Tables tbl){
(pass values return from the view to your query for saving to the database)
{

MVC virtual magical mapping or "model binding"

A MVC controller takes a few form items passed to it.
Let's say Name and Address.
In the [Post] controller
It receives a Person Object.
The MVC magical mapping takes place and the Person Object is filled.
1) What is the correct term for this magical mapping?
MODEL BINDING
2) Why if my Person object has virtual object, it doesn't get magically filled up?
OK so here is some REAL code.
public class PackageItem
{
public int ProposalItemID { get; set; }
public virutal PackageByContract { get; set; }
public int Quantity { get; set; }
}
public class EquipmentItem
{
public int ProposalItemID { get; set; }
public virtual EquipmentByContract { get; set; }
public int Quantity { get; set; }
}
public class ProposalItem
{
public PackageItem PackageItem { get; set; }
public EquipmentItem EquipmentItem { get; set; }
}
EquipmentByContract
and
PackageByContract
objects both have
EquipmentByContractID
and
PackageByContractID
<select name="PackageItem.PackageByContract.PackageByContractID"...>
<select name="PackageItem.EquipmentByContract.EquipmentByContractID"...>
Post the controller
Upon Debugging PackageByContractID and EquipmentByContractID are both null
Valued being sent are int
In my controller
[HttpPost]
public ActionResult Index(ProposalItem Item)
{...}
Upon hovering over the Item, both objects appear.
When I drill through it both values are null.
MVC needs some very specific inputs with very specific ids to be posted in order to work its Model Binding magic.
If the model is coming back null, you either don't have an input corresponding to each property of your model, or your ids are wrong.
Check out this post for some ideas of what it should look like.

asp.net mvc model binding fails for <List> items in editor template

I've searched many posts on SO and still not sure what I did wrong here. I have a model for "Order" which includes a <list> of "OrderItem"
public class Order
{
public int OrderId { get; set; }
public int CustId { get; set; }
public DateTime OrderDate { get; set; }
public int OrderType { get; set; }
...
...
public List<OrderItem> OrderItems = new List<OrderItem>();
}
public class OrderItem
{
public string ProductCode { get; set; }
public decimal RetailPrice { get; set; }
public string ProductQuantity { get; set; }
}
In my view, which is strongly typed to the Order model, I am using an Editor Template to display the order items
#model FTG.Models.Order
#Html.EditorFor(x => x.OrderItems)
and the editor template seems to assign a proper name for the model binding to occur:
input type="number" id="OrderItems_0__ProductQuantity" name="OrderItems[0].ProductQuantity"...
input type="number" id="OrderItems_1__ProductQuantity" name="OrderItems[1].ProductQuantity"...
But my model comes back to the controller with count=0 for the list. The rest of the model looks fine, I just can't get the values from the list of orderitems.
Does anyone know what I am doing wrong, or what I am missing?
I think your model class is missing a property for the child list. Try adding a property for the OrderItems list.
OrderItems is a field, not a property. You need to make it a property with a getter and setter, then in your constructor you create the empty list and assign it to the property.

Resources