Dataannotations validation - c#

on asp.net mvc3 I'm using dataanotations for validation. I control the validations on my controller with a simple if(ModelState.IsValid). How can I control those validations in a simple class, not a controller?
Thanks!

Use the validator helper class: http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validator.aspx

This is pretty much what the MVC validator does behind the scenes:
This will iterate through all the annotations and figure our if there are any errors and add them to an error collection. It's best to put this in a base class then have all your other classes inherit from it. if GetErrors().Any() returns true, the model is invalid.
public IEnumerable<ErrorInfo> GetErrors() {
return from prop in TypeDescriptor.GetProperties(this).Cast<PropertyDescriptor>()
from attribute in prop.Attributes.OfType<ValidationAttribute>()
where !attribute.IsValid(prop.GetValue(this))
select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(string.Empty));
}
Error Info Class:
public class ErrorInfo{
public string Name { get; set; }
public string FormatErrorMessage { get; set; }
public ErrorInfo(string name, string formatErrorMessage){
Name = name;
FormatErrorMessage = formatErrorMessage;
}
}

Answered Here (w/ .net 4):
Using ASP.Net MVC Data Annotation outside of MVC

Related

Making class property optional WebAPI MVC5

I am using MVC5 WebAPI and i have a class as follows:
public string Name { get; set; }
public string Sub { get; set; }
public List<Actions> Actions { get; set; }
(Actions is another custom class)
When client makes an API call they have to send the Actions property as null. Is there a way that the client may not send the actions property at all?
How could this be done?
Thanks in advance.
I think this public List Actions { get; set; } is optional by default.
if user/client don't specify it will be null.
Have you added any required field validations to it?
If the client doesn't post actions. Then Actions at the time of model binding would be null. So there isn't any extra work from your side. In other words, if you post only Name and Sub, then Actions would be null.

Decoration on ViewModel property to use a different name for binding

On MVC3, is there a way to decorate a ViewModel property in order to get the DefaultModelBinder to use a different name for it in the request?
For example, suppose you have the following view model:
public class SomeModel
{
public string Direction {get;set;}
}
But the parameter coming in is Dir from an external source (such as some third-party component, for example).
I know a custom model binder could handle that, but I assume there must be a way to decorate the property, similar to the way action parameters can use Bind(Prefix="...") in order to define that mapping.
You could always create another Property:
public class SomeModel
{
public string Direction {get;set;}
public string Dir
{
get { return this.Direction; }
set { this.Direction = value; }
}
}
I'd also mention that the ViewModel used in a view (cshtml/vbhtml) does not have to be the same ViewModel used on the Post Method.
OK, so after more research looking at similar questions and seeing the feedback here as well, it seems that the answer to my question is basically "NO".
There is no out-of-the-box way, so either custom binders must be used or or the properties should be renamed.
A similar question with a more detailed answer can be found here: How to bind URL parameters to model properties with different names
I was able to accomplish this in ASP.NET MVC Core using the FromForm attribute.
public class DataTableOrder
{
public int Column { get; set; }
[FromForm(Name = "Dir")]
public string Direction { get; set; }
}
Documentation: https://docs.asp.net/en/latest/mvc/models/model-binding.html#customize-model-binding-behavior-with-attributes
However, depending if you do a GET or a POST, you might want to use [FromQuery] instead of [FromForm] I suppose.

Can ASP.Net MVC 2 Custom attributes on class level and on property level be active in the same time?

