Pergunta

VS 2010 Beta 2, .NET 4.

Na minha aplicação ASP.NET MVC 2, quando submeto um formulário para um método de ação que aceita um objeto criado pela estrutura de entidade, recebo o seguinte erro:

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();

A propriedade é chamada de "Texto" e é do tipo "text NOT NULL" no MS SQL 2008.

Minha ação irá verificar se o valor é nulo ou vazio, se for, um erro de modelo será adicionado, mas recebo o erro assim que envio o formulário.

Foi útil?

Solução

Você está se vinculando diretamente à entidade? Com certeza parece. Então você tem duas opções:

  1. Escreva um fichário de modelo personalizado que traduz nulo -> String vazia.
  2. Ligue -se a um modelo de edição que permite os nulos e, em seguida, altere isso para esvaziar a string ao copiar os valores para a entidade na ação.

Eu escolheria o #2, pessoalmente. Eu acho que você deve sempre usar modelos de visualização/edição, e este é um ótimo exemplo do porquê.

Outras dicas

Eu estava tendo o mesmo problema. Olhei em volta e encontrei um trabalho por aqui. Ele descreve o problema como sendo causado pela validação da EF que ocorre antes da validação de campo necessária. Ele também mostra como podemos resolver esse problema usando um [DisplayFormat] Marcação. Espero que isso ajude você.

Aqui está o link para a pergunta e a solução alternativa:

A validação do lado do servidor de uma propriedade de string necessária no MVC2 Entity Framework 4 não funciona

Isso é um problema com o MVC2 e o Entity Framework 4 ou é intencional?Parece que a validação das propriedades EF funciona bem para campos não anuláveis ​​(obrigatórios) de data e hora e a validação do tipo de dados de campos numéricos versus campos de string está funcionando sem a necessidade de usar ViewModels.

Recriei o problema usando uma tabela FOOBAR simples usando uma coluna varchar(50) única e não anulável chamada barName no slq 2008.Gerei o modelo EF desse banco de dados e adicionei rapidamente um controlador e uma visualização CREATE para a entidade FOOBAR.Se eu tentar POST para a ação CREATE sem inserir um valor para a propriedade barName, o VS entrará em uma exceção no arquivo designer.cs do modelo (assim como o acima).Quando tento ultrapassar a exceção, a mensagem de validação aparece no formulário e o campo fica destacado em rosa.

Parece que algo não está disparando na sequência correta.Porque a exceção ocorre antes do VS entrar no método HTTPPOST CREATE.

Achei o código do exemplo ASP.Net MvcMusicStore útil. http://mvcmusicstore.codeplex.com/releases/view/44445#DownloadId=119336

Parece que a ligação ao ViewModel corrige o problema.

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; }
        }
    }
}

A resposta de Ashish Shakya me ajudou. Eu adicionei esse atributo à propriedade e agora ele funciona.

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

Então parece isso:

    [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();
        }
    }

Importe o espaço para nome:

using System.ComponentModel.DataAnnotations;

E adicione a propriedade de atributo [Required]

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

Assim, o ModelState.IsValId é igual a False, mostrando a mensagem de erro na validação e não falhará no servidor com NULL.

Eu tive o mesmo problema e corrigi -lo fazendo false para true assim:

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

Eu só tive o mesmo problema e vim aqui para encontrar a solução. No entanto, a resposta pode ser aprimorada.

Svavar's e Hackitmngr estavam no caminho certo, no entanto, a combinação de ambos fornece o melhor resultado. Você não deseja decorar as classes geradas, pois corre o risco de perder suas alterações personalizadas medificações no modelo de EF.

Metadatatype (typeof (mytablemetadata))] Classe Parcial Public MyTable {// Regras de validação para a classe do álbum

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

Para resolver quaisquer argumentos entre os dois. Eu diria que Svavar's foi a resposta direta, o Hackitmngr foi o aprimoramento.

Funciona muito bem para mim!

Defina a propriedade StoreGeneratedPattern, calculada para cada campo e ela resolveu o problema para mim.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top