ASP.Net MVC 2 Model Validation Regex Validator fails - asp.net-mvc-2

I have following property in my Model Metadata class:
[Required(ErrorMessage = "Spent On is required")]
[RegularExpression(#"[0-1][0-9]/[0-3][0-9]/20[12][0-9]",
ErrorMessage = "Please enter date in mm/dd/yyyy format")]
[DataType(DataType.Date)]
[DisplayName("Spent On")]
public DateTime SpentOn { get; set; }
But whenever I call ModelState.IsValid it always returns false because regex is not validating. I have matched the entered date (08/29/2010) against new regex using same pattern and it matches perfectly.
What am I doing wrong?

Actualy there is another workaround for this. You can simply subclass the RegularExpressionAttribute
public class DateFormatValidatorAttribute : RegularExpressionAttribute {
public DateFormatValidatorAttribute()
: base(#"[0-1][0-9]/[0-3][0-9]/20[12][0-9]")
{
ErrorMessage = "Please enter date in mm/dd/yyyy format";
}
public override bool IsValid(object value) {
return true;
}
}
in your Global.asax.cs on application start register the RegularExpression addapter for client side validation like so:
DataAnnotationsModelValidatorProvider.RegisterAdapter(
typeof(DateFormatValidatorAttribute),
typeof(RegularExpressionAttributeAdapter));
Now you get to have the build-in MVC regular exression validator client side and keep the DateTime as your property type

That's because regex applies to strings and not DateTime properties. If the user enters an invalid string which cannot be parsed to a DateTime instance from the model binder it will add a generic error message before your regex pattern executes.
You have a couple of possibilities:
Customize the error message in a resource file
Write a custom model binder
Use a string property (I feel guilty for proposing this :-))

Related

How Do I Format Date in Model or Linq Query for Controller Output

I have an API controller that renders a JSON result which is used by the infinite scroll plugin. Unfortunately, I don't see any way to format the output using the plugin itself, so I have to make sure the output is properly formatted before it is sent to the controller.
I have run into a problem with DateTime because all the examples I can find for formatting it rely on using server side code in the view. That is not an option with infinite scroll.
Preferably this should be done in the LINQ query or the model. I tried changing my model to:
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime? Date
{
get;
set;
}
That did not work. Likewise, changing the part of the select clause of the link query that says Date = p.Date to stuff like Convert.ToDateTime(p.Date).ToString("dddd MMMM dd, yyyy") doesn't work because you can't implicitly convert a string to date or something. That last example is exactly how I do it in the view.
How do I replicate that output in the JSON of an API controller?
NEW: The same seems true with decimals. I have prices that should include two decimals, but the JSON output in the controller only has as many as the user put in. This results in stuff like $20.5 followed by $0 and $22.55. The last of course being correct.
My price model looks like this:
[Required(ErrorMessage = "Price Required!")]
[Range(.00, Double.PositiveInfinity, ErrorMessage = "Must Be Positive Number!")]
[Display(Name = "Price:")]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal? Price { get; set; }
Try this...
public DateTime? Date { get; set; }
public string StringDate
{
set => Date?.ToString("0:MM/dd/yyyy")
}

Extend EF 6.2 with new mapping rules

NHibernate can be extended with new implementations of IUserType, so I can customize how a mapped property is read and stored to/from the database.
An example. If I want DB null varchar to load as "n/a" string, and "n/a" string to be stored as null.
How is this possible with EF 6.2?
I am looking for a solution that doesn't break the change-tracker.
As of EF 6.2, there is no such functionality provided out of the box by the library.
If you decide to move to EF Core instead, there you can use the HasConversion functionality.
However, in your case you still wouldn't be able to use it, because there is one caveat: it can't be used to convert null values. Null always gets converted to null. From docs:
A null value will never be passed to a value converter. A null in a database column is always a null in the entity instance, and vice-versa. This makes the implementation of conversions easier and allows them to be shared amongst nullable and non-nullable properties. See GitHub issue #13850 for more information.
In that case, I suggest that instead of a Value Conversion you configure your string property to have a Backing Field. Then, you can read/write to/from the private backing field, and then have a public property handling the null value.
public class Blog
{
private string _stringFromDb;
public string MyString { get; set; }
[BackingField(nameof(_stringFromDb))]
public string MyString
{
get { return _stringFromDb ?? "n/a"; }
}
public void SetMyString(string myString)
{
// put your validation code here
_stringFromDb = myString;
}
}
In EF 6.2 the closest you could have, as a workaround, is a [NotMapped] property that can be in charge of translating the property you load from the DB.
public string StringDB { get; set; }
[NotMapped]
public string StringConverted
{
get { return MyStringProperty ?? "n/a"; }
set { MyStringProperty = value }
}
If, in addition to this, you want to hide the property being mapped to your DB by making it private, it's not as straightforward as with EF Core's backing field, but you could follow this other answer for instructions on how to achieve it.

Validate Unique Value in MVC5 and EF6

