Validating a MVC3 viewmodel object based on a selected condition - c#

I want to do some conditional validation for a view model I have created.
public class MyViewModel
{
public int SelectedItem { get; set; }
public Item Item1 { get; set; }
public DetailedItem Item2 { get; set; }
}
public class Item
{
[Required]
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
public class DetailedItem
{
[Required]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
}
I have a radiobutton bound to SelectedItem that via clientside shows or hides a partial view bound to Item & DetailedItem.
On form post I want to validate the selected model but how. If I were to use the above code and do a
ModelState.IsValid
With only one of the partial views fully completed I would get a IsValid=false due to the other modal not containing the required fields.
Is there a way to only validate only the selected model?
Any help would be awesome!

Yes, the ModelState is a Dictionary class and you can remove an item from it using a Key.
For example,
ModelState.Remove("Item1");
Then a call to
ModelState.IsValid
will ignore requirements of that entry.
Here is a link to the documentation, and there is also some discussion about whether this should ever occur in your ViewModels or not.

Related

How can I create a "Create" view in MVC using a List of objects in the view model?

I am fairly new to MVC in general but I am trying to figure out the best way to do create a form to create a model that has a list of another object as a property.
Here is my form on my web page:
Create Recipe Form
When you click the "Add another step" button it will add another section to the form to enter in the details of the next step.
Below are the models I am using with the annotations removed.
public class Recipe
{
public int id { get; set; }
public ApplicationUser Author { get; set; }
public string name { get; set; }
public string description { get; set; }
public int yield { get; set; }
public int preptime { get; set; }
public int cooktime { get; set; }
public List<RecipeVariation> variations { get; set; }
public List<RecipeStep> steps { get; set; }
public List<RecipeNote> notes { get; set; }
}
public class RecipeStep
{
public int id { get; set; }
public int stepNum { get; set; }
public string header { get; set; }
public string bodyText { get; set; }
}
My current solution is to pass a FormCollection through to the HttpPost ActionResult Create in my controller, however, the collection is difficult to parse through. Everytime you add a new "RecipeStep" the name is altered so that I do not have the values concatenated when calling Model.header or Model.bodyText. Is there a better way to parse through this information or even pass through the RecipeSteps as a List?
Thank you
First of all you need to take a foreign key receipeId in receipestep model.
Then on create button click in action method in controller take two parameters(Receipe receipe,List receipestep) and pass object to those parameters.
Then save object to database as first insert into Receipe table and then insert into receipestep table and pass Id of Receipe model as foreign key ReceipeId in ReceipeStep model.
Thanks.
Hope you understand

How to wrap model in viewmodel and use it in datagrid?

I am developing a wpf application with MVVM.
For now, I have my model entities, one viewmodel per views and of course views.
There is examples of my entities:
public class Group : INotifyPropertyChanged
{
public string GID { get; set; }
public string Label { get; set; }
public DateTime Date { get; set; }
public int Rank { get; set; }
}
public class Person : INotifyPropertyChanged
{
public string Name { get; set; }
public Group Group { get; set; }
}
(I removed notifications to simplify)
Currently, I map my model entities to viewmodel throught an intermediate class which repeat properties of model and add some others. To summary: model <-> component <-> viewmodel. But this add more useless complexity for me.
In addition I have a special case where I want to show a list of person in a datagrid.
You can see here in excel
As you can see, Group column is a dropdown filtered by start date and end date and Level column is filtered based on selected group in the previous dropdown.
So, my question is: How do you wrap your model by viewmodel ? And specialy with this case.
Finally, I found a simple solution based on this article I colleague shared with me.
public class PersonViewModel(){
public Person Person { get; set; }
}
public class MainViewModel(){
public Club Club { get; set; }
public ObservableCollection<PersonViewModel> PersonViewModels { get; set;}
public PersonViewModel CurrentPersonViewModel { get; set; }
}
That's perhaps not perfect but this avoid too much complexity in my solutions.

How to handle CheckBoxFor for string value in Entity Framework?

Hello I am trying to handle checkbox for a form where it can be checked or unchecked for the status of task completion. In my database I have taken data field of type varchar which is to be set Pending/Done whenever user check/uncheck the checkbox. Checkbox examples which I found is not fulfilling my need because they are set to separate class of collection of Elements but I don't want that.
MyTblModel.cs
[Table("tblToDo")]
public class ToDoModel
{
[Key]
public int SrNo { get; set; }
public string Title { get; set; }
public string Status { get; set; }
[Column(TypeName = "DateTime2")]
public virtual DateTime CreatedDate { get; set; }
[Column(TypeName = "DateTime2")]
public virtual DateTime? CompletionDate { get; set; }
}
MyContext.cs
public DbSet<ToDoModel> ToDoList { get; set; }
I am accessing this in controller.
HomeController.cs
Session["ToDoList"] = myContext.ToDoList.OrderByDescending(x => x.CreatedDate).ToList();
Now I just fail to understand how to access above given status in CheckBoxFor because it expects me to pass bool value which I don't get. I also want to know, the time I save my data how to pass checkbox status to table as Done/Pending.
Thank you.

Exclude Fields From Model Validation

Let's say I have a following ViewModel :
public class PersonViewModel
{
[Required]
public String Email { get; set; }
[Required]
public String FirstName { get; set; }
[Required]
public String LastName { get; set; }
}
This is a ViewModel not a original Entity, I use this model in two places, in the first one I want to validate all fields, but in another one I want to exclude Email field from model validation. Is there anyway to specify to exclude field(s) from validation?
You can use
ModelState.Remove("Email");
to remove entries in model state, that are related to hidden fields.
The best solution is to divide view model into two:
public class PersonViewModel
{
[Required]
public String FirstName { get; set; }
[Required]
public String LastName { get; set; }
}
public class PersonWithEmailViewModel : PersonViewModel
{
[Required]
public String Email { get; set; }
}
An ugly solution:
ModelState.Remove("Email");
Recommended solution:
Create another ViewModel. A VM is supposed to represent your view, so if your view has no Email field, make a suitable VM for it.

How to set order of appearance for fields when using Html.EditorFor in MVC 2?

I have the following classes in my Model:
public abstract class Entity : IEntity
{
[ScaffoldColumn(false)]
public int Id { get; set; }
[Required,StringLength(500)]
public string Name { get; set; }
}
and
public class Model : SortableEntity
{
[Required]
public ModelType Type { get; set; }
[ListRequired]
public List<Producer> Producers { get; set; }
public List<PrintArea> PrintAreas { get; set; }
public List<Color> Colors { get; set; }
}
To display the "Model" class in the view I simply call Html.EditorFor(model=>model), but the "Name" property of the base class is rendered last, which is not the desired behaviour.
Is it possible to influenece on the order of displayed fields somehow?
I've not been able to find an attribute for that, so your options are:
1) create one, and then revise the base Object.ascx template to account for it, or
2) create a custom editor template for your classes that explicitly put stuff in the order you want.

Categories