O ASP.NET MVC Html.ValidationSummary (true) não exibe erros de modelo

194

Estou com algum problema com o Html.ValidationSummary. Não quero exibir erros de propriedade no ValidationSummary. E quando eu defino Html.ValidationSummary (true), ele não exibe mensagens de erro do ModelState. Quando houver alguma exceção na ação do controlador na string

MembersManager.RegisterMember(member);

A seção catch adiciona um erro ao ModelState:

ModelState.AddModelError("error", ex.Message);

Mas ValidationSummary não exibe essa mensagem de erro. Quando defino Html.ValidationSummary (false), todas as mensagens são exibidas, mas não quero exibir erros de propriedade. Como posso resolver este problema?

Aqui está o código que estou usando:

Modelo:

public class Member
{
        [Required(ErrorMessage = "*")]
        [DisplayName("Login:")]
        public string Login { get; set; }

        [Required(ErrorMessage = "*")]
        [DataType(DataType.Password)]
        [DisplayName("Password:")]
        public string Password { get; set; }

        [Required(ErrorMessage = "*")]
        [DataType(DataType.Password)]
        [DisplayName("Confirm Password:")]
        public string ConfirmPassword { get; set; }
}

Controlador:

[HttpPost]
public ActionResult Register(Member member)
{
    try
    {
        if (!ModelState.IsValid)
            return View();

        MembersManager.RegisterMember(member);
    }
    catch (Exception ex)
    {
        ModelState.AddModelError("error", ex.Message);

        return View(member);
    }
}

Visão:

<% using (Html.BeginForm("Register", "Members", FormMethod.Post, 
                        new { enctype = "multipart/form-data" })) {%> 
    <p>
        <%= Html.LabelFor(model => model.Login)%>
        <%= Html.TextBoxFor(model => model.Login)%>
        <%= Html.ValidationMessageFor(model => model.Login)%>
    </p>

    <p>
        <%= Html.LabelFor(model => model.Password)%>
        <%= Html.PasswordFor(model => model.Password)%>
        <%= Html.ValidationMessageFor(model => model.Password)%>
    </p>

    <p>
        <%= Html.LabelFor(model => model.ConfirmPassword)%>
        <%= Html.PasswordFor(model => model.ConfirmPassword)%>
        <%= Html.ValidationMessageFor(model => model.ConfirmPassword)%>
    </p>

    <div>
        <input type="submit" value="Create" />
    </div>

    <%= Html.ValidationSummary(true)%>
<% } %>
msi
fonte

Respostas:

324

Acredito que a maneira como o sinalizador ValidationSummary funciona é que ele exibirá apenas ModelErrors string.emptycomo a chave. Caso contrário, presume-se que seja um erro de propriedade. O erro personalizado que você está adicionando possui a chave 'error', portanto não será exibido quando você chamar ValidationSummary (true). Você precisa adicionar sua mensagem de erro personalizada com uma chave vazia como esta:

ModelState.AddModelError(string.Empty, ex.Message);
Jab
fonte
9
@ LordCover: Eu acho que isso está "funcionando como projetado" e não um bug - a sobrecarga de ValidationSummary () usada por padrão exclui erros ModelState associados às propriedades do modelo em si. Isso deixa esses erros a serem representados pelas chamadas Html.ValidationMessageFor () para cada propriedade individual sem que elas sejam duplicadas no resumo. Assim, parece que qualquer erro de modelo adicionado a uma chave não vazia é considerado associado a uma propriedade de modelo, mesmo que a chave não corresponda ao nome de uma propriedade.
Daniel Schaffer
26
Apenas uma observação para outros implementadores: ModelState.AddModelError(string.Empty, ex);também não parece funcionar. Você deve usar a ModelState.AddModelError(string, string)sobrecarga como mostrado acima.
wolfyuk
2
atualização: No MVC4, isso não parece mais ser o caso. ModelState.AddModelError ("", ex.Message); funciona
Neil Thompson
4
MVC5 Eu ainda precisava ligar para o ex.Message para fazê-lo funcionar.
smiggleworth
salvou o dia! MVC5 ainda tem alguns problemas :)
jufo
67

Isso funciona melhor, pois você pode mostrar validationMessage para uma chave especificada:

    ModelState.AddModelError("keyName","Message");

e exibi-lo assim:

    @Html.ValidationMessage("keyName")
ingvesund
fonte
28

Eu sei que isso é meio antigo e foi marcado como respostas com 147 votos a favor, mas há algo mais a considerar.

Você pode ter todos os erros de modelo, a propriedade nomeada e string.Empty keys iguais, serão mostrados no ValidationSummary, se necessário. Há uma sobrecarga no ValidationSummary que fará isso.

    //   excludePropertyErrors:
    //   true to have the summary display model-level errors only, or false to have
    //   the summary display all errors.
    public static MvcHtmlString ValidationSummary(this HtmlHelper htmlHelper, bool excludePropertyErrors);

insira a descrição da imagem aqui

Levitikon
fonte
5
Sim! Basta mudar @Html.ValidationSummary(true, "", new { @class = "text-danger" })para@Html.ValidationSummary(false, "", new { @class = "text-danger" })
Xeningem 25/03
7

Talvez assim:

[HttpPost]
public ActionResult Register(Member member)
{
    try
    {
       if (!ModelState.IsValid)
       {
          ModelState.AddModelError("keyName", "Form is not valid");
          return View();
       }
       MembersManager.RegisterMember(member);
    }
    catch (Exception ex)
    {
       ModelState.AddModelError("keyName", ex.Message);
       return View(member);
    }
}

E no display adicione:

<div class="alert alert-danger">
  @Html.ValidationMessage("keyName")
</div>

OU

<div class="alert alert-danger">
  @Html.ValidationSummary(false)
</div>
Piotr Knut
fonte
5
@Html.ValidationSummary(false,"", new { @class = "text-danger" })

Usar esta linha pode ser útil

sachind
fonte
Adicione a linha acima no arquivo cshtml.
sachind
2

No meu caso, não estava funcionando por causa do retorno.

Ao invés de usar:

return RedirectToAction("Rescue", "CarteiraEtapaInvestimento", new { id = investimento.Id, idCarteiraEtapaResgate = etapaDoResgate.Id });

Eu usei:

return View("ViewRescueCarteiraEtapaInvestimento", new CarteiraEtapaInvestimentoRescueViewModel { Investimento = investimento, ValorResgate = investimentoViewModel.ValorResgate });

É um modelo, então é óbvio que ModelState.AddModelError("keyName","Message"); deve trabalhar com um modelo.

Esta resposta mostra o porquê. Adicionando validação com DataAnnotations

Allan Patrick Patzlaff
fonte
0

Se quase tudo parece certo, outra coisa a se observar é garantir que o resumo da validação não esteja sendo explicitamente oculto por meio de alguma substituição de CSS como esta:

.validation-summary-valid {
    display: none;
}

Isso também pode fazer com que o @Html.ValidationSummaryapareça oculto, pois o resumo é renderizado dinamicamente com a validation-summary-validclasse.

alex
fonte
0

Podes tentar,

<div asp-validation-summary="All" class="text-danger"></div>
Adrita Sharma
fonte
note - este deve ser um <div>, se for um <span>, não será renderizado.
Stephen Angell
-4

Adicione-o na parte mais baixa da sua visualização:

@ scripts de seção {@ Scripts.Render ("~ / bundles / jqueryval")}

ronIT
fonte