Question

VS 2010 Beta 2, .NET 4.

In my ASP.NET MVC 2 application, when I submit a form to an action method that accepts an object created by the entity framework, I get the following error:

Exception Details: System.Data.ConstraintException: This property cannot be set to a  
null value.

Source Error: 


Line 4500:                OnTextChanging(value);
Line 4501:                ReportPropertyChanging("Text");
Line 4502:                _Text = StructuralObject.SetValidValue(value, false);
Line 4503:                ReportPropertyChanged("Text");
Line 4504:                OnTextChanged();

The property is called "Text" and is of type "text NOT NULL" in MS SQL 2008.

My action will check if the value is nullorempty, if it is, a model error will be added, but I get the error as soon as I submit the form.

Was it helpful?

Solution

Are you binding directly to the entity? Sure looks like it. So you have two choices:

  1. Write a custom model binder which translates null -> empty string.
  2. Bind to an edit model which allows nulls instead, and then change this to empty string when you copy the values to the entity in the action.

I'd choose #2, personally. I think you should always use view/edit models, and this is a great example of why.

OTHER TIPS

I was having the same problem. I looked around and found a work around here. It describes the problem as being caused by the EF validation taking place before the Required field validation. It also shows how we can work around this problem by using a [DisplayFormat] Tag. Hope this will help you.

Here's the link to the question and the workaround:

Server-side validation of a REQUIRED String Property in MVC2 Entity Framework 4 does not work

Is this an issue with the MVC2 and Entity Framework 4 or is this by design? It appears that validation of EF properties works fine for datetime non-nullable (required) fields and data type validation of numeric versus string fields is working without having to use ViewModels.

I recreated the issue using with a simple FOOBAR table using a single, non-nullable varchar(50) column called barName in slq 2008. I generated the EF model from that database and quickly added a controller and a CREATE view for the FOOBAR entity. If I try to POST to the CREATE action without entering in a value for the property barName, VS steps into an exception within the designer.cs file of the model (just like the one above). When, I try to step past the exception, the validation message shows up on the form and the field is highlighted in pink.

It seems like something is not firing in the correct sequence. Because the exception occurs before VS steps into the HTTPPOST CREATE method.

I found the code from the ASP.Net MvcMusicStore sample helpful. http://mvcmusicstore.codeplex.com/releases/view/44445#DownloadId=119336

It appears that binding to the ViewModel fixes the issue.

namespace MvcMusicStore.ViewModels
{
    public class StoreManagerViewModel
    {
        public Album Album { get; set; }
        public List<Artist> Artists { get; set; }
        public List<Genre> Genres { get; set; }
    }
}
........

namespace MvcMusicStore.Models
{
    [MetadataType(typeof(AlbumMetaData))]
    public partial class Album
    {
        // Validation rules for the Album class

        [Bind(Exclude = "AlbumId")]
        public class AlbumMetaData
        {
            [ScaffoldColumn(false)]
            public object AlbumId { get; set; }

            [DisplayName("Genre")]
            public object GenreId { get; set; }

            [DisplayName("Artist")]
            public object ArtistId { get; set; }

            [Required(ErrorMessage = "An Album Title is required")]
            [StringLength(160)]
            public object Title { get; set; }

            [DisplayName("Album Art URL")]
            [StringLength(1024)]
            public object AlbumArtUrl { get; set; }

            [Required(ErrorMessage = "Price is required")]
            [Range(0.01, 100.00, ErrorMessage="Price must be between 0.01 and 100.00")]
            public object Price { get; set; }
        }
    }
}

Ashish Shakya's answer helped me. I added this attribute to the property and now it works.

[DisplayFormat(ConvertEmptyStringToNull = false, NullDisplayText="")]

So it looks like this:

    [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
    [DataMemberAttribute()]
    [DisplayFormat(ConvertEmptyStringToNull = false, NullDisplayText="")]
    public global::System.String MyProperty
    {
        get
        {
            return _MyProperty;
        }
        set
        {
            OnMyPropertyChanging(value);
            ReportPropertyChanging("MyProperty");
            _MyProperty = StructuralObject.SetValidValue(value, false);
            ReportPropertyChanged("MyProperty");
            OnMyPropertyChanged();
        }
    }

Import the namespace:

using System.ComponentModel.DataAnnotations;

And add the attribute property [Required]

[Required]
public global::System.String MyProperty
    {
        get
        {
            return _MyProperty;
        }
        set
        {
            OnMyPropertyChanging(value);
            ReportPropertyChanging("MyProperty");
            _MyProperty = StructuralObject.SetValidValue(value, false);
            ReportPropertyChanged("MyProperty");
            OnMyPropertyChanged();
        }
    }

Thus ModelState.IsValid equals false, showing error message in the validation and will not fail on the server with Null.

I had the same problem and fixed it by making false to true like this:

Line 4502:
_Text = StructuralObject.SetValidValue(value, false);

I just had the same problem myself, and came here to find the solution. However, the answer can be enhanced.

Svavar's and HackITMngr were on the right track, however combining both gives the best outcome. You don't want to go decorating the generated classes, as you risk losing your custom changes upon modifications to the EF model.

[MetadataType(typeof(MyTableMetaData))] public partial class MyTable { // Validation rules for the Album class

    public class MyTableMetaData
    {
        [DisplayFormat(ConvertEmptyStringToNull = false, NullDisplayText="")]
        public string MyTextProperty { get; set; }
    }
}

To settle any arguments between the two. I'd say Svavar's was the direct answer, HackITMngr was the enhancement.

Works great for me!

I set StoreGeneratedPattern property as Computed for each field and it solved the problem for me.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top