60

I want to show a ValidationSummary mcv3 with "alert-error" Bootstrap styling.

I'm using a Razor view, and I show model errors with this code:

 @Html.ValidationSummary(true, "Errors: ")

It generates HTML code like this:

<div class="validation-summary-errors">
   <span>Errors:</span>
   <ul>
      <li>Error 1</li>
      <li>Error 2</li>
      <li>Error 3</li>
   </ul>
</div>

I tried with this too:

@Html.ValidationSummary(true, "Errors:", new { @class = "alert alert-error" })   

and it works ok, but without the close button (X)

It generates HTML code like this:

<div class="validation-summary-errors alert alert-error">
   <span>Errors:</span>
   <ul>
      <li>Error 1</li>
      <li>Error 2</li>
      <li>Error 3</li>
   </ul>
</div>

but Bootstrap alert should have this button into the div:

<button type="button" class="close" data-dismiss="alert">×</button>

Can anyone help?


This Works! - Thanks Rick B

@if (ViewData.ModelState[""] != null && ViewData.ModelState[""].Errors.Count() > 0) 
{ 
   <div class="alert alert-error"> 
      <a class="close" data-dismiss="alert">×</a> 
      <h5 class="alert-heading">Ingreso Incorrecto</h5> 
      @Html.ValidationSummary(true)
   </div>
} 

I also had to remove the class ".validation-summary-errors" from "site.css", because that style defines other font color and weight.

