I have a LINQ-TO-SQL model with a table that contains three columns. The usual ID (identity, autogenerated), then A of type int and B of type varchar(MAX). All columns are defined in the database as NOT NULL.
On a WebForms-page I declared an DetailsView that binds to the items:
<asp:ValidationSummary runat="server" ShowModelStateErrors="true" />
<asp:DetailsView DataKeyNames="Id" runat="server" ItemType="test.MyTable"
SelectMethod="..." UpdateMethod="...">
<Fields>
<asp:DynamicField DataField="A" />
<asp:TemplateField>
<EditItemTemplate>
<asp:TextBox ID="B" runat="server" TextMode="MultiLine" Columns="80" Rows="8" Text="<%# BindItem.B %>" />
</EditItemTemplate>
<ItemTemplate>
<pre><asp:Label runat="server" Text="<%# Item.B %>" /></pre>
</ItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView>
All this code runs in Visual Studio 2012, on ASP.NET 4.5.
So far so good. Updating and viewing works. The problem begins when I enter invalid values. Using "" for field A results in a nice error message at the top of the page. Yay! However, when I use "" as value for field B this happens:
public void DetailsView_UpdateItem(int id)
{
var item = db.MyTable.Where(row => row.Id==id).Single();
TryUpdateModel(item);
if (ModelState.IsValid)
db.SubmitChanges();
}
I do not understand why ModelState.IsValid would return true when the data model specified that B cannot be null. Can somebody explain? What am I doing wrong?
One thing I tried was adding Data Annotations to the data classes by including the following code. It didn't work.
[MetadataType(typeof(MyTableMetadata))]
public partial class MyTable
{
}
public class MyTableMetadata
{
[Required]
[StringLength(255,MinimumLength=1)]
public string B { get; set; }
}
It's obvious that I could manually check for null in the UpdateItem method or that I could add a RequiredFieldValidator - but I'd prefer not to.
Just some arbitrary suggestions: Ensure, that you are referencing System.ComponentModel.DataAnnotations 3.5. (not 3.6) or some other correct namespace for that (as far as i got it, there are some for WCF RIA services only). try different setting for [DisplayFormat(ConvertEmptyStringToNull = ... )] Ensure that you're doing a POST request =)
Why do you think you are getting a null value? An empty string is not equivalent to null. You can confirm this by manually checking for null, like you suggested.
You can add a StringLengthAttribute
to enforce a non-empty constraint in addition to a non-null constraint.
The TryUpdateModel() method essentially (simplifying a lot) uses the name of the field/property in the model class to look for the posted value in forms collection of the post. In the case of an asp.net grid with you specifying the ID = B for the textbox, the name of the control becomes something like ctl00$B. The model binder is not going to be able to connect the dots and obtain the value from the forms collection even though it is present in the post.
I feel that using "asp:BoundField" for your editable field might solve your problem. You may also consider writing a custom model binder or assign the value yourself. Changing the name of the property in the model to match the name of the generated control is another way to solve the problem (Please, don't pick this option though.)
TryUpdateModel() would return false when it finds the value in the post but couldn't cast the value to the type in the model. Otherwise it returns true.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With