I have a class that I am using to model my data in MVC. I have added some DataAnotations to mark fields that are required and I am using regular expressions to check valid Email Addresses. Everything works fine if the object is posted back to MVC and I have the ModelState property that I can check to confirm that the class is valid but how do I check to see if the class is valid outside of MVC using the same class and Data Anotations that I have already set up?
Here's a method that I've used in the past with Data Annotations to get all of the errors on an annotated object (it could use some improvements, but it's a good starting point:
public static IEnumerable<ErrorInfo> GetErrors(object instance)
{
return from prop in TypeDescriptor.GetProperties(instance).Cast<PropertyDescriptor>()
from attribute in prop.Attributes.OfType<ValidationAttribute>()
where !attribute.IsValid(prop.GetValue(instance))
select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(String.Empty), instance);
}
There doesn't appear to be anything built into .NET 3.5. If you can develop against .NET 4, though, there is a Validator class that provides what you need:
Validator class on MSDN
Related
We have a web application using ASP.NET MVC, which supports controller methods that take a class object as a parameter. There is automatic binding of the posted form values in order to construct and populate the class object, which occurs before the actual code of the controller method is even invoked. So far so good, but here is my problem: in the course of constructing the class object, the ASP.NET binding engine is invoking every public property of the class. Some of these properties involve some expensive calculation (iterating internal lists, doing counts and so forth), and it is irritating to have them called for no reason whatsoever and the values thrown away. These are read-only properties with only a 'get' and no 'set', so the binder cannot possibly be touching them for purposes of assigning values to them. How can we keep this from happening?
Here is what has been tried so far without success:
Use a [Bind(Include = "...")] in the controller method declaration to limit to the other (non-read-only) properties that can actually be assigned to.
Use a [BindNever] annotation on the read-only properties within the class definition.
Our current workaround is, we just abandon the read-only property implementation altogether and rewrite them all as methods. The binder code does not invoke methods, so this works, but we would still rather have them as properties, and it seems like a problem that should be capable of solution. Any thoughts anyone?
== EDIT =============
Additional things tried, in response to answers here, that still did not work:
Use a [Bind(Exclude = "...")] in the controller method declaration specifying the properties we do not want to invoke. (They are still invoked anyway.)
== EDIT 2 =============
Additional details per request. I am using VS 2015, .NET Framework 4.5.2. Just now I created a sample program to demonstrate the problem:
File -> New -> Project -> Web -> ASP.NET Web Application
Under "ASP.NET 4.5.2 Templates", choose "MVC"
In ManageViewModels.cs, there is a class called "AddPhoneNumberViewModel". This class occurs as a parameter of the method ManageController.AddPhoneNumber (HttpPost version). Add a public property to the class called "PropertyThatShouldNeverBeCalled" and place a breakpoint within it (see code sample below).
Compile and run the application in Debug mode. Attempt to access the endpoint /Manage/AddPhoneNumber, you will have to create an account, then access the endpoint again, enter a phone number, and click "Submit".
Observe that you have hit your breakpoint in PropertyThatShouldNeverBeCalled.
Try one of the unsuccessful fixes described above (e.g. add [Bind(Exclude="PropertyThatShouldNeverBeCalled")] to the definition of ManageController.AddPhoneNumber).
Repeat step 4 above. Observe that you have still hit your breakpoint.
Code sample 1 (from ManageViewModel.cs):
public class AddPhoneNumberViewModel
{
[Required]
[Phone]
[Display(Name = "Phone Number")]
public string Number { get; set; }
public bool PropertyThatShouldNeverBeCalled
{
get
{
bool returnVal = true; // place breakpoint here
return returnVal;
}
}
}
Code sample 2 (from ManageController.cs):
//
// POST: /Manage/AddPhoneNumber
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> AddPhoneNumber([Bind(Exclude = "PropertyThatShouldNeverBeCalled")]AddPhoneNumberViewModel model)
{
// etc.
}
P.S. The problem also occurs when the project is compiled in release mode and run without debugging. I have used logging to confirm this in my original project. For purposes of the sample project, it is just simpler to observe the problem using a breakpoint.
You should use a POCO model such as a DTO (Domain Transfer Object) or a View Model that only contains the properties you need to bind (with any validation you want to have ASP.NET handle as well) and then feed that model into the rest of your application to consume as needed.
You can use the [Bind(Exclude="...")] attribute on the object type as the parameter to the Controller:
Example:
[HttpPost]
public ActionResult Post([Bind(Exclude = "PropertyName")] MyClass dataIn)
{
...
}
MyClass being the object that is being bound on the data coming in to the Controller Action. The Exclude= accepts a comma delimited string for all properties you do not want to be part of the model binding.
https://msdn.microsoft.com/en-us/library/system.web.mvc.bindattribute.exclude(v=vs.118).aspx
I found nothing on the web what [Required] actually does. The msdn-article is not explorative at all.
static class Program
{
public static Main()
{
var vustomer = new CustomerClass();
}
}
public class CustomerClass
{
public string m_FirstName;
[Required]
public string m_LastName;
}
As far as i understand, that should throw an exception since m_LastName is required, but not set. But i don't get one. I don't get what it's good for and what this actually does.
RequiredAttribute, like all other attributes, does nothing by itself other than annotate something (in this case, a field of a type). It is entirely up to the application that consumes the type to detect the presence of the attribute and respond accordingly.
Your sample program does not do this, so the attribute does not have any visible effect. Certain frameworks such as ASP.NET MVC and WPF do check for and respond to the presence of the attribute.
This attribute is used by the Validator class to add validation errors based on any types that inherit from ValidationAttribute. This is used by MVC model validation, for example.
In C#, attributes are almost decoration to classes and properties.
Except for a few security related attributes, most do nothing. They are used by a higher-level framework to do something.
In the case of ASP.NET 4 MVC, only when the object is part of a request that attribute is used to generate an error.
If you want to use that attribute in any other environment, you must write code to inspect it.
It won't do anything from a plain old public static void Main()
Documentation on RequiredAttribute:
Specifies that a data field value is required.
However this validation is typically only performed in the UI layer. It is not "baked" into the constructor or other low-level usage. If you want to manually fire the validation you could do something like:
var customer = new CustomerClass();
var context = new ValidationContext(customer, serviceProvider: null, items: null);
var results = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(customer, context, results);
if (!isValid)
{
foreach (var validationResult in results)
{
Console.WriteLine(validationResult.ErrorMessage);
}
}
To add to the current answers, these are some of the practical uses I can think of out of my head:
Entity Framework use this to model the database as not nullable fields.
Javascript client side validation provides javascript libraries for checking if the input field has any data, else prevent the form submission avoiding unnecesary roundtrips to the server.
Server side validation (when doing model binding) also check when you are posting a model with that decorator that the attribute passed in is in the request. This determines if the model state should be set to an invalid state or not. (1)
There are also annotation for JSON.NET library that changes how the model is serialized/unserialized. I'm pretty confident (but not sure) that the Validate Schema of Json.net does take into consideration the 'Required' attribute when validating a schema.
Other attribute decorators are used on web services, but 'Required' is not one I know has it uses in this scenario.
Web api uses this attribute to mark the property as required on documentation help pages and model binding.
You can create your own application logic that can be aware of the 'Required' property. For example, on a view to mark the property with an * in the label if it's required.
This are some uses but you are not limited to them.
(1) Note: if your property is, for example, an int and you decorate it with Required, model state will never be on a invalid state. You should use Nullable properties for this use-cases.
I've a c# application(in fact it runs into a windows service or like a windows application).
In receive the configuration for one run of the service/application from an XML file.
This XML file is in fact only my data serialized/deserialized in XML. It's one of my other application that generate it.
Before running the business code, I would like to ensure that the configuration file is valid.
By this I mean things like "This String must not be null", "This TimeSpan must have a value greater than XYZ", ...
So only verification that can be made by seing the content of the field(no need to access to something else).
It reminds me a lot the Data Annotation that I used in asp.Net MVC, and I would like if there is something similar for simple c# code, without having to load the whole asp.net MVC dll.
My other option is to implement a method "Validate()" which throw an exception if one field is incorrect, but I will have a lot of if(String.IsNullOrEmpty() and other dummy validations.
I do not want to implement myself a big validator that uses reflexion, it's a bit overkill for only a small configuration file verification.
The application which generate those file could also be interessted to use those same validation.
Edit: I've to use .Net 3.5
This question looks like a duplicate of the following SO question.
Using ASP.Net MVC Data Annotation outside of MVC
Edit: Seeing as you say the ValidationContext isn't available I would recommend writing some custom code that uses Reflection and evaluates all the attributes on the properties for you.
See the answer to this question for an example of how it can be done.
ASP.Net MVC 2 Controller's TryValidate doesn't validate the List<> items within the model
I used the IDataErrorInfo(the same class will be used in the wpf application). And with a custom method where I check every possible attribute here.
Here is the method:
public Boolean IsModelValid()
{
Boolean isValid = true;
PropertyInfo[] properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo p in properties)
{
if (!p.CanWrite || !p.CanRead)
{
continue;
}
if (this[p.Name] != null)
{
isValid = false;
}
}
return isValid;
}
One of the key features of a project I'm working on is the ability for the user to configure Forms (as in "Forms" to fill-up) based on a pool of pre-existing field types (well known types, for instance "user name", "date of birth" etc. but also "generic types" like "string", "DateTime" etc.).
We used to have a static ViewModel that worked fine for the "well known" types and looked like this:
public class UserInputModel
{
[StringLength(200)]
public string Name { get; set; }
[Required(ErrorMessageResourceName = "BirthDateEmptyError", ErrorMessageResourceType = typeof(Resources.ErrorMessages))]
public DateTime BirthDate { get; set; }
//Here comes a lot of other properties
}
All the known properties were listed and we were showing or hiding them given the context.
But the last requirement came and changed all that. The user shall now be able to add as many generic type fields as he wants. In order to do this, we decided to make this InputModel entirely dynamic. It now looks like this:
public class UserInputModel
{
// Each ModelProperty has an "Id" and a "Value" property
public ICollection<ModelProperty> Properties { get; set; }
}
This works like a charm. The razor view only has to iterates over the collection, create the corresponding controls for each property of the collection in a more than standard way:
#Html.TextBoxFor(m => m.Properties[index].Value);
... and we nicely get the data back as a filled form.
=> This works fine, but we don't have any client-side validation. For this, we would need some Metadata... which we don't have via annotations anymore since we're dynamically creating the model.
In order to provide those MetaData, I created a CustomModelMetadataProvider that inherits from DataAnnotationsModelMetadataProvider and registered it as the new ModelMetadataProvider in the Global.asax. The CreateMetadata() function gets called upon creation of the ViewModel, and that for each of the properties of my ViewModel... sofar so good.
Where the problem starts: in order to add some metadata to the current property, I first need to identify which property I am currently looking at ("Name" has a maxlength of 200, "date of birth" hasn't so I cannot assign a maxlength to every property per default). And somewhow I didn't manage to do that yet since all the properties have the same name Value and the same container type ModelProperty.
I tried accessing the container of the property via reflection, but since the ModelAccessor's target is the ViewModel itself (because of the lambda expression m => m.Properties), the following construct gives me the ViewModel as a whole, not just the ModelProperty:
var container = modelAccessor.Target.GetType().GetField("container");
var containerObject = (UserInputModel)container.GetValue(modelAccessor.Target);
I've been flipping this over and over but cannot find a way to identify which ModelProperty I have in hand. Is there a way to do this?
Update: after flipping this in every possible direction for a while, we finally went another way. We are basically using unobstrusive javascript to use MVC's validation capabilities without touching attributes nor metadata. In short, we add HTML attributes like value-data="true" (and all other required attributes) to the #Html.TextBoxFor() statements. This works wonderfully for all the atomic validations (required, stringlength etc.).
Tim, you can leverage what appears to be client-side validation through Ajax with the Remote attribute on your properties.
Basically, you'll need to set up a validation controller and then write some smarts into that controller. But at least you'd be able to write some helper methods and keep it all in one place. You would have a series of validators, based on the meta data that you are presenting to the end users, and each validator method would work for a particular type with good re-use.
The one pitfall to this approach would be that you would need to write a validation method for each type and condition that you want to support. Sounds like you're having to go down that road anyways, though.
Hope this helps.
See if this article help you: Technique for carrying metadata to View Models with AutoMapper.
Also use this one for ideas (custom model metadata provider): changing viewmodel's MetadataType attribute at runtime
Fluent validation is probably the best option for you in my mind, but its obviously up to you to select the best match among those above.
Update
Try use ModelMetadata and override ModelMetadataProvider: Dive Deep Into MVC: ModelMetadata and ModelMetadataProvider. This way you completely customize your model metadata (this replaces data annotations) and you have complete control on what is happening, rather than relying on ASP.NET MVC.
Another good place to look at it is Creating your own ModelMetadataProvider to handle custom attributes.
Hope this all is of help to you.
I have a model class :
public class YearlyChageRate
{
public int Year { get; set; }
public double Rate { get; set; }
}
and I want to check that Yeae is unique or no and in condition Year is not unique application show an error message to users.How can I check the Year filed is repeated or not?
Here is a good example:
http://tugberkugurlu.com/archive/asp-net-mvc-remote-validation-for-multiple-fields-with-additionalfields-property
And here too: MVC validation for unique
You can use Remote attribute in your model to perform check for unique value in database.
This is official example of Remote attribute: http://msdn.microsoft.com/en-us/library/gg508808(v=vs.98).aspx
And one more: http://www.a2zdotnet.com/View.aspx?Id=198
You could use the [Remote] validation attribute on your view model.
Although you can use DataAnnotations attributes for validation and the [Remote] attribute for checks against the DB, it's not a very good design choice.
Let me explain:
data access is a data-layer matter
validation is a business-layer matter
user input and feedback is a ui matter
With DataAnnotations, you're mixin 3 in 1. It can be faster, but surely not well designed.
You could try a more disciplinate approach, like this:
Have a method at business level that will take your object as a parameter, perform validation internally using a validation framework of your choiche;
This method will call the data access to persist the object only if the validation passed;
This method will always return to the UI the validated object, plus a collection of fields/errors if anything didn't validate;
When you read the output of the method in your ui, you can either display a success page if there were no errors, or redisplay the form with the validation errors returned. To do this, the use of the PRG pattern is highly recommended, as you should never display a page on a POST method. Google for the PRG pattern to learn more about it. MvcContrib has a nice ActionFilter called ModelStateToTempData to make the implementation of the PRG pattern something trivial.