In my MVC application I have a requirement where I want user to insert Unique value in a column.
i.e.: Username should be unique in Users table.
I used [Indes(IsUnique = true)] data annotation in my model.
But when I insert duplicate value in the field it throws an exception, but I want to display an Error Message on my View saying Please try with a different Username
Please help me what should I do here?
You can use one of those:
Write your CustomValidator (ny recommendation)
[CustomRemoteValidator(ErrorMessage = #"Username already in use")]
public string Username{ get; set; }`
And override IsValid method
public override bool IsValid(object value)
{
return !(this.DbContext.Set<User>().Any(a =>
a.Username.Equals((string)value));
}
Check it in your business layer.
Check it before save entity in database by overriding SaveChanges() method.

MVC-type validation

Hey i have model and it looks like this:
[Required(ErrorMessage = "Morate unijeti vrijednost")]
public int Cijena{ set; get; }
If user doesn't enter value , my error message is being written, but if user enter value that is not int I got this message "The value '' is not valid for Cijena" . How can I overwrite this message with custom one?
Thx
Use a regular expression validator as well
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.regularexpressionattribute(v=vs.95).aspx
[RegularExpression(Pattern=#"\d+", ErrorMessage="only numbers please")]

How to change ErrorMessage property of the DataAnnotation validation in MVC2.0

My task is to change the ErrorMessage property of the DataAnnotation validation attribute in MVC2.0. For example I should be able to pass an ID instead of the actual error message for the Model property and use that ID to retrieve some content(error message) from a another service e.g database, and display that error message in the View instead of the ID. In order to do this I need to set the DataAnnotation validation attribute’s ErrorMessage property.
[StringLength(2, ErrorMessage = "EmailContentID.")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
It seems like an easy task by just overriding the DataAnnotationsModelValidatorProvider ‘s
protected override IEnumerable GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable attributes)
However it seems to be a complicated enough.
a. MVC DatannotationsModelValidator’s ErrorMessage property is read only. So I cannot set anything here
b. System.ComponentModel.DataAnnotationErrorMessage property(get and set) which is already set in MVC DatannotationsModelValidator so we cannot set again. If you try to set you get “The property cannot set more than once…” error message appears.
public class CustomDataAnnotationProvider : DataAnnotationsModelValidatorProvider
{
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
IEnumerable<ModelValidator> validators = base.GetValidators(metadata, context, attributes);
foreach (ValidationAttribute validator in validators.OfType<ValidationAttribute>())
{
messageId = validator.ErrorMessage;
validator.ErrorMessage = "Error string from DB And" + messageId ;
}
//......
}
}
Can anyone please help me on this?
Here is the question: What is your motivation to changing the error message property?
Think this through very carefully, as you are heading down a path where you are obfuscating what is actually happening in the application. Certainly the database informatino is useful, but it is not really part of the validation, nor should it be.
When you head in this direction, you are essentially saying that the validation can only be invalid if there is a database problem. I see two issues with this:
It breaks the separation of concerns. You are reporting a persistance error in the model, which is not where it occurred.
The solution is not unit testable, as you must engage the database.
I don't like either of the two above.
Can you solve this? Possibly if you will create your own custom validation attribute. I would have to check and ensure that is correct. Another option is to aim for custom validation:
http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx
This article can also help you head in the direction you desire:
http://ryanrivest.com/blog/archive/2010/01/15/reusable-validation-error-message-resource-strings-for-dataannotations.aspx
Do you want to solve this? Not really if you are attempting to keep a proper separation of concerns in your application. I would not polute my validation error message (this is not valid) with a database error (I am not valid, but the database also blew up). Just my two cents.
There are built in ways to get the error message via a resource. Instead of a database lookup to get a resource at runtime, generate resources from your database and use that for your error messages.
You can then use the ErrorMessageResourceName and ErrorMessageResourceType to allow the DataAnnotation to perform a resource lookup instead of hard-coding a specific string.
public sealed class MyModel
{
[Required(
ErrorMessageResourceName="MyDescriptionResource",
ErrorMessageResourceType=typeof(MyCustomResource))]
public string Description { get; set; }
}
Also you may want to have a look at ValidationAttribute.FormatErrorMessage Method on msdn.
This method formats an error message
by using the ErrorMessageString
property. This method appends the name
of the data field that triggered the
error to the formatted error message.
You can customize how the error
message is formatted by creating a
derived class that overrides this
method.
A quick sample (and not meant to be a definitive example)
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false,
Inherited = true)]
public sealed class PostCodeValidationAttribute
: ValidationAttribute
{
public override bool IsValid(object value)
{
if( value == null )
return true;
string postCode = value as string;
if( string.IsNullOrEmpty(postCode) )
return true;
if ( !PostCode.IsValidPostCode(postCode, this.PostCodeStyle) )
return false;
return true;
}
public PostCodeStyle PostCodeStyle { get; set; }
public override string FormatErrorMessage(string name)
{
return string.Format(
"{0} is not a valid postcode for {1}", name, PostCodeStyle);
}
}
* I've omitted the PostCodeStyle enumeration as well as the PostCode class for validating a postcode.