When you decorate a model object's property with the Required attribute and don't specify ErrorMessage or ResourceType/Name you get the validation message in the interpolated form of "The {0} field is required.", where param 0 is the value of the DisplayName attribute of that property.
I want to change that default string to something else but I want to keep the generic nature of it, that is I don't want to specify ErrorMessage or ResourceType/Name for every property of the model object. Where is the default string stored and how can I change it?
Deriving your own attribute is a fair option and probably has the lowest overhead to get started, but you'll need to go back and change all your existing uses of [Required]. You (and any others on your team) will also need to remember to use (and teach newcomers to use) the right one going forward.
An alternative is to replace the ModelMetadataProviders and ModelValidatorProviders to return strings from a resource file. This avoids the drawbacks above. It also lays the groundwork for replacing messages for other attributes (e.g., MaxLengthAttribute) and for supporting additional languages.
protected void Application_Start()
{
var stringProvider = new ResourceStringProvider(Resources.LocalizedStrings.ResourceManager);
ModelMetadataProviders.Current = new LocalizedModelMetadataProvider(stringProvider);
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new LocalizedModelValidatorProvider(stringProvider));
}
Here is the full source, documentation, and a blog post describing the usage.
Have you tried creating a derived class of RequiredAttribute and overriding the FormatErrorMessage method? This should work:
public class MyRequiredAttribute : System.ComponentModel.DataAnnotations.RequiredAttribute
{
public override string FormatErrorMessage(string name)
{
return base.FormatErrorMessage(string.Format("This is my error for {0}", name));
}
}
Related
I have lots of property names with PascalCase names.
For example:
public string ProposalNotes { get; set; }
I am after overriding the default Html.DisplayNameFor() method to automatically split the property names to "Proposal Notes" without having to add the display attributes as below:
[Display(Name = "Proposal Notes")]
I want the DisplayName attributes to still work when I need to override this new convention. For example when I have property names like "PgCodeInst" to "Institution Code".
Is there any way of doing this?
I remember a tutorial on how to do something similar but cannot find it.
It's certainly possible, but I just went digging through the source a bit, and I think you're going to find it far more trouble than it's worth. There's multiple classes you'd have to derive from and override methods on, and then you'd have to wire in all your custom stuff in place of the built-ins.
Adding the Display attribute is not really all that much of a burden, and frankly is a bit more explicit in its intention, which is always a good thing. However, if you're dead-set against using it, you might instead consider using a library like Humanizer and just doing something like:
#nameof(Model.ProposalNotes).Titleize();
FWIW, you'd need to add the using statement to your view (#using Humanizer), but you can do that just once in _ViewImports.cshtml.
Also, depending on what you actually want the display name for, you can always just create a custom tag helper. For example, to automatically do this with labels, you can simply inherit from LabelTagHelper (or create your own) and use you own custom logic for determining the display name to show there, instead of worrying about changing the behavior of something like DisplayNameFor. You can also create a custom tag helper to just output the titleized name as above:
public class TitleizeTagHelper : TagHelper
{
const string ForAttributeName = "asp-for";
[HtmlAttributeName(ForAttributeName)]
public ModelExpression For { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "span";
output.SetContent(For.Name.Titleize());
}
}
Then:
<titleize asp-for="ProposalNotes" />
That's a bit of overkill for something so simple, admittedly, but you could beef it up by stealing the logic from LabelTagHelper to support custom display names, as well, if the attribute is actually applied.
This question already has answers here:
Accessing members in your own class: use (auto)properties or not?
(5 answers)
Closed 9 years ago.
So I have a simple class, User, which is something like this (ignore horrible whitespace use, wanted to keep it brief to read online):
public class User
{
private string username;
public string Username
{
get
{
return username;
}set{
if(Validate.usernameIsValid(value)){username = value;}
else{throw new InvalidArgumentException("Username is invalid");}
}
}
//some more fields
public User(String argUsername)
{
this.Username = argUsername;
//OR validate again before:
username = argUsername;
}
}
Is it better to use the public accessor within the class to use its validation? Or is that bad practice and in that case, should I re-validate before setting the private username field?
I'd recommend using the public setter over local setting of the variable, simply because there'll be one place - the setter - where all the logic related to validation is handled. But this is only effective if you follow this convention every where within the class and all the derived versions strictly.
One cannot assume that a member variable is not manipulated elsewhere in the class ( or its derived versions, if it is protected). Imagine another programmer debugging an error related to username validation. It can be a pleasant surprise to find out upon search, that all validations take place via the setter - so she doesn't haven't to debug multiple validation logic.
The answer depends on where the data is coming from. Since the driving point behind using a setter is to avoid duplicating your validation code, you have two basic cases:
When the data is coming from outside your class (i.e. through a method parameter, as in your example) then you should call the setter, which would perform validation for you.
When the data has been "sanitized" at the point where you are ready to assign, go straight to the variable, bypassing the validation.
The former case extends to situations where you read user input.
The later case includes situations where you restore object's state from a snapshot, or generate object's state internally. For example, if your setter has null/empty string validation, and your method wants to set the string to a string representation of a GUID, it's OK to skip the setter.
In most cases I use the public property because what is done there usualy needs to be done all the time. But there are exceptions (for example if validations needs to be done once). So you can't really can't tell in general.
Using public accessors within a class is OK, as well as using any public method. (After all, properties are just syntax sugar for getter/setter methods.)
Using accessors internally might be preferred if accessing a property from within a class has the same semantics as accessing it from outside.
In addition, accessors bring a consistent way to deal with regular and auto-implemented properties. (Auto-implemented ones just do not expose backing fields explicitly.)
Also, outside of constructors, almost for sure, accessors should be used for virtual properties.
Direct use of backing field is needed rather for back-door property manipulations.
But there is no general rule which approach to choose.
actually you have done well, self encapsulate fields make you set the value of property based on your needs easily: for example take a look at this:
private readonly ProductManufacturer _productManufacturer = new ProductManufacturer();
private readonly IList<ProductCategory> _productCategories = new List<ProductCategory>();
public ProductManufacturer ProductManufacturer
{
get { return _productManufacturer; }
}
public IEnumerable<ProductCategory> ProductCategory
{
get { return _productCategories; }
}
now you can get the list of product category list else where, or you can only do some other operation on product category like this:
public void AddProductCategory(ProductCategory productCategory)
{
_productCategories.Add(productCategory);
}
for more information about self encapsulate fields take a look at this:
http://www.refactoring.com/catalog/selfEncapsulateField.html
I have to write custom attribute to check dependent property using MVC pattern. I am using System.ComponentModel.DataAnnotations for checking required fields.
My WPF application contains listview control. All my properties written in modal class get filled in listview when view is loaded first time.
I am providing functionality where user can include/exclude new property in listview. However I don't want to allow user to exclude those property on which other properties are dependent.
For example, If securitynumber property depends on employeename property. While excluding employeename, I want to display validation message that "securitynumber depends on employeename, so can't exclude employeename"
I need help in writing and using custom attribute for e.g
[Dependencyon("Employeename")]
public object securitynumber { get ;set ;}
and want to get value of "Dependencyon" wherever I needed.
You have three options:
A) You can use the CustomValidationAttribute and supply a custom built validator.
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.customvalidationattribute.validatortype(v=vs.95).aspx
B) You can create a class that inherits from ValidationAttribute.
http://msdn.microsoft.com/en-us/library/cc668224.aspx
C) If you only want to do this on the MVC Action you can Create an ActionFilterAttribute as per gordatron's response.
I guess you are looking to create a custom filter.. Its been a while but from memory I think it would be something like:
public class Dependencyon : ActionFilterAttribute {
string field;
public Dependencyon (string field){
this.field = field;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//check whether field is populated and redirect if not?
}
}
here is a starter on ActionFilters:
http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/understanding-action-filters-cs
(I cannot remember details on constructor params for these so i may be way off.. sorry but i guess it wont take long to try)
I've created some classes that will be used to provide data to stored procedures in my database. The varchar parameters in the stored procs have length specifications (e.g. varchar(6) and I'd like to validate the length of all string properties before passing them on to the stored procedures.
Is there a simple, declarative way to do this?
I have two conceptual ideas so far:
Attributes
public class MyDataClass
{
[MaxStringLength = 50]
public string CompanyName { get; set; }
}
I'm not sure what assemblies/namespaces I would need to use to implement this kind of declarative markup. I think this already exists, but I'm not sure where and if it's the best way to go.
Validation in Properties
public class MyDataClass
{
private string _CompanyName;
public string CompanyName
{
get {return _CompanyName;}
set
{
if (value.Length > 50)
throw new InvalidOperationException();
_CompanyName = value;
}
}
}
This seems like a lot of work and will really make my currently-simple classes look pretty ugly, but I suppose it will get the job done. It will also take a lot of copying and pasting to get this right.
I'll post this as a different answer, because it is characteristically different than Code Contracts.
One approach you can use to have declarative validation is to use a dictionary or hash table as the property store, and share a utility method to perform validation.
For example:
// Example attribute class for MaxStringLength
public class MaxStringLengthAttribute : Attribute
{
public int MaxLength { get; set; }
public MaxStringLengthAttribute(int length) { this.MaxLength = length; }
}
// Class using the dictionary store and shared validation routine.
public class MyDataClass
{
private Hashtable properties = new Hashtable();
public string CompanyName
{
get { return GetValue<string>("CompanyName"); }
[MaxStringLength(50)]
set { SetValue<string>("CompanyName", value); }
}
public TResult GetValue<TResult>(string key)
{
return (TResult)(properties[key] ?? default(TResult));
}
public void SetValue<TValue>(string key, TValue value)
{
// Example retrieving attribute:
var attributes = new StackTrace()
.GetFrame(1)
.GetMethod()
.GetCustomAttributes(typeof(MaxStringLengthAttribute), true);
// With the attribute in hand, perform validation here...
properties[key] = value;
}
}
You can get at the calling property using reflection by working up your stack trace as demonstrated here. Reflect the property attributes, run your validation, and voila! One-liner getter/setters that share a common validation routine.
On an aside, this pattern is also convenient because you can design a class to use alternative dictionary-like property stores, such as ViewState or Session (in ASP.NET), by updating only GetValue and SetValue.
One additional note is, should you use this approach, you might consider refactoring validation logic into a validation utility class for shared use among all your types. That should help prevent your data class from getting too bulky in the SetValue method.
Well, whatever way you go, what's executed is going to look like your second method. So the trick is getting your first method to act your second.
First of all, It would need to be [MaxStringLength(50)]. Next, all that's doing is adding some data to the Type object for this class. You still need a way of putting that data to use.
One way would be a binary re-writer. After compilation (but before execution), the rewriter would read the assembly, looking for that Attribute, and when finding it, add in the code for the check. The retail product PostSharp was designed to do exactly that type of thing.
Alternately, you could trigger it at run-time. SOmething like:
public class MyDataClass
{
private string _CompanyName;
[MaxStringLength(50)]
public string CompanyName
{
get {return _CompanyName;}
set
{
ProcessValidation()
_CompanyName = value;
}
}
}
That's still quite ugly, but it's a bit better if you have a number of validation attributes.
The first method using attribute sounds good.
Implement your attribute by inherit from the System.Attribute class and mark your class with AttributeUsage attribute to let your attribute being set on a field.
Then, using reflection, check for presence and value of the attribute before sending the value to the SP.
Thats provide you with lot more flexibility than the second method. If tomorow you decide to let your SP receive the first N chars of a too lengthly string, you won't have to modify all your code but only the one that interpret the attribute.
There are indeed some validation attribute in the framework but I wouldn't use those one because you could implies some behaviour you don't expect and because you won't be able to modify then in any way (liek if you want something like [MaxLength(50, true)] to specify that using the first 5O chars is OK.
It sounds like a business rule. So I would put it in a Company class (Since it is CompanyName), and do the validation there. I don't see why it would require copying and pasting if you have it encapsulated.
Either an attribute or your second example should be fine. The attribute allows for reuse in other classes with string length constraints, however.
Though not exactly the same thing, I recently became aware of .NET 4 Code Contracts in an MSDN article. They provide a convenient and elegant way of encoding and analyzing code assumptions. It's worth taking a look at.
I'm building an ASP.NET MVC site where I want to decorate my ViewModels with validation attributes. One of the things I want to validate is that the address that a user submits through a form is geocodable. For that, I have already created a custom ValidationAttribute and have applied to my StreetAddress property.
This is all good, except that I am actually making two geocoding requests - one in my ViewModel for validation and another in my Controller to input the latitude and longitude into my database. I want to cut down on unnecessary network usage and delays, so I need to pass the
result from the validation geocode into my controller.
To accomplish such a thing, I think I should create a Latitude and Longitude property in my ViewModel. The View itself won't touch these 2 properties, but the validation attribute will either report a failure in geocoding and return the View or write the results into the properties.
For a validation attribute to access 3 properties, it has to be applied to the whole class. I don't know how to do that yet, but that's what this question is for.
UPDATE: Thanks to this answer, I have figured out how to create a class-level validation attribute. The link in the answer also demonstrates how to read the contents of a property inside the class (via Reflection). I still haven't figured out how to write to a property, though.
My Questions
How do I create a ValidationAttribute that can be applied to a whole class? Below, I have posted the code that I want to transfrom into an attribute that can be applied to my ViewModel:
public class GeocodableAttribute : ValidationAttribute
{
public GeocodableAttribute() : base()
{
ErrorMessage = "We weren't able to find that location.";
}
public override bool IsValid(object value)
{
if (value == null) //we don't care if it's required or not.
{
return true;
}
var address = (string)value;
var response = Geocoder.CallGeoWS(address.Trim());
if(response.Status=="ZERO_RESULTS")
{
return false;
}
return true;
}
}
How do I have the attribute write to certain properties in the class that it is applied to? When I apply this attribute to my ViewModel, I want it to write successful geocoding results into two properties and return true. How can I implement that?
UPDATE #2: I think I just figured out how to write to a property. Should the following code work?
private static void WritePropertyValue(object obj, string propertyName, object valueToWrite)
{
if (obj == null) return null;
var type = obj.GetType();
var propertyInfo = type.GetProperty(propertyName);
if (propertyInfo == null) return null;
propertyInfo.SetValue(obj, valueToWrite, null);
}
Will this break client-side validation for other attributes/properties? I have other properties in my ViewModel that I have decorated with built-in ValidationAttributes, such as [Required] and [Range]. I have also enabled client-side validation for them. Will applying my new attribute to the whole ViewModel class completely break client-side validation or will validation for the other properties be performed on the client and then total validation will be performed on the server?
1) You can't access the outer class via a property level ValidationAttribute.
You could use a custom model binder to accomplish this. Simply detect the attributes and validate accordingly.
Creating a custom model binder:
http://www.singingeels.com/Articles/Model_Binders_in_ASPNET_MVC.aspx
2) No. Did you try?
This is almost a duplicate. I'd check out the question and answers for my dupe submission. It may contain a separate technique, class level validation, that may do what you need.