ModelState.AddModelError - Como posso adicionar um erro que não é para uma propriedade?

188

Estou verificando meu banco de dados Create(FooViewModel fvm){...}para ver se o fvm.prop1e fvm.prop2já existe nessa combinação; Nesse caso, desejo adicionar um erro ao modelstate e retornar a exibição inteira. Eu tentei:

public ActionResult Create(FooViewModel fvm){
    if (ThatComboAlreadyExists(fvm)) {
      ModelState.AddModelError("Model", "There is already one like that");
      return View(fvm);
    }
}

... mas não consigo exibir erros no Html.ValidationSummary, que é onde suponho que eles apareceriam. Suspeito que "Modelo" não seja a chave certa, mas não consegui encontrar nada no Google.

Scott Baker
fonte

Respostas:

328

Acabei encontrando um exemplo do uso que estava procurando - para atribuir um erro ao Modelo em geral, em vez de uma de suas propriedades, como de costume:

ModelState.AddModelError(string key, string errorMessage);

mas use uma string vazia para a chave:

ModelState.AddModelError(string.Empty, "There is something wrong with Foo.");

A mensagem de erro será apresentada <%: Html.ValidationSummary() %>como você esperaria.

Scott Baker
fonte
21
Este caso me faz pensar: por que não existe um método como ModelState.AddError(errorMessage)ou ModelState.AddGlobalError(errorMessage)... seria intuitivo e mais fácil descobrir como adicionar uma mensagem de erro não relacionada às propriedades de nenhum modelo.
Rubens Mariuzzo
@ Rubens: Verdade, mas você pode facilmente adicionar esse método com métodos de extensão.
Johnny5
2
Você também pode exibir o erro usando@Html.ValidationMessage(string.Empty)
Ben Foster
a chave é a propriedade do seu modelo vinculada à visualização - que possui o erro - apenas para ficar claro.
Niico 19/10/16
1
A ValidationSummaryErrors(bool excludePropertyErrors)sobrecarga exibirá todos os erros de validação se o argumento for falso ou apenas erros não específicos da propriedade (chave = "") se o argumento for verdadeiro.
precisa saber é o seguinte
26

Você pode adicionar o erro de modelo em qualquer propriedade do seu modelo, sugiro que não haja nada relacionado à criação de uma nova propriedade.

Como exemplo, verificamos se o email já está em uso no DB e adicionamos o erro à propriedade Email na ação. Assim, quando eu retorno a exibição, eles sabem que há um erro e como mostrá-lo usando

<%: Html.ValidationSummary(true)%>
<%: Html.ValidationMessageFor(model => model.Email) %>

e

ModelState.AddModelError("Email", Resources.EmailInUse);
VinnyG
fonte
1
Isso parece contra-intuitivo no meu caso - estou verificando se uma combinação específica de col1 e col2 já existe no banco de dados, portanto, não parece certo ter a propriedade IsDuplicateOfAnotherRow no meu ViewModel. Acontece que você pode adicionar um erro ao seu modelo - veja minha resposta.
Scott Baker
1
Existe uma maneira de obter a string "Email" para AddModelError sem usar uma string literal frágil? Gosta (m=>m.email).SomeMagicToString()?
Snekse
Eu não penso assim, você tem que ir com a corda mágica ... não o melhor, mas ainda uma boa solução
VinnyG
4
O nameofoperador que vem no C # 6.0 resolve esse problema de cadeia mágica. msdn.microsoft.com/pt-br/magazine/dn802602.aspx
RJ Cuthbertson
3

Colocar a propriedade dot model em strings funcionou para mim: ModelState.AddModelError("Item1.Month", "This is not a valid date");

Chris
fonte
2
Isso realmente mostraria um mês inválido na sua interface do usuário, mas não resolve o problema original.
Scott Baker
2
O problema original decorre de não entender o que "chave" representa no método. Isso esclarece como funciona a "chave", por isso é bom saber que a chave não precisa ser apenas um nome de propriedade, mas também pode se referir a propriedades aninhadas ou ao valor especial String.Empty.
Triynko