Customizing DisplayFormat beyond DataFormatString - asp.net-mvc

I have a MVC 4 project where I would like to use functionality similar to DisplayFromat, but setting a DataFormatString is not enough. I would like a function to be called to format the string. Is that possible?
I have tested inheriting DisplayFormat but that just lets me set the DataFormatString.
I have looked at customizing DataAnnotationsModelMetadataProvider, but I don't see how I would make it call a custom function for formatting.
My particular case is that I need to format the integer 201351 as "w51 2013". I couldn't come up with a format string that does that.

The easiest way is to expose a read-only property on your Model:
public class Model{
public int mydata{get; set;}
public string formattedDate{
get{
string formattedval;
// format here
return formattedval;
};
}
}

You can create a custom ValidationAttribute. Here is some code I use to validation someone has selected a drop down value.
using System.ComponentModel.DataAnnotations;
public sealed class PleaseSelectAttribute : ValidationAttribute
{
private readonly string _placeholderValue;
public override bool IsValid(object value)
{
var stringValue = value.ToString();
if (stringValue == _placeholderValue || stringValue == "-1")
{
ErrorMessage = string.Format("The {0} field is required.", _placeholderValue);
return false;
}
return true;
}
public PleaseSelectAttribute(string placeholderValue)
{
_placeholderValue = placeholderValue;
}
}
Then Use it:
[Required]
[Display(Name = "Customer")]
[PleaseSelect("Customer")]
public int CustomerId { get; set; }

Related

An object reference is required for the non-static field, method, or property error when passing parameter to attribute

In my MVC project, i want to validate an input by other input value. For instance according by following code, it doesn't return validation message if employee is a female and user doesn't choose any military service value but if employee is male, it returns validation message but i am getting this error during the runtime;
"An object reference is required for the non-static field, method, or property HRManager.Models.Employee.CheckMilitary()"
public class Employee
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public int Gender { get; set; }
[RequiredByValue(IsRequired = CheckMilitary())]
public string MilitaryService { get; set; }
private bool CheckMilitary()
{
// If gender is female return false
return (this.Gender == 0)? false : true;
}
}
public class RequiredByValue : ValidationAttribute
{
public bool IsRequired { get; set; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
//todo
return base.IsValid(value, validationContext);
}
}
It looks like you are calling a non static property from a static method. You will need to either make the CheckMilitary static, or create an instance of Employee
seems like you are trying to determine if the gender and thus make the MilitaryService field required before you know the 'Employee`
give us an example on how and when you are calling: HRManager.Models.Employee.CheckMilitary() and I'll give you proper example on how to fix.

Data Annonation Custom Attribut [DateTime]

I'm trying to add Data Validation To my DateTime Attribut i want to oblige user to select Date between DateTime.Now and smaller then one years after DateTime.now.addyears(+1)
This is my code :
public class DateDebut : ValidationAttribute
{
public override bool IsValid(object value)
{
if (value == null) return false;
DateTime enteredDate = (DateTime)value;
if ( (enteredDate >= DateTime.Now) && (enteredDate <= DateTime.Now.AddYears(+1)))
return true;
else
return false;
}
}
[Required]
[Display(Name = "De : ")]
[DataType(DataType.Date)]
[DateDebut(ErrorMessage="Date invalide")]
public DateTime dd { get; set; }
This Custom Validation dosn't work, verification is not excuted, ai think i'm missed something realy simple?
I agree completelt with Daniel,
However I find that when i am needing to do comparisons of properties in my model I use the IValidatableObject
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.ivalidatableobject.aspx
I find it faster and easier for most small types of comparisons
you would have some that looks like this
public class myModel : IvalidatableObject
{
string debut = DateTime.Now.ToShortDateString();
string fin = DateTime.Now.AddYears(+1).ToShortDateString();
[Required]
[Display(Name = "De : ")]
[DataType(DataType.Date)]
public DateTime dd { get; set; }
public IEnumerable<ValidationResult> Validate()
{
if(this.debut > this.fin)
{
yield return new ValidationResult("debut cannot be greated then fin");
}
}
}
read up and see whats best for you
Attributes are static in nature. Have you considered writing your own attribute for validation? There are several examples on the web that should get you started.
You could also inherit from RangeAttribute and inject it as needed.

How change Displayname value at runtime based on other parameter value in MVC?

