Korzystanie z Ajax.BeginForm z ASP.NET MVC 3 Razor

264

Czy istnieje samouczek lub przykład użycia Ajax.BeginFormw Asp.net MVC 3, gdzie istnieją dyskretne sprawdzanie poprawności i Ajax?

To nieuchwytny temat dla MVC 3 i wydaje mi się, że mój formularz nie działa poprawnie. Dokonuje przesłania Ajax, ale ignoruje błędy sprawdzania poprawności.

JBeckton
źródło

Odpowiedzi:

427

Przykład:

Model:

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

Kontroler:

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

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

Widok:

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

a oto lepszy (z mojej perspektywy) przykład:

Widok:

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

które można dodatkowo ulepszyć za pomocą wtyczki jQuery .

Darin Dimitrov
źródło
41
Zgadzam się na użycie jQUery dla Ajax. Myślę, że zdecydowana większość aplikacji Asp.net MVC Ajax raczej używa jQuery niż wbudowanych rozszerzeń Ajax.
Robert Koritnik
6
Używam czegoś takiego, a wynik wydaje się iść na własną stronę, a nie tylko zastępować wynik div. Wiesz dlaczego?
David
3
Tak, zgadzam się również na używanie czystego jQuery dla ajax, używanie rozszerzenia MVC ajax oznacza, że ​​musisz niepotrzebnie uczyć się innych reguł i składni, aby w końcu użyć jQuery. Więc nawet muszę pisać więcej, ale lepiej zrobić to we właściwy sposób, a także uzyskać większą kontrolę i elastyczność.
Nestor
3
@ darin-dimitrov: kiedy wypróbuję twój ostatni przykład, muszę dodać dane: $ ('form'). serialize (), do wywołania ajax (). W przeciwnym razie dane formularza nie są przekazywane, a mój model jest nieprawidłowy po stronie serwera. Zastanawiam się, czy coś przeoczyłem?
Brett
2
@DarinDimitrov co zrobić, jeśli wystąpił błąd z BLL i musisz odesłać model z powrotem do widoku i wyświetlić komunikat o błędzie, ponieważ warstwa utwardzona zapewniła głębszą weryfikację danych i znalazła problem. Samo sprawdzanie poprawności po stronie klienta nie wystarczy. Nie możesz zwrócić Widok (model); teraz, ponieważ cały widok jest renderowany w wyniku div ... co to jest za obejście?
CD Smith
54

Myślę, że wszystkie odpowiedzi pominęły kluczowy punkt:

Jeśli używasz formularza Ajax, aby musiał się zaktualizować (a NIE inny div poza formularzem), musisz umieścić div zawierający NA ZEWNĄTRZ formularza. Na przykład:

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

W przeciwnym razie skończysz jak @David, gdzie wynik jest wyświetlany na nowej stronie.

Dror
źródło
7
Problem Davida prawie zawsze jest spowodowany brakiem pakietu jqueryval, który zawiera dyskretny kod ajax. Bądź ostrożny z tym podejściem, które opublikowałeś, w przeciwnym razie otrzymasz jeden post, a następnie formularz zostanie ukryty, ponieważ właśnie go zastąpiłeś. Następnie potrzebujesz widoku „MyAction” do zarządzania jego formą i ponownie określ w nim wszystkie opcje ajax.
Adam Tuliper - MSFT
W mojej aplikacji ukierunkowanej div pokazującej cały formularz ze stroną wzorcową proszę o pomoc
Nitin ...
Dla mnie UnobtrusiveJavaScriptEnablednigdzie się nie ustawiłem
Kunal
15

W końcu udało mi się uruchomić rozwiązanie Darina, ale najpierw popełniłem kilka błędów, co spowodowało problem podobny do Davida (w komentarzach poniżej rozwiązania Darina), gdzie wynik był publikowany na nowej stronie.

Ponieważ po zwróceniu metody musiałem coś zrobić z formularzem, zapisałem go do późniejszego użycia:

var form = $(this);

Jednak ta zmienna nie miała właściwości „action” ani „method”, które są używane w wywołaniu 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();
});

Zamiast tego musisz użyć zmiennej „this”:

$.ajax({
    url: this.action, 
    type: this.method,
    data: $(this).serialize(),
    success: function (html) {
        // Do something with the returned html.
    }
});
Jason
źródło
5
Dzieje się tak, ponieważ zmienna formy, którą ustawiłeś, jest jQueryobiektem z formą jako selektorem. form[0]miałby właściwości. Dobrą praktyką jest także prefiksowanie dowolnych jQueryzmiennych w $celu łatwiejszego ich identyfikowania.
James South
6

Rozwiązanie Darina Dimitrowa działało dla mnie z jednym wyjątkiem. Kiedy przesłałem widok częściowy z (celowymi) błędami weryfikacji, w oknie dialogowym zwrócono duplikaty formularzy:

wprowadź opis zdjęcia tutaj

Aby to naprawić musiałem zawinąć Html.BeginForm w div:

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

Po przesłaniu formularza wyczyściłem div w funkcji powodzenia i wyprowadziłem zweryfikowany formularz:

    $('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
źródło
Też dostaję ten sam błąd. Używam Partial Viewsdo renderowania funkcji tworzenia poniżej strony indeksu. Mogę uzyskać wszystkie komunikaty sprawdzania poprawności w częściowym widoku. Ale gdy się Createpowiedzie, indeks jest wyświetlany dwukrotnie. Nie mam Html.BeginFormw widoku indeksu.
Vini,
Spróbuj użyć UpdateTargetId = "myForm"zamiast tego
Kunal
4

Jeśli nie sprawdzono sprawdzania poprawności danych lub treść jest zawsze zwracana w nowym oknie, upewnij się, że te 3 wiersze znajdują się u góry widoku:

<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
źródło
Nie znalazłem ich w rozwiązaniu. Musiałem zainstalować je z menedżera pakietów
Nuget
3

Przykład

// W modelu

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

// W 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>

W widoku 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>
}

W kontrolerze

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

musisz przekazać ViewName i Model do metody RenderPartialViewToString. zwróci ci widok z zatwierdzeniem, które zostały zastosowane w modelu i dołączą treść do div „targetId” w Index.cshtml. W ten sposób, przechwytując RenderHtml częściowego widoku, możesz zastosować walidację.

Shivkumar
źródło
3

Formularze Ajax działają asynchronicznie przy użyciu Javascript. Konieczne jest więc załadowanie plików skryptów do wykonania. Mimo że jest to niewielki kompromis w zakresie wydajności, wykonanie odbywa się bez postback.

Musimy zrozumieć różnicę między zachowaniem formularzy HTML i Ajax.

Ajax:

  1. Nie przekieruje formularza, nawet jeśli wykonasz funkcję RedirectAction ().

  2. Wykona asynchronicznie operacje zapisywania, aktualizacji i wszelkich modyfikacji.

HTML:

  1. Przekieruje formularz.

  2. Wykonuje operacje zarówno synchronicznie, jak i asynchronicznie (z dodatkowym kodem i ostrożnością).

Wykazano różnice za pomocą POC w poniższym linku. Połączyć

użytkownik1080810
źródło
1

Przed dodaniem Ajax.BeginForm. Dodaj poniższe skrypty do swojego projektu w podanej kolejności,

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

Tylko te dwa są wystarczające do wykonania operacji Ajax.

Balaji Dinakaran
źródło