I am working on asp.net mvc 2 web application.
I have model with 3 properties:
[IsCityInCountry("CountryID", "CityID"]
public class UserInfo
{
[Required]
public int UserID { get; set; }
[Required]
public int CountryID { get; set; }
[Required]
public int CityID { get; set; }
}
I have one "required" property attribute, and one attribute on class level :
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class IsCityInCountry : ValidationAttribute
{
public IsCityInCountry(string countryIDProperty, string cityIDProperty)
{
CountryIDProperty = countryIDProperty;
CityIDProperty = cityIDProperty;
}
public string CountryIDProperty { get; set; }
public string CityIDProperty { get; set; }
public override bool IsValid(object value)
{
var properties = TypeDescriptor.GetProperties(value);
var countryID = properties.Find(CountryIDProperty, true).GetValue(value);
var cityID = properties.Find(CityIDProperty , true).GetValue(value);
int countryIDInt;
int.TryParse(countryID.ToString(), out countryIDInt);
int cityIDInt;
int.TryParse(cityID.ToString(), out cityIDInt);
if (CountryBusiness.IsCityInCountry(countryIDInt, cityIDInt))
{
return true;
}
return false;
}
}
When I post the form on my view, and CountryID is not entered, in ModelState dictionary there's an error about that issue. Other attribute is ignored ("IsCityInCountry"). When I choose CountryID and CityID, which is not in selected country, I get appropriate validation message about that, and ModelState has another key (which is ""). I understand that advantage have property attributes and then class attributes. My question; is there any way to get all validation messages at the same time, no matter what kind of attributes are involved (class or property attributes)? Thanks in advance.
ASP.NET MVC won't perform class level validation if there are property level validation errors. Brad Wilson explains this in his blog post:
Earlier today, we committed a change to MVC 2 that converted the
validation system from Input Validation to Model Validation.
What this means is that we will always run all validators on an
object, if that object had at least one value bound into it during
model binding. We run the property-level validators first, and if all
of those succeed, we'll run the model-level validators.
I would recommend you to go ahead and checkout FluentValidation.NET if you want to perform some more advanced validation in an ASP.NET MVC application. Declarative validation simply doesn't fit the bill in advanced validation scenarios.

Is there an attribute that I can use with ASP.NET MVC 3 to prevent model fields from being automatically included in my views?

Is there an attribute that I can use with ASP.NET MVC 3 to prevent model fields from automatically showing up in my view? What I mean by this is that I have classes like the following:
public class EntityBase
{
public int ID { get; set; }
//more fields...
}
public class TestEntity : EntityBase
{
public string TestEntityName { get; set; }
//more fields...
}
I know about all of the attributes in System.ComponentModel and System.ComponentModel.DataAnnotations to enforce validation - Required, StringLength, etc. - but is there one I can use that will prevent certain fields from showing up in the view when I create it from Visual Studio? All of my project's model classes inherit from EntityBase, but I don't want any of EntityBase's fields to be visible on the view. I'm using Razor as my ViewEngine, in case it matters.
TIA,
Benjy
Use ScaffoldColumn:
[ScaffoldColumn(false)]

asp.NET MVC 2 DataAnnotations UpdateModel<T> validation

I'm trying to use DataAnnotations to add validation to my models in asp.NET MVC 2 RC2, using TryUpdateModel
var user = UserManager.Find(id);
this.TryUpdateModel<IProvisioningObject>(user, form.ToValueProvider());
This updates the model, but the validation is never called. I tried using TryUpdateModel as well (which is the direct type of user), not using the form value provider, using ProvisioningObject directly (which has the validation metadata), to no avail.
Googling for examples only gives me ways to use DataAnnotations by binding through a parameter
public ActionResult Update(User user)
Which I dislike for update scenarios.
Any tips and/or solutions?
EDIT
My objects are auto-generated objects from a WCF service.
I made partials to be able to add DataAnnotations.
I call TryUpdateModel three times because it apparently doesn't support inheritance, which I think is also my problem with DataAnnotations. I specify the validation attributes for ProvisioningObject, and the binding doesn't look for inherited stuff like that.
[MetadataType(typeof(ProvisioningObjectMetadata))]
public partial class ProvisioningObject : IProvisioningObject
{
public string DisplayNameInvariant { get { return string.IsNullOrEmpty(this.DisplayName) ? this.Name : this.DisplayName; } }
}
[MetadataType(typeof(UserMetadata))]
public partial class User : IUser
{
}
public class ProvisioningObjectMetadata
{
[DisplayName("Country")]
public string CountryIsoCode { get; set; }
[Required(ErrorMessageResourceType = typeof(Properties.Validation), ErrorMessageResourceName = "DisplayNameIsRequired")]
[TempValidator]
public string DisplayName { get; set; }
}
public class UserMetadata
{
[DisplayName("Username")]
public string Name { get; set; }
}
// Controller action
public ActionResult Update(string id, FormCollection form)
{
var user = UserManager.Find(id);
this.TryUpdateModel<IUser>(user.User, form.ToValueProvider());
this.TryUpdateModel<IPerson>(user.User, form.ToValueProvider());
this.TryUpdateModel<IProvisioningObject>(user.User, form.ToValueProvider());
if (ModelState.IsValid) // always true
{
return Redirect;
}
else
{
return View();
}
}
If I add the metadata for DisplayName in UserMetadata, it works as expected, but that seems very redundant for nothing. And it would mean I would also have to copy/paste all my inherited interfaces so TryUpdateModel behaves appropriately.
I guess I'm looking for a way that doesn't require me to copy and paste my validation attributes to inherited classes.
New Answer:
"My objects are auto-generated objects from a WCF service."
Autogenerated objects won't have any attributes on them. Are you defining your objects and their attributes on the server side or on the client side?
Old Answer:
If your metadata is not on IProvisioningObject then no validation will be called. The MVC2 default model binder only knows how to find "extra" [MetadataType(buddyClass)] validation information.
For update scenarios bind against DTOs and then map the DTOs, if IsValid() to your main model classes.
Implement IDataErrorInfo interface in your partial class
You will have to write custom validation for each field(where you can use data annotation class to validate each required property)
If you need code example then let me know. I will write it for you!
source: http://www.asp.net/(S(pdfrohu0ajmwt445fanvj2r3))/learn/mvc/tutorial-37-cs.aspx
How do you know that the validation is not being called? Are you checking ModelState.IsValid in your update controller and finding that it is erroneously coming back true?
A typical update pattern is:
UpdateModel(model);
if(!ModelState.IsValid) return View(model);
return RedirectToAction("Index");
If you are expecting some "IsValid" on your model to automatically be called, that will not happen. The data annotations work behind the scenes with the ModelState dictionary on the Controller base class.

Categories

Resources