I'm using MVC 2 with some Models from a LinqToSql project that I built. I see that when I post back to a Controller Action after editing a form that has a DateTime field from the Model, the MVC Html.ValidationMessageFor() helper will nicely display an error
beside the Date text box.
This seems to happen automatically when the you test ModelState.IsValid() in the Controller Action, as if the MVC model binding automatically knows that the DateTime field cannot be empty.
My question is... I have some other string fields in these LinqToSql generated classes that are Not-Nullable (marked as Not Nullable in Sql Server which passes thourgh to the LinqToSql generated classes), so why doesn't Mr. MVC pick up on those as well and
display a "Required" message in the ValidationMessageFor() placeholders I have added for those fields?
Sure, I have successfully added the MetadataType(typeof<t>) buddy classes to cover these Non-nullable string fields, but it sure does seem redundant to add all this metadata in buddy classes when the LinqToSql generated classes already contain enough info
that MVC could sniff out. It MVC validation works with DateTime automatically, why not these Not-nullable fields too?
I'm sure it's because the default modelbinder works with DataAnnotations and the the Linq to sql classes are annotated with attributes from the System.Data.Linq namespace for their mapping.
I created a little class to help me parse the linq to sql attributes, at the moment I have a solution that implements CustomTypeDescriptors on my linq to sql classes to augment the Column attributes with DataAnnotations. I now think this is overly complex
and I'm going to move the code to a custom MetadataProvider/custom MetadataValidationProvider.
I'll post the attribute parser code anyway. Using this I don't have to create a buddy class I can just examine the linq to sql metadata in a generic way. i.e. for each existing attribute use the parser to see if its required/needs stringlength, and if so
emit these as validators with the standard dataannotation validation providers results
public class LinqToSqlAttributeParser
{
public static readonly string[] TextTypes = new string[] { "char", "varchar", "nchar", "nvarchar" };
public static readonly string LengthRegex = "[" + string.Join("|", TextTypes) + "]\\((.*)\\)";
public bool IsNotNull(ColumnAttribute column)
{
if (column == null) return false;
if (column.DbType == null) return false;
return string.Compare(column.DbType, "NOT NULL", true) == 0;
}
public int? ExtractLength(ColumnAttribute column)
{
if (column == null) return null;
if (column.DbType == null) return null;
Match match = Regex.Match(column.DbType.ToLower(), LengthRegex, RegexOptions.Compiled);
if (match == null || match.Groups.Count != 2) return null;
if (string.Compare(match.Groups[1].Value.ToLower(), "MAX", true) == 0) return int.MaxValue;
return int.Parse(match.Groups[1].Value);
}
}
kind regards,
Paul
http://pabloblamirez.blogspot.com - When you ask a question, remember to click "mark as answered" when you get a reply which answers your question; this ensures the right forum member gets credit below for being helpful (and makes search more relevant too).
I know the two have different annotation mechanisms, that's why I'm so confused as to why the MVC validation notices the DateTime as empty. I have not told the MVC model *anything* about the validation for that field, yet it knows that it is required!
MVC is looking at something to know this. So, my arguments (question) is: If MVC can know the date is required, why stop there? It should (could) look at the other fields too and come to the same conclusion about them.
The binder knows only about static type information. Since DateTime is a non-nullable value type, the binder can detect that null incoming values have absolutely no chance of being bound correctly.
Since String is a reference type, it can accept null values, so the binder attempts to setthese properties to null. It has no way of knowing from the static type information itself that the backing column in the database is non-nullable.
Marked as answer by ricka6 on Mar 15, 2010 07:47 PM
TheRealMattS...
Member
22 Points
19 Posts
Model validation happens automatically with LinqToSql DateTime fields, but not other NOT NULL fie...
Mar 15, 2010 04:50 AM|LINK
I'm using MVC 2 with some Models from a LinqToSql project that I built. I see that when I post back to a Controller Action after editing a form that has a DateTime field from the Model, the MVC Html.ValidationMessageFor() helper will nicely display an error beside the Date text box.
This seems to happen automatically when the you test ModelState.IsValid() in the Controller Action, as if the MVC model binding automatically knows that the DateTime field cannot be empty.
My question is... I have some other string fields in these LinqToSql generated classes that are Not-Nullable (marked as Not Nullable in Sql Server which passes thourgh to the LinqToSql generated classes), so why doesn't Mr. MVC pick up on those as well and display a "Required" message in the ValidationMessageFor() placeholders I have added for those fields?
Sure, I have successfully added the MetadataType(typeof<t>) buddy classes to cover these Non-nullable string fields, but it sure does seem redundant to add all this metadata in buddy classes when the LinqToSql generated classes already contain enough info that MVC could sniff out. It MVC validation works with DateTime automatically, why not these Not-nullable fields too?
ignatandrei
All-Star
135204 Points
21687 Posts
Moderator
MVP
Re: Model validation happens automatically with LinqToSql DateTime fields, but not other NOT NULL...
Mar 15, 2010 05:22 AM|LINK
MVC2 automatically validates all object instead of validating just the input data properties from HTML.
Not sure why do you have this behaviour -could you post some relevant code?
And, if you want not to validate all model, use http://blog.stevensanderson.com/2010/02/19/partial-validation-in-aspnet-mvc-2/
PaulBlamire
Participant
1272 Points
227 Posts
Re: Model validation happens automatically with LinqToSql DateTime fields, but not other NOT NULL...
Mar 15, 2010 06:49 AM|LINK
Hi,
I'm sure it's because the default modelbinder works with DataAnnotations and the the Linq to sql classes are annotated with attributes from the System.Data.Linq namespace for their mapping.
I created a little class to help me parse the linq to sql attributes, at the moment I have a solution that implements CustomTypeDescriptors on my linq to sql classes to augment the Column attributes with DataAnnotations. I now think this is overly complex and I'm going to move the code to a custom MetadataProvider/custom MetadataValidationProvider.
I'll post the attribute parser code anyway. Using this I don't have to create a buddy class I can just examine the linq to sql metadata in a generic way. i.e. for each existing attribute use the parser to see if its required/needs stringlength, and if so emit these as validators with the standard dataannotation validation providers results
public class LinqToSqlAttributeParser { public static readonly string[] TextTypes = new string[] { "char", "varchar", "nchar", "nvarchar" }; public static readonly string LengthRegex = "[" + string.Join("|", TextTypes) + "]\\((.*)\\)"; public bool IsNotNull(ColumnAttribute column) { if (column == null) return false; if (column.DbType == null) return false; return string.Compare(column.DbType, "NOT NULL", true) == 0; } public int? ExtractLength(ColumnAttribute column) { if (column == null) return null; if (column.DbType == null) return null; Match match = Regex.Match(column.DbType.ToLower(), LengthRegex, RegexOptions.Compiled); if (match == null || match.Groups.Count != 2) return null; if (string.Compare(match.Groups[1].Value.ToLower(), "MAX", true) == 0) return int.MaxValue; return int.Parse(match.Groups[1].Value); } }kind regards,
Paul
TheRealMattS...
Member
22 Points
19 Posts
Re: Model validation happens automatically with LinqToSql DateTime fields, but not other NOT NULL...
Mar 15, 2010 01:47 PM|LINK
I know the two have different annotation mechanisms, that's why I'm so confused as to why the MVC validation notices the DateTime as empty. I have not told the MVC model *anything* about the validation for that field, yet it knows that it is required! MVC is looking at something to know this. So, my arguments (question) is: If MVC can know the date is required, why stop there? It should (could) look at the other fields too and come to the same conclusion about them.
levib
Star
7702 Points
1099 Posts
Microsoft
Re: Model validation happens automatically with LinqToSql DateTime fields, but not other NOT NULL...
Mar 15, 2010 04:35 PM|LINK
The binder knows only about static type information. Since DateTime is a non-nullable value type, the binder can detect that null incoming values have absolutely no chance of being bound correctly.
Since String is a reference type, it can accept null values, so the binder attempts to setthese properties to null. It has no way of knowing from the static type information itself that the backing column in the database is non-nullable.