asp.net-mvc ejemplos - Usando Ajax.BeginForm con ASP.NET MVC 3 Razor




properties control (8)

¿Existe un tutorial o ejemplo de código sobre el uso de Ajax.BeginForm dentro de Asp.net MVC 3 donde existe una validación discreta y Ajax?

Este es un tema difícil de alcanzar para MVC 3, y parece que no consigo que mi formulario funcione correctamente. Hará un envío Ajax pero ignora los errores de validación.


Answers

Creo que todas las respuestas pasaron por alto un punto crucial:

Si usa el formulario Ajax para que necesite actualizarse (y NO otro div fuera del formulario), debe colocar el div contenido FUERA del formulario. Por ejemplo:

 <div id="target">
 @using (Ajax.BeginForm("MyAction", "MyController",
            new AjaxOptions
            {
                HttpMethod = "POST",
                InsertionMode = InsertionMode.Replace,
                UpdateTargetId = "target"
            }))
 {
      <!-- whatever -->
 }
 </div>

De lo contrario, terminará como @David, donde se mostrará el resultado en una nueva página.


Los formularios Ajax funcionan de forma asíncrona utilizando Javascript. Por lo que es necesario, para cargar los archivos de script para su ejecución. Aunque es un pequeño compromiso de rendimiento, la ejecución se realiza sin devolución de datos.

Necesitamos entender la diferencia entre los comportamientos de los formularios Html y Ajax.

Ajax:

  1. No redireccionará el formulario, incluso si realiza una RedirectAction ().

  2. Realizará operaciones de guardado, actualización y cualquier modificación de forma asíncrona.

HTML:

  1. Se redirigirá el formulario.

  2. Realizará operaciones de forma síncrona y asíncrona (con un código y cuidado adicionales).

Demostró las diferencias con un POC en el siguiente enlace. Link


Si no se realizó ninguna validación de datos, o si el contenido siempre se devuelve en una nueva ventana, asegúrese de que estas 3 líneas estén en la parte superior de la vista:

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>

Ejemplo:

Modelo:

public class MyViewModel
{
    [Required]
    public string Foo { get; set; }
}

Controlador:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return Content("Thanks", "text/html");
    }
}

Ver:

@model AppName.Models.MyViewModel

<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

<div id="result"></div>

@using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "result" }))
{
    @Html.EditorFor(x => x.Foo)
    @Html.ValidationMessageFor(x => x.Foo)
    <input type="submit" value="OK" />
}

y aquí hay un mejor ejemplo (en mi perspectiva):

Ver:

@model AppName.Models.MyViewModel

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/index.js")" type="text/javascript"></script>

<div id="result"></div>

@using (Html.BeginForm())
{
    @Html.EditorFor(x => x.Foo)
    @Html.ValidationMessageFor(x => x.Foo)
    <input type="submit" value="OK" />
}

index.js :

$(function () {
    $('form').submit(function () {
        if ($(this).valid()) {
            $.ajax({
                url: this.action,
                type: this.method,
                data: $(this).serialize(),
                success: function (result) {
                    $('#result').html(result);
                }
            });
        }
        return false;
    });
});

que se puede mejorar aún más con el complemento de formulario jQuery .


Antes de agregar el Ajax.BeginForm. Agregue los siguientes scripts a su proyecto en el orden mencionado,

  1. jquery-1.7.1.min.js
  2. jquery.unobtrusive-ajax.min.js

Solo estos dos son suficientes para realizar la operación Ajax.


Logré que la solución de Darin funcionara eventualmente, pero primero cometí algunos errores, lo que resultó en un problema similar a David (en los comentarios debajo de la solución de Darin) donde el resultado se estaba publicando en una nueva página.

Como tuve que hacer algo con el formulario después de que se devolviera el método, lo almacené para su uso posterior:

var form = $(this);

Sin embargo, esta variable no tenía las propiedades de "acción" o "método" que se utilizan en la llamada ajax.

$(document).on("submit", "form", function (event) {
    var form = $(this);

    if (form.valid()) {
        $.ajax({
            url: form.action, // Not available to 'form' variable
            type: form.method,  // Not available to 'form' variable
            data: form.serialize(),
            success: function (html) {
                // Do something with the returned html.
            }
        });
    }

    event.preventDefault();
});

En su lugar necesitas usar la variable "this":

$.ajax({
    url: this.action, 
    type: this.method,
    data: $(this).serialize(),
    success: function (html) {
        // Do something with the returned html.
    }
});

La solución de Darin Dimitrov funcionó para mí con una excepción. Cuando envié la vista parcial con errores de validación (intencionales), terminé con los formularios duplicados que se devolvían en el cuadro de diálogo:

Para solucionar esto tuve que envolver el Html.BeginForm en un div:

<div id="myForm">
    @using (Html.BeginForm("CreateDialog", "SupportClass1", FormMethod.Post, new { @class = "form-horizontal" }))
    {
        //form contents
    }
</div>

Cuando se envió el formulario, borré el div en la función de éxito y realicé el formulario validado:

    $('form').submit(function () {
        if ($(this).valid()) {
            $.ajax({
                url: this.action,
                type: this.method,
                data: $(this).serialize(),
                success: function (result) {
                    $('#myForm').html('');
                    $('#result').html(result);
                }
            });
        }
        return false;
    });
});

Aquí hay una solución bastante simple:

En el controlador devolvemos nuestros errores de esta manera:

if (!ModelState.IsValid)
        {
            return Json(new { success = false, errors = ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage).ToList() }, JsonRequestBehavior.AllowGet);
        }

Aquí hay algunos de los guiones del cliente:

function displayValidationErrors(errors)
{
    var $ul = $('div.validation-summary-valid.text-danger > ul');

    $ul.empty();
    $.each(errors, function (idx, errorMessage) {
        $ul.append('<li>' + errorMessage + '</li>');
    });
}

Así es como lo manejamos a través de ajax:

$.ajax({
    cache: false,
    async: true,
    type: "POST",
    url: form.attr('action'),
    data: form.serialize(),
    success: function (data) {
        var isSuccessful = (data['success']);

        if (isSuccessful) {
            $('#partial-container-steps').html(data['view']);
            initializePage();
        }
        else {
            var errors = data['errors'];

            displayValidationErrors(errors);
        }
    }
});

Además, renderizo vistas parciales a través de ajax de la siguiente manera:

var view = this.RenderRazorViewToString(partialUrl, viewModel);
        return Json(new { success = true, view }, JsonRequestBehavior.AllowGet);

Método RenderRazorViewToString:

public string RenderRazorViewToString(string viewName, object model)
    {
        ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext,
                                                                     viewName);
            var viewContext = new ViewContext(ControllerContext, viewResult.View,
                                         ViewData, TempData, sw);
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
            return sw.GetStringBuilder().ToString();
        }
    }




asp.net-mvc asp.net-mvc-3