[DisplayName("Planned Amt($):")]
public string PlannedAmount { get; set; }
[DisplayName("Unallocated Amt($):")]
public string UnallocatedAmount { get; set; }
I have this members in my class .Based on budgetType variable value i need to change the DisplayName Value for both the attributes. Please, let me know how to do that.
You should just be able to inherit from DisplayNameAttribute and override the DisplayName property:
public class DisplayNameExAttribute : DisplayNameAttribute
{
public override string DisplayName
{
get
{
// do what you want here.
return base.DisplayName;
}
}
}
I haven't actually tried to implement this, so it is possible that the DisplayName attribute is coded such that some other extension point will have to be used, but I'll try to confirm.
You can inherit from DisplayNameAttribute like this:
public class BudgetDisplayNameAttribute : DisplayNameAttribute
{
public BudgetDisplayNameAttribute(string pBaseName) : base(pBaseName) { }
public override string DisplayName
{
get
{
return My.BudgetType + " " + base.DisplayName;
}
}
}
Where, for this example, My.BudgetType is a public static string in a public static class:
public static class My
{
public static string BudgetType = "Quarterly";
}
And then apply the attribute to your property like this:
[BudgetDisplayName("Planned Amt($):")]
public string PlannedAmount { get; set; }
[BudgetDisplayName("Unallocated Amt($):")]
public string UnallocatedAmount { get; set; }
Finally, the part of your program that uses the DisplayName attribute of your properties will get the text:
"Quarterly Planned Amt($):" for the PlannedAmount property
"Quarterly Unallocated Amt($):" for the UnallocatedAmount property

Can I dynamically turn off validation in MVC?

I have a search form where I can search on one of two fields. Only one of the two is required. Is there a way to cleanly do this in the MVC provided validation?
If this is server validation, you could create a Custom Validation Attribute for this:
[ConditionalRequired("Field1","Field2")]
public class MyModel()
{
public string Field1 { get; set; }
public string Field2 { get; set; }
}
Then you can create a custom validation attribute.. something like the following:
[AttributeUsage( AttributeTargets.Class, AllowMultiple = true, Inherited = true )]
public sealed class ConditionalRequiredAttribute : ValidationAttribute
{
private const string _defaultErrorMessage = "Either '{0}' or '{1}' must be provided.";
public string FirstProperty { get; private set; }
public string SecondProperty { get; private set; }
public ConditionalRequiredAttribute( string first, string second )
: base( _defaultErrorMessage )
{
FirstProperty = first;
SecondProperty = second;
}
public override string FormatErrorMessage( string name )
{
return String.Format( CultureInfo.CurrentUICulture, ErrorMessageString,
FirstProperty, SecondProperty );
}
public override bool IsValid( object value )
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties( value );
string originalValue = properties.Find( FirstProperty, true ).GetValue( value ).ToString(); // ToString() MAY through a null reference exception.. i haven't tested it at all
string confirmValue = properties.Find( SecondProperty, true ).GetValue( value ).ToString( );
return !String.IsNullOrWhiteSpace( originalValue ) || !String.IsNullOrWhiteSpace( confirmValue ); // ensure at least one of these values isn't null or isn't whitespace
}
}
Its a little verbose, but it gives you the flexibility to able this attribute directly to your model as opposed to applying it to each individual field

How to validate two properties with ASP.NET MVC 2

I'm just getting started with ASP.NET MVC 2, and playing around with Validation.
Let's say I have 2 properties:
Password1
Password2
And I want to require that they are both filled in, and require that both are the same before the model is valid.
I have a simple class called "NewUser".
How would I implement that? I've read about ValidationAttribute, and understand that. But I don't see how I would use that to implement a validation that compares two or more properties against eathother.
Thanks in advance!
Problem with below solution:
When this is applied to an application, and the ModelBinder runs the validation of the Model, then there is a problem:
If a Property-level ValidationAttribute contains an error, then the Class-level ValidationAttribute's are NOT validated. I have not found a solution to this problem as of yet.
If you have a solution to this problem please share your experience. Thanks alot!
The default ASP.NET MVC 2 template of Visual Studio includes the exact validation attribute you need. Pasted from AccountModels.cs file :
[AttributeUsage(AttributeTargets.Class,
AllowMultiple = true, Inherited = true)]
public sealed class PropertiesMustMatchAttribute : ValidationAttribute {
private const string _defaultErrorMessage =
"'{0}' and '{1}' do not match.";
private readonly object _typeId = new object();
public PropertiesMustMatchAttribute(string originalProperty,
string confirmProperty)
: base(_defaultErrorMessage) {
OriginalProperty = originalProperty;
ConfirmProperty = confirmProperty;
}
public string ConfirmProperty { get; private set; }
public string OriginalProperty { get; private set; }
public override object TypeId {
get {
return _typeId;
}
}
public override string FormatErrorMessage(string name) {
return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
OriginalProperty, ConfirmProperty);
}
public override bool IsValid(object value) {
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(value);
object originalValue = properties.Find(OriginalProperty,
true /* ignoreCase */).GetValue(value);
object confirmValue = properties.Find(ConfirmProperty,
true /* ignoreCase */).GetValue(value);
return Object.Equals(originalValue, confirmValue);
}
}
How to use :
[PropertiesMustMatch("Password", "ConfirmPassword",
ErrorMessage = "The password and confirmation password do not match.")]
class NewUser {
[Required]
[DataType(DataType.Password)]
[DisplayName("Password")]
public string Password { get; set; }
[Required]
[DataType(DataType.Password)]
[DisplayName("Confirm password")]
public string ConfirmPassword { get; set; }
}

Resources