Verwenden von Ajax.BeginForm mit ASP.NET MVC 3 Razor

264

Gibt es ein Tutorial oder ein Codebeispiel für die Verwendung Ajax.BeginFormin Asp.net MVC 3, in dem unauffällige Validierung und Ajax vorhanden sind?

Dies ist ein schwer fassbares Thema für MVC 3, und ich kann mein Formular anscheinend nicht richtig zum Laufen bringen. Es wird eine Ajax-Übermittlung durchgeführt, die Validierungsfehler werden jedoch ignoriert.

JBeckton
quelle

Antworten:

427

Beispiel:

Modell:

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

Regler:

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

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

Aussicht:

@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" />
}

und hier ist ein besseres (aus meiner Sicht) Beispiel:

Aussicht:

@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;
    });
});

Dies kann mit dem jQuery-Formular-Plugin weiter verbessert werden .

Darin Dimitrov
quelle
41
Ich bin damit einverstanden, jQUery für Ajax zu verwenden. Ich denke, dass die überwiegende Mehrheit der Asp.net MVC Ajax-Anwendungen eher jQuery als die integrierten Ajax-Erweiterungen verwendet.
Robert Koritnik
6
Ich verwende so etwas wie das Folgende und das Ergebnis scheint auf eine eigene Seite zu gehen und nicht nur ein div-Ergebnis zu ersetzen. Weißt du, warum?
David
3
Ja, ich stimme auch der Verwendung von reinem jQuery für Ajax zu. Die Verwendung der MVC-Ajax-Erweiterung bedeutet, dass Sie unnötig andere Regeln und Syntax erlernen müssen, um letztendlich jQuery zu verwenden. Selbst ich muss mehr schreiben, aber es ist besser, es richtig zu machen, und Sie erhalten mehr Kontrolle und Flexibilität.
Nestor
3
@ darin-dimitrov: Wenn ich Ihr letztes Beispiel versuche, muss ich dem Aufruf von ajax () folgende Daten hinzufügen: $ ('form'). serialize (). Andernfalls werden keine Formulardaten übergeben und mein Modell ist auf der Serverseite ungültig. Frage mich, ob ich etwas übersehen habe?
Brett
2
@DarinDimitrov Was passiert, wenn ein Fehler mit der BLL vorliegt und Sie das Modell an die Ansicht zurücksenden und die Fehlermeldung anzeigen müssen, da die gehärtete Schicht eine tiefere Validierung der Daten ermöglicht und ein Problem festgestellt hat. Es reicht nicht aus, sich nur auf die clientseitige Validierung zu verlassen. Sie können View (Modell) nicht zurückgeben. jetzt, weil die gesamte Ansicht im Ergebnis div gerendert wird ... was ist die Problemumgehung dafür?
CD Smith
54

Ich denke, dass alle Antworten einen entscheidenden Punkt verfehlt haben:

Wenn Sie das Ajax-Formular verwenden, damit es sich selbst aktualisieren muss (und NICHT ein anderes Div außerhalb des Formulars), müssen Sie das enthaltene Div AUSSERHALB des Formulars platzieren. Zum Beispiel:

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

Andernfalls werden Sie wie @David enden, wo das Ergebnis auf einer neuen Seite angezeigt wird.

Dror
quelle
7
Davids Problem wird fast immer dadurch verursacht, dass das jqueryval-Bundle, das den unauffälligen Ajax-Code enthält, nicht enthalten ist. Seien Sie sehr vorsichtig mit diesem Ansatz, den Sie veröffentlicht haben, da Sie sonst einen Beitrag erhalten und Ihr Formular abgespritzt wird, da Sie es gerade ersetzt haben. Anschließend benötigen Sie die Ansicht Ihrer "MyAction", um das Formular zu verwalten und alle darin enthaltenen Ajax-Optionen erneut anzugeben.
Adam Tuliper - MSFT
In meiner Anwendung zielgerichtete div zeigt ganze Form mit Masterseite bitte helfen Sie mir
Nitin ...
Für mich hatte ich UnobtrusiveJavaScriptEnablednirgendwo wahr gesetzt
Kunal
15

Ich habe Darins Lösung irgendwann zum Laufen gebracht, aber zuerst ein paar Fehler gemacht, die zu einem ähnlichen Problem wie David (in den Kommentaren unter Darins Lösung) führten, bei dem das Ergebnis auf einer neuen Seite veröffentlicht wurde.

Da ich nach der Rückgabe der Methode etwas mit dem Formular tun musste, habe ich es zur späteren Verwendung gespeichert:

var form = $(this);

Diese Variable hatte jedoch nicht die Eigenschaften "action" oder "method", die im Ajax-Aufruf verwendet werden.

$(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();
});

Stattdessen müssen Sie die Variable "this" verwenden:

