views:

42

answers:

1

I've just ran into an unexpected behaviour for Entity framework entities in use with ASP.NET MVC application with SQL Server as datastore. For a column marked as not null allowed I did not set up data annotation Required attribute inside the entities' metadata partial class (I was under impression that I had to for all properties that I wish to make mandatory) but after the POST from my view the controller action returned to the same view as a result of this check

        // check for errors
        if (!ViewData.ModelState.IsValid)
            return View(invoice);

with a description that a property should not be null. I deliberately posted the textbox for the property empty and I have no custom (manual) Data Annotation attributes in place for this property.

This is the EF wizard generated code for this property

    [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
    [DataMemberAttribute()]
    public global::System.DateTime PayDate
    {
        get
        {
            return _PayDate;
        }
        set
        {
            OnPayDateChanging(value);
            ReportPropertyChanging("PayDate");
            _PayDate = StructuralObject.SetValidValue(value);
            ReportPropertyChanged("PayDate");
            OnPayDateChanged();
        }
    }
    private global::System.DateTime _PayDate;
    partial void OnPayDateChanging(global::System.DateTime value);
    partial void OnPayDateChanged();

Is it the IsNullable attribute's fault for this kind of behaviour? Let me be clear that if it indeed is so, then this is quite nice, though I haven't noticed it before and would like to verify if that's the right behaviour or do I have something messed up there?

+4  A: 

There are a couple of different things going on here. First, EF will generate the property as DateTime for NOT NULL date columns in the database and it will generate Nullable for NULL date columns in the database. That's point one.

Point two is that MVC 2 has some "default" behavior in the default model binder. That is, for all value types it will perform a validation (independent of data annotations) that the user typed in a value. If they didn't it will show the validation that you are currently seeing.

So that explains what you are seeing. However, there are a couple other points to keep in mind. First, it's still a good practice to use the [Required] attribute because this allows you to customize the error message displayed to the user. Secondly, it's generally considered best practices to use a view model for your views rather than your EF domain model directly in your views. So I'd recommend creating a view model (you can just use AutoMapper to map the properties if your view model matches your domain model), and then using the data annotations to provide more fine-grained control over the metadata - not just validation, but also [DisplayName], [UIHint], etc.

Steve Michelotti
I've already established that for this particular project I don't require View models because they would be very similar, if not identical to the Business model classes generated by EF. Other than that, your answer seems fine.
mare
OK, but just keep in mind what I said as your project progresses. Without view models you could make things more complicated than they need to be. how will you handle validation? Are you going to modify the generated EF code to apply the various data annotations you need? if so, you won't be able to regen the code for DB changes. What if you want to take advantage of MVC's rich metadata infrastructure by apply UIHint's or other UI metadata attributes? Those are presentation concerns that belong in the view models and you want to keep presentation concerns out of your domain model.
Steve Michelotti