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

Asked

Viewed 244 times

1

I am using DDD and have some validations in my domain that need to be done, but when I use Modelstate.Addmodelerror and return my model and my Partialview, the form of my Partial does not remain in the open modal. Instead, it displays an html page with no css styles. I know I have to do it with Javascript/Ajax/jQuery and return a Json in the Controller. But I haven’t quite made it work yet. Some effective way to do?

I put the codes in to make it easier to visualize something that’s wrong. Basically what I want is to return the errors that occur in the controller to be displayed inside the Partialview loaded in the modal bootstrap.

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 Form Loaded in Modal

@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 the modal

$("#novaAcao").click(function () {
        $("#modal").load("/acao/create", function () {
            $("#modal").modal("show");
        });
    });
  • Edit the question and enter the code you already made.

1 answer

0


Well, let’s go in pieces:

  1. If your action is Httppost, you do not need the "Jsonrequestbehavior.Allowget" snippet (although there is no error);
  2. Your form already has the associated "onsubmit" event. Then, by clicking on the Submit button this event will be triggered automatically, without this excerpt: onclick="Document.getElementById('acaoFrm'). Submit();
  3. In your "acaoSubmit()" function 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.
    });
  }
});

  1. Your code gets even better and more readable by defining Response.Statuscode in your Httppost action in case of error (e.g., 400, 500) or success (e.g., 200). In this case you would also have to change your treatment of the return of the call Ajax. Here is an example: https://stackoverflow.com/questions/12112361/how-to-set-http-status-code-from-asp-net-mvc-3
  • Thanks so much! That’s exactly what I was looking for. And thank you so much for the tips.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.