$.ajax({
    url: this.action, 
    type: this.method,
    data: $(this).serialize(),
    success: function (html) {
        // Do something with the returned html.
    }
});
Jason
quelle
5
Das liegt daran, dass die Formularvariable, die Sie festgelegt haben, das jQueryObjekt mit dem Formular als Selektor ist. form[0]hätte die Eigenschaften. Es wird auch empfohlen, jQueryVariablen ein Präfix $voranzustellen, um sie leichter identifizieren zu können.
James South
6

Die Lösung von Darin Dimitrov hat mit einer Ausnahme für mich funktioniert. Als ich die Teilansicht mit (absichtlichen) Validierungsfehlern übermittelte, wurden im Dialogfeld doppelte Formulare zurückgegeben:

Geben Sie hier die Bildbeschreibung ein

Um dies zu beheben, musste ich das Html.BeginForm in ein div einschließen:

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

Als das Formular gesendet wurde, habe ich das div in der Erfolgsfunktion gelöscht und das validierte Formular ausgegeben:

    $('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;
    });
});
steveareeno
quelle
Ich bekomme auch den gleichen Fehler. Ich verwende Partial Views, um die Erstellungsfunktion unter der Indexseite zu rendern. Ich kann alle Validierungsnachrichten in der Teilansicht erhalten. Wenn dies Createjedoch erfolgreich ist, wird der Index zweimal angezeigt. Ich habe keine Html.BeginFormin meiner Indexansicht.
Vini
Versuchen Sie UpdateTargetId = "myForm"stattdessen
Kunal
4

Wenn keine Datenüberprüfung durchgeführt wurde oder der Inhalt immer in einem neuen Fenster zurückgegeben wird, stellen Sie sicher, dass sich diese drei Zeilen oben in der Ansicht befinden:

<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>
Cheny
quelle
Ich habe sie nicht in Lösung gefunden. Ich musste sie vom Nuget-Paketmanager installieren
FindOut_Quran
3

Beispiel

// Im Modell

public class MyModel
{  
   [Required]
    public string Name{ get; set; }
}

// In PartailView //PartailView.cshtml

@model MyModel

<div>
    <div>
      @Html.LabelFor(model=>model.Name)
    </div>
    <div>
        @Html.EditorFor(model=>model.Name)
        @Html.ValidationMessageFor(model => model.Name)
    </div>
</div>

In der Ansicht Index.cshtml

@model MyModel
<div id="targetId">
    @{Html.RenderPartial("PartialView",Model)}
</div>

@using(Ajax.BeginForm("AddName", new AjaxOptions { UpdateTargetId = "targetId", HttpMethod = "Post" }))
{
     <div>
        <input type="submit" value="Add Unit" />
    </div>
}

Im Controller

public ActionResult Index()
{
  return View(new MyModel());
}


public string AddName(MyModel model)
{
   string HtmlString = RenderPartialViewToString("PartailView",model);
   return HtmlString;
}


protected string RenderPartialViewToString(string viewName, object model)
        {
            if (string.IsNullOrEmpty(viewName))
                viewName = ControllerContext.RouteData.GetRequiredString("action");

            ViewData.Model = model;

            using (StringWriter sw = new StringWriter())
            {
                ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
                ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
                viewResult.View.Render(viewContext, sw);
                return sw.GetStringBuilder().ToString();
            }
        }

Sie müssen ViewName und Model an die RenderPartialViewToString-Methode übergeben. Es gibt Ihnen die Ansicht mit Validierung zurück, die Sie im Modell angewendet haben, und hängt den Inhalt in "targetId" div in Index.cshtml an. Auf diese Weise können Sie die Validierung anwenden, indem Sie RenderHtml der Teilansicht abfangen.

Shivkumar
quelle
3

Ajax-Formulare arbeiten asynchron mit Javascript. Daher ist es erforderlich, die Skriptdateien zur Ausführung zu laden. Obwohl es sich um einen kleinen Leistungskompromiss handelt, erfolgt die Ausführung ohne Postback.

Wir müssen den Unterschied zwischen dem Verhalten von HTML- und Ajax-Formularen verstehen.

Ajax:

  1. Das Formular wird nicht umgeleitet, auch wenn Sie eine RedirectAction () ausführen.

  2. Führt Speicher-, Aktualisierungs- und Änderungsvorgänge asynchron aus.

Html:

  1. Leitet das Formular um.

  2. Führt Operationen sowohl synchron als auch asynchron aus (mit etwas zusätzlichem Code und Sorgfalt).

Demonstrierte die Unterschiede mit einem POC im folgenden Link. Verknüpfung

user1080810
quelle
1

Vor dem Hinzufügen der Ajax.BeginForm. Fügen Sie Ihrem Projekt die folgenden Skripte in der angegebenen Reihenfolge hinzu:

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

Nur diese beiden reichen aus, um eine Ajax-Operation durchzuführen.

Balaji Dinakaran
quelle