How to display domain validations and errors in a partial view modal bootstrap?

1

I'm using DDD and I have some validations in my domain that need to be done, however when I use ModelState.AddModelError and return my model and my PartialView, the form of my Partial does not remain in modal open. Instead, it displays an html page without css styles. I know I have to do with Javascript / Ajax / jQuery and return a Json on the Controller. But I still have not gotten it right. Any effective way to do it?

I put the codes to make it easier to see something that is wrong. Basically what I want is to return the errors that happen in the controller to be displayed inside the PartialView loaded in bootstrap modal.

Controller code

public ActionResult Create()
        {
            ViewBag.Title = "Adicionar Ação de Formulário";
            return PartialView("~/Views/Acao/_AcaoFormulario.cshtml", _acaoAppService.Iniciar());
        }

        [HttpPost]
        public JsonResult Create(AcaoViewModel acaoViewModel)
        {
            JsonResult result;

            var errorResult = new List<ValidationError>();

            if (ModelState.IsValid)
            {
                var acaoReturn = _acaoAppService.Salvar(acaoViewModel, acaoViewModel.AcaoId);

                if (!acaoReturn.ValidationResult.IsValid)
                {

                    foreach (var error in acaoReturn.ValidationResult.Erros)
                    {
                        errorResult.Add(new ValidationError(error.Message));
                    }

                    return result = Json(new ActionResponse(false, errorResult), JsonRequestBehavior.AllowGet);
                }

                return result = Json(new ActionResponse(true, null), JsonRequestBehavior.AllowGet);
            }

            errorResult.Add(new ValidationError("Ação Inválida"));

            return result = Json(new ActionResponse(false, errorResult));
        }

PartialView with Modal Loaded Form

@model PAD.Application.ViewModels.AcaoViewModel

@{
    Layout = null;
}

<div class="modal-dialog modal-lg">
    <div class="modal-content">
        @using (Html.BeginForm(null, null, FormMethod.Post, new { id = "acaoFrm", onsubmit = "acaoSubmit()" }))
        {
            <div class="card-header">
                <button class="close" type="button" data-dismiss="modal">
                    <span class="sr-only">Close</span>
                    <span aria-hidden="true">x</span>
                </button>
                <h4 class="card-title">@ViewBag.Title</h4>
            </div>
            <div class="modal-body">
                <div class="card-block">

                    @Html.AntiForgeryToken()
                    @Html.HiddenFor(model => model.AcaoId)

                    <div class="text-danger">
                        <ul></ul>
                    </div>

                    <div class="form-body">
                        <div class="row">
                            <div class="form-group col-md-4">
                                @Html.LabelFor(model => model.Nome)
                                @Html.TextBoxFor(model => model.Nome, htmlAttributes: new { @class = "form-control" })
                            </div>
                            <div class="form-group col-md-4">
                                @Html.LabelFor(model => model.Tipo, htmlAttributes: new { @for = "tipo" })
                                @*@Html.TextBoxFor(model => model.Tipo, htmlAttributes: new { @class = "form-control" })*@
                                <select class="form-control" id="tipo" name="tipo">
                                    <option>-- Selecionar --</option>
                                    <option value="A">Ação BD</option>
                                    <option value="C">Consulta BD</option>
                                </select>
                            </div>
                            <div class="form-group col-md-4">
                                @Html.LabelFor(model => model.FonteDadosId)
                                @Html.DropDownListFor(model => model.FonteDadosId, Model.ComboFonteDados, "-- Selecionar --", new { @class = "form-control" })
                            </div>
                        </div>
                        <div class="row">
                            <div class="form-group col-md-4">
                                @Html.LabelFor(model => model.Take)
                                @Html.TextBoxFor(model => model.Take, htmlAttributes: new { @class = "form-control" })
                            </div>
                            <div class="form-group col-md-4">
                                @Html.LabelFor(model => model.Execucao, htmlAttributes: new { @for = "execucao" })
                                @*@Html.TextBoxFor(model => model.Execucao, htmlAttributes: new { @class = "form-control" })*@
                                <select class="form-control" id="execucao" name="execucao">
                                    <option>-- Selecionar --</option>
                                    <option value="E">Excluir</option>
                                    <option value="X">Executar</option>
                                    <option value="S">Salvar</option>
                                </select>
                            </div>
                            <div class="form-group col-md-4">
                                @Html.LabelFor(model => model.RotinaId)
                                @Html.DropDownListFor(model => model.RotinaId, Model.ComboRotinas, "-- Selecionar -- ", new { @class = "form-control" })
                            </div>
                        </div>
                        <div class="row">
                            <div class="form-group col-md-6">
                                @Html.LabelFor(model => model.Descricao)
                                @Html.TextBoxFor(model => model.Descricao, htmlAttributes: new { @class = "form-control" })
                            </div>
                            <div class="form-group col-md-6">
                                @Html.LabelFor(model => model.PopUpContainer)
                                @Html.TextBoxFor(model => model.PopUpContainer, htmlAttributes: new { @class = "form-control" })
                            </div>
                        </div>
                        <div class="row">
                            <div class="form-group col-md-6">
                                @Html.LabelFor(model => model.Where)
                                @Html.TextAreaFor(model => model.Where, htmlAttributes: new { @class = "form-control", @rows = "10" })
                            </div>
                            <div class="form-group col-md-6">
                                @Html.LabelFor(model => model.OrderBy)
                                @Html.TextAreaFor(model => model.OrderBy, htmlAttributes: new { @class = "form-control", @rows = "10" })
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="card-footer">
                <button class="btn btn-danger shadow" type="button" data-dismiss="modal">
                    <span class="icon-remove"></span> Fechar
                </button>
                <button type="submit" class="btn btn-success shadow pull-right" onclick="document.getElementById('acaoFrm').submit();">
                    <span class="icon-check"></span> Salvar
                </button>
            </div>
        }
    </div>
</div>

Javascript calling modal

$("#novaAcao").click(function () {
        $("#modal").load("/acao/create", function () {
            $("#modal").modal("show");
        });
    });
    
asked by anonymous 03.10.2017 / 07:50

1 answer

1

Well, let's break it down:

  • If your action is HttpPost, you do not need the "JsonRequestBehavior.AllowGet" excerpt (although there is no error);
  • Your form already has the associated "onsubmit" event. So, when clicking on the submit button this event will be triggered automatically, without needing this excerpt: onclick="document.getElementById ('acaoFrm'). Submit ();
  • In your "actionSubmit ()" call your HttpPost action via Ajax. In the "done ()" event of the Ajax call, do something like:
  • .done(function(result){
      if(result.data != null && !result.data.sucesso){ //sucesso: primeiro parâmetro de ActionResponse
        var erros = result.data.errorList; //errorList: segundo parâmetro de ActionResponse
        $.each(erros, function(key, value ) {
          $("#divErros").append("<p>" + value + "</p>"); //crie uma divErros em sua modal.
        });
      }
    });
  • Your code gets even better and more readable by setting the Response.StatusCode in your HttpPost action in case of error (eg 400, 500) or success (eg 200). In this case it would also have to change its handling of the callback Ajax. Here's an example: link
  • 04.10.2017 / 04:53