Exclude Fields From Model Validation - c#

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.

Related

Different validation on Model depending on Page

I have a Details Model that is used in 2 different pages.
public class Details
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string Nationality { get; set; }
}
When saved in the 1st Page, I want every property of this model to be required, however when saved in the 2nd Page, I want every property to be optional.
Is there a way to make this validation conditional depending on the page I use it?
I'm assuming details model is a base class for these two separate views. You should make it abstract and derive from it (unless you do need to use it somewhere) or use automapper to map details model into details-1 and details-2 with the required validation attributes

Partial server side validation for complex property

In ASP.NET Core MVC app, I need to skip model validation for certain complex property in controller's action.
Let's say I have a following model structure:
public class Person
{
public int PersonID { get; set; }
public PersonalInfo PersonalInfo { get; set; }
public ContactInfo ContactInfo { get; set; }
public Person()
{
PersonalInfo = new PersonalInfo();
ContactInfo = new ContactInfo();
}
}
public class PersonalInfo
{
[Required(ErrorMessage = "First name is required")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last name is required")]
public string LastName { get; set; }
}
public class ContactInfo
{
[Required(ErrorMessage = "Phone is required")]
public string Phone { get; set; }
[Required(ErrorMessage = "Email is required")]
public string Email{ get; set; }
}
In post action, I would like to skip validation for ContactInfo, although it is a part of model and is submitted. Something like this:
[HttpPost]
public ActionResult SavePerson(Person model)
{
ModelState.Remove("ContactInfo");
if (ModelState.IsValid)
{
(...)
}
}
This would work if ContactInfo was simple (is "scalar" correct term?) property.
I know that some of you would suggest me to use seperate viewmodels, but I do not think it is applicable in this case (I'm trying to create a form with multiple steps, and all the data has to be on form in order to be submitted in order to be preserved between steps...)
Also, I guess I could use ModelState.Remove for each property of ContactInfo class, but it seems repetitive and difficult to maintain, especially because my classes contain much more properties.
ModelState.Remove("ContactInfo");
Seems that the ModelState doesn't contain the "ContactInfo" key, so it will not work. If you want to disable the validation in the child class, as you guess, you need to remove all properties in it, such as:
ModelState.Remove("ContactInfo.Phone");
ModelState.Remove("ContactInfo.Email");
but it seems repetitive and difficult to maintain, especially because my classes contain much more properties.
It is indeed repetitive when there are many properties, but you can use reflection to simplify it.
foreach (var property in model.ContactInfo.GetType().GetProperties())
{
ModelState.Remove("ContactInfo." + property.Name);
}
If you have arrays try following. If you do not use XmlElement with an array Xml Serialization requires two Xml Tags. Using XmlElement requires only one tag. :
[XmlElement()]
public List<PersonalInfo> PersonalInfo { get; set; }
[XmlElement()]
public List<ContactInfo> ContactInfo { get; set; }

Is it possible for a model ID to contain date when its made?

I have a model, that needs an ID that contains the date that its made, and if there are more than one made that day, they need to have a number attached to it like so:
15122019
16122019-1
16122019-2
17122019
something like this, and it would need to be made automatically, no input from the user..
is this possible?
this is how my model looks right now:
public class RaidRequest
{
public int Id { get; set; }
[Required]
public Permissions Access { get; set; }
[Required]
public Group UserOrAdmin { get; set; }
[Required]
public string Department { get; set; }
[Required]
public string NameSurname { get; set; }
[Required]
public string Reason { get; set; }
[Required]
public string UNCPath { get; set; }
}
How would this be possible?
Yes, It's possible. However to have such formatting 16122019-1 you need string column. Such logic should be implemented on the Bussiness layer
Also, you have to take into account concurrent inserts, if the system is highly loaded, to have correct increment value
Code improvements:
Your request model should not have fields which are not used (like Id). It's better to have several DTO for each level: API, Business Logic, Database.

Multiple Model In MVC

I am learning how to use MVC right now and I just have a question on when I am creating and updating entries in the database. I was reading a post from this page: asp.mvc 4 EF ActionResult Edit with not all fields in view
The guy in it said to create a model that will be used, so is the efficient way to insert a new row and update an existing row by having two models with different properties?
So my models would look like this -
public class UserModelView
{
public string FirstName { get; set; }
public string Surname { get; set; }
public DateTime AccountCreated { get; set; }
public DateTime? LastLoggedIn { get; set; }
}
public class UserModelCreate
{
[Key]
public int UserId { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public DateTime AccountCreated { get; set; }
}
public class UserModelUpdate
{
public string FirstName { get; set; }
public string Surname { get; set; }
public DateTime? LastLoggedIn { get; set; }
}
Is this the best way to do what I need to do?
Im guessing you were previously using the entity class when binding your model back in.
You shouldn't do that!
The guy in the post is right, this is a much better way of controlling your entity and model information and provides a layer of seperation between the two.
After all you wouldnt want a user being able to directly manipulate an entity via a HTTP request.
I answered something similar here

Validating a MVC3 viewmodel object based on a selected condition

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.

Categories