Gonzalo
  • 2,866
  • 7
  • 27
  • 42
  • What is the HTML produced with the class being set to "alert alert-error". – Rick B Dec 13 '12 at 19:52
  • other way try [this tip](http://stackoverflow.com/a/30323853/2218697) to **return bootstrap alert message** hope helps someone. – Shaiju T May 19 '15 at 11:11
  • Checkout this solution: http://www.codingfusion.com/Post/Displaying-Bootstrap-Alert-for-Validation-Summary-in-ASP-NET-MVC-with-close-butt – MaxPayne Aug 09 '23 at 05:58

16 Answers16

55

edited again

I misunderstood your question at first. I think the following is what you want:

@if (ViewData.ModelState[""] != null && ViewData.ModelState[""].Errors.Count > 0)
{ 
    <div class="alert alert-error">
        <button type="button" class="close" data-dismiss="alert">×</button>
        @Html.ValidationSummary(true, "Errors: ")
    </div>
}
Simua
  • 263
  • 1
  • 10
Rick B
  • 1,156
  • 10
  • 11
  • 1
    That code doesn't work because validationsummary is only visible when there are errors in the model. Your code generates a permanent div in the view. – Gonzalo Dec 13 '12 at 20:09
  • 1
    The point of what I wrote is just to test if the html produces what you are expecting from bootstrap or not. If this simple, static html does not display as you are expecting, you have a css issue. – Rick B Dec 13 '12 at 20:13
  • Ok, I understand. Your code generates the same html, without the close button. It is correct. I need to add button dynamically into the div, because the validationsummary div is generated automatically by Razor when change the model state. Maybe there another way... – Gonzalo Dec 13 '12 at 20:32
  • @user1898594: You should post this as an addendum to your question, not as an edit to the answer. – Alexander Pavlov Dec 14 '12 at 10:45
  • 4
    if (!ViewData.ModelState.IsValid) would be a lot simpler. Can also attach the classes to the validation summary itself using @Html.ValidationSummary(true, "Errors: ", new { @class = "alert alert-danger"}) – Chris Searles Sep 23 '14 at 03:32
39

This answer is based on RickB's one

  • Updated for the latest bootstrap ==>> alert-error doesn't exist in favor of alert-danger.

  • Works for all Validation Errors not only Key String.Empty ("")

For anyone using Bootstrap 3 and trying to get nice looking alerts:

if (ViewData.ModelState.Keys.Any(k=> ViewData.ModelState[k].Errors.Any())) { 
    <div class="alert alert-danger">
        <button class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
        @Html.ValidationSummary(false, "Errors: ")
    </div>
}

The solution provided by RickB works only on manually added errors on (String.Empty key) but not on those generated by ModelState (normally this gets triggered first via javascript but it's always a good practice to have a fallback if (for example) the Html.ValidationMessageFor is missing or many other situations.

Alex Dresko
  • 5,179
  • 3
  • 37
  • 57
Bart Calixto
  • 19,210
  • 11
  • 78
  • 114
35

Alternative solution. =)

@if (ViewData.ModelState.Any(x => x.Value.Errors.Any())) 
{ 
   // Bootstrap 2 = "alert-error", Bootstrap 3 and 4 = "alert-danger"
   <div class="alert alert-danger alert-error"> 
      <a class="close" data-dismiss="alert">&times;</a> 
      @Html.ValidationSummary(true, "Errors: ")
   </div>
}
Tieson T.
  • 20,774
  • 6
  • 77
  • 92
Daniel Björk
  • 2,475
  • 1
  • 19
  • 26
19

I did not like how the ValidationSummary rendered using a bullet list (unordered list). It had a lot of unnecessary space below the error list.

A solution to that issue - is simply to loop through the errors and render the errors how you want. I used paragraphs. For example:

@if (ViewData.ModelState.Any(x => x.Value.Errors.Any()))
{
    <div class="alert alert-danger" role="alert">
        <a class="close" data-dismiss="alert">×</a>
        @foreach (var modelError in Html.ViewData.ModelState.SelectMany(keyValuePair => keyValuePair.Value.Errors))
        {
            <p>@modelError.ErrorMessage</p>
        }
    </div>
}

The result, in my case, looks something like this: enter image description here

Donal
  • 31,121
  • 10
  • 63
  • 72
14
@Html.ValidationSummary("", new { @class = "alert alert-danger" })
Veedrac
  • 58,273
  • 15
  • 112
  • 169
6

Consider writing an extension method to the HtmlHelper like:

public static class HtmlHelperExtensions
{
    public static HtmlString ValidationSummaryBootstrap(this HtmlHelper htmlHelper)
    {
        if (htmlHelper == null)
        {
            throw new ArgumentNullException("htmlHelper");
        }

        if (htmlHelper.ViewData.ModelState.IsValid)
        {
            return new HtmlString(string.Empty);
        }

        return new HtmlString(
            "<div class=\"alert alert-warning\">"
            + htmlHelper.ValidationSummary()
            + "</div>");
    }
}

Then you just need to fit the ul-li styling in your stylesheet.

oexenhave
  • 191
  • 1
  • 3
6

In MVC 5, ViewData.ModelState[""] always returned a null value. I had to resort to the IsValid command.

if (!ViewData.ModelState.IsValid)
{
   <div class="alert alert-danger">
      <a class="close" data-dismiss="alert">×</a>
      <strong>Validation Errors</strong>
      @Html.ValidationSummary()
   </div>
}
Rethic
  • 1,054
  • 4
  • 21
  • 36
3

I took a slightly different route: using JQuery to hook into the form submit:

$('form').each(function() {
    var theForm = $(this);
    theForm.submit(function() {
        if ($(this).valid()) {
            if ($(this).find('.validation-summary-valid').length) {
                $('.validation-summary-errors').hide();
            }
        } else {
            if ($(this).find('.validation-summary-errors').length) {
                $('.validation-summary-errors')
                    .addClass('alert alert-error')
                    .prepend('<p><strong>Validation Exceptions:</strong></p>');
            }
        }
    });
});

I have this set inside a self-executing javascript module so that it hooks onto any validation summaries that I create.

HTH

Chuck

SwampyFox
  • 1,105
  • 9
  • 13
  • The prepend HTML was showing up multiple times on failed resubmit so I had to attach a class to it and wipe it out before the prepend. Otherwise, worked great. Thanks! – manafire Jun 26 '14 at 15:50
  • 1
    @swampyfox, suggested edits to fix prepended title:`var $element = $(".validation-summary-errors"); $element.addClass("alert alert-danger"); if($element.data("hasTitle") === true) {} else $element.prepend("

    Please fix these errors:

    ") .data("hasTitle", true);`
    – TugboatCaptain Sep 10 '14 at 22:03
2

You can use jquery:

$(function(){
 $('.validation-summary-errors.alert.alert-error.alert-block').each(function () {
     $(this).prepend('<button type="button" class="close" data-dismiss="alert">×</button>');
 });
});

It is looking for every div containing given error classes from bootstrap and writing html at beginning of the div. I am adding .alert-block class as the bootstrap page says:

For longer messages, increase the padding on the top and bottom of the alert wrapper by adding .alert-block.

Mariusz
  • 3,054
  • 2
  • 20
  • 31
2

This solution uses Sass to make it work but you could achieve the same thing with basic css. To make this work with client side validation we cant rely on checking the ModelState since that assumes a postback has occurred. The out-of-the-box mvc client side validation already makes things visible at the right time so let it do its thing and simply style the list items in the validation summary to render like bootstrap alerts.

Razor markup:

@Html.ValidationSummary(false, null, new { @class = "validation-summary-errors-alerts" })

Sass

.validation-summary-errors-alerts{
ul{
    margin: 0;
    list-style: none;
    li{
        @extend .alert;
        @extend .alert-danger;
    }
}}

The css that produced for my project looked like this - yours will be different:

.validation-summary-errors-alerts ul li {
min-height: 10px;
padding: 15px 20px 15px 62px;
position: relative;
border: 1px solid #ca972b;
color: #bb7629;
background-color: #fedc50;
font-family: Arial;
font-size: 13px;
font-weight: bold;
text-shadow: none;}
Daniel Kereama
  • 911
  • 9
  • 17
  • 1
    This doesn't address the close button, however I'm up-voting because this is an awesome way to use the Bootstrap styles without changing the validator markup. The 'close' behavior of the BootStrap alert relies on JavaScript/progressive-enhancement anyway, so it might be more valid to add the button via JavaScript. Using LESS, the same thing can be achieved using the following syntax: `@import (less) "bootstrap.css";` to import the CSS as LESS, and `_.validation-summary-errors { &:extend(.alert); &:extend(.alert-danger); }` to extend the alert classes. – Aaron Newton Oct 29 '16 at 02:00
2

Based on the answers here:

@if (!ViewData.ModelState.IsValid)
{
    <div class="alert alert-danger">
        <button type="button" class="close" data-dismiss="alert">×</button>
        @Html.ValidationSummary(false, "Errors: ")
    </div>
}

(I'm using Bootstrap 4)

Enrico
  • 2,734
  • 1
  • 27
  • 40
1

TwitterBootstrapMVC takes care of this one with just one line:

@Html.Bootstrap().ValidationSummary()

Important, to assure that it behaves the same during the server side and client side (unobtrissive) validation, you need to include a javaScript file that takes care of that.

You can customize your Validation helper with extension methods however you see fit.

Disclaimer: I'm the author of TwitterBootstrapMVC. Using it with Bootstrap 3 requires a license.

Dmitry Efimenko
  • 10,973
  • 7
  • 62
  • 79
1

Alternative solution with pure javascript (jQuery). I'm working with MVC4 + Bootstrap3 but it works perfect for you.

$(function () {
        $(".validation-summary-errors").addClass('alert alert-danger');
        $(".validation-summary-errors").prepend('<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>')
    });

If you don't want to write server side logic then is a nice alternative solution.

snekkke
  • 441
  • 1
  • 5
  • 15
0

Expanding upon Daniel Björk's solution you can include a little script to adjust the CSS included with ValidationSummary() output. The resulting bootstrap alert was showing a rendering issue until I removed the validation-summary-errors class.

@if (ViewData.ModelState.Any(x => x.Value.Errors.Any())) {
   <div class="alert alert-danger">
      <a href="#" class="close" data-dismiss="alert">&times;</a>
      <h4>Validation Errors</h4>
      @Html.ValidationSummary()
   </div>
}

<script>
$(".validation-summary-errors").removeClass("validation-summary-errors");
</script>

You can also easily give a bootstrap highlight to fields with errors. See http://chadkuehn.com/convert-razor-validation-summary-into-bootstrap-alert/

2Yootz
  • 3,971
  • 1
  • 36
  • 31
0

To achieve the same in bootstrap 4, use the following:

 @if (ViewData.ModelState[""] != null && ViewData.ModelState[""].Errors.Count() > 0)
        {
            <div class="col-auto alert alert-danger" role="alert">
                @Html.ValidationSummary(true)
            </div>
        }
Jason Loki Smith
  • 428
  • 3
  • 12
0

If it needs to work with clientside javascript I suggests doing this:

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

You still can assign the bootstrap class

@Html.ValidationSummary(null, new {@class= "alert alert-danger" })

but it will only show when you have actual errors.