Sử dụng Ajax.BeginForm với ASP.NET MVC 3 Razor


264

Có hướng dẫn hoặc ví dụ mã nào về việc sử dụng Ajax.BeginFormtrong Asp.net MVC 3 khi xác thực và Ajax không tồn tại?

Đây là một chủ đề khó nắm bắt cho MVC 3 và dường như tôi không thể để biểu mẫu của mình hoạt động bình thường. Nó sẽ thực hiện đệ trình Ajax nhưng bỏ qua các lỗi xác thực.

Câu trả lời:


427

Thí dụ:

Mô hình:

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

Điều khiển:

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

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

Lượt xem:

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

và đây là một ví dụ tốt hơn (theo quan điểm của tôi):

Lượt xem:

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

có thể được tăng cường hơn nữa với plugin dạng jQuery .


41
Tôi đồng ý về việc sử dụng JQUery cho Ajax. Tôi nghĩ rằng phần lớn các ứng dụng Asp.net MVC Ajax sử dụng jQuery hơn là các phần mở rộng Ajax tích hợp.
Robert Koritnik

6
Tôi đang sử dụng một cái gì đó như sau và kết quả dường như sẽ đi đến trang riêng của nó và không chỉ thay thế một kết quả div. Bạn có biết tại sao?
David

3
Có, tôi cũng đồng ý trong việc sử dụng jQuery thuần cho ajax, sử dụng phần mở rộng MVC ajax có nghĩa là bạn cần phải học các quy tắc và cú pháp khác để cuối cùng sử dụng jQuery. Vì vậy, ngay cả tôi cần phải viết nhiều hơn, nhưng tốt hơn là làm đúng cách, cộng với bạn có nhiều quyền kiểm soát và linh hoạt hơn.
Nestor

3
@ darin-dimitrov: khi tôi thử ví dụ sau của bạn, tôi phải thêm dữ liệu: $ ('form'). serialize (), vào lệnh gọi ajax (). Mặt khác, không có dữ liệu biểu mẫu nào được thông qua và mô hình của tôi không hợp lệ ở phía máy chủ. Tự hỏi nếu có một cái gì đó tôi đã bỏ qua?
Brett

2
@DarinDimitrov nếu có lỗi với BLL và bạn cần gửi mô hình trở lại Chế độ xem và hiển thị thông báo lỗi vì lớp cứng đã cung cấp xác thực sâu hơn cho dữ liệu và tìm thấy sự cố. Chỉ dựa vào xác nhận phía khách hàng là không đủ. Bạn không thể trả về View (model); bây giờ vì toàn bộ khung nhìn được hiển thị trong div kết quả ... cách giải quyết cho điều đó là gì?
CD Smith

54

Tôi nghĩ rằng tất cả các câu trả lời đã bỏ lỡ một điểm quan trọng:

Nếu bạn sử dụng biểu mẫu Ajax để nó cần tự cập nhật (và KHÔNG phải là một div khác ngoài biểu mẫu) thì bạn cần đặt div BÊN NGOÀI của biểu mẫu. Ví dụ:

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

Nếu không, bạn sẽ kết thúc như @David nơi kết quả được hiển thị trong một trang mới.


7
Vấn đề của David hầu như luôn luôn được gây ra từ việc không bao gồm gói jqueryval có chứa mã ajax không phô trương. Hãy cẩn thận với cách tiếp cận này mà bạn đã đăng nếu không bạn sẽ nhận được một bài đăng và sau đó biểu mẫu của bạn sẽ bị xóa vì bạn vừa thay thế nó. Sau đó, bạn yêu cầu chế độ xem "MyAction" của mình để quản lý biểu mẫu của nó và chỉ định lại tất cả các tùy chọn ajax trong đó.
Adam Tuliper - MSFT

Trong ứng dụng của tôi, mục tiêu div hiển thị toàn bộ biểu mẫu với trang chính, vui lòng giúp tôi
Nitin ...

Đối với tôi, tôi đã không đặt UnobtrusiveJavaScriptEnabledthành sự thật ở bất cứ đâu
Kunal

15

Cuối cùng tôi đã có giải pháp của Darin nhưng đã mắc một vài lỗi trước tiên dẫn đến một vấn đề tương tự như David (trong các bình luận bên dưới giải pháp của Darin) khi kết quả được đăng lên một trang mới.

Vì tôi phải làm một cái gì đó với biểu mẫu sau khi phương thức được trả về, tôi đã lưu nó để sử dụng sau:

var form = $(this);

Tuy nhiên, biến này không có thuộc tính "hành động" hoặc "phương thức" được sử dụng trong lệnh gọi 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();
});

Thay vào đó, bạn cần sử dụng biến "này":

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

5
Đó là bởi vì biến biểu mẫu bạn đã đặt jQueryđối tượng với biểu mẫu làm bộ chọn. form[0]sẽ có các tính chất. Đó cũng là một thực hành tốt để tiền tố bất kỳ jQuerybiến nào $để dễ dàng xác định chúng hơn.
James South

6

Giải pháp của Darin Dimitrov làm việc cho tôi với một ngoại lệ. Khi tôi gửi chế độ xem một phần với lỗi xác thực (cố ý), tôi đã kết thúc với các biểu mẫu trùng lặp được trả về trong hộp thoại:

nhập mô tả hình ảnh ở đây

Để khắc phục điều này, tôi đã phải bọc Html.BeginForm trong một div:

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

Khi biểu mẫu được gửi, tôi đã xóa div trong hàm thành công và xuất ra biểu mẫu được xác thực:

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

Tôi cũng nhận được cùng một lỗi. Tôi đang sử dụng Partial Viewsđể kết xuất chức năng tạo bên dưới trang chỉ mục. Tôi có thể nhận được tất cả các thông báo xác thực trong Chế độ xem một phần. Nhưng khi Createthành công, chỉ số được hiển thị hai lần. Tôi không có Html.BeginFormtrong Chế độ xem Chỉ mục của mình.
Vini

UpdateTargetId = "myForm"Thay vào đó hãy thử sử dụng
Kunal

4

Nếu không có xác thực dữ liệu nào bị loại bỏ hoặc nội dung luôn được trả về trong một cửa sổ mới, hãy đảm bảo 3 dòng này nằm ở đầu chế độ xem:

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

Tôi đã không tìm thấy chúng trong giải pháp. Tôi đã phải cài đặt chúng từ trình quản lý gói
Nuget

3

Thí dụ

// Trong mô hình

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

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

Trong chế độ xem 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>
}

Trong bộ điều khiển

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

bạn phải truyền ViewName và Model cho phương thức RenderPartialViewToString. nó sẽ trả về cho bạn chế độ xem với xác thực mà bạn đã áp dụng trong mô hình và nối thêm nội dung trong div "targetId" trong Index.cshtml. Tôi theo cách này bằng cách bắt RenderHtml của chế độ xem một phần, bạn có thể áp dụng xác thực.


3

Các biểu mẫu Ajax hoạt động không đồng bộ bằng Javascript. Vì vậy, nó là bắt buộc, để tải các tập tin kịch bản để thực hiện. Mặc dù đó là một thỏa hiệp hiệu suất nhỏ, việc thực hiện xảy ra mà không bị hoãn lại.

Chúng ta cần hiểu sự khác biệt giữa các hành vi của cả hai dạng Html và Ajax.

Ajax:

  1. Không chuyển hướng biểu mẫu, ngay cả khi bạn thực hiện RedirectAction ().

  2. Sẽ thực hiện lưu, cập nhật và mọi hoạt động sửa đổi không đồng bộ.

Html:

  1. Sẽ chuyển hướng mẫu.

  2. Sẽ thực hiện các hoạt động cả Đồng bộ và Không đồng bộ (Có thêm một số mã và chăm sóc).

Thể hiện sự khác biệt với POC trong liên kết dưới đây. Liên kết


1

Trước khi thêm Ajax.BeginForm. Thêm các tập lệnh bên dưới vào dự án của bạn theo thứ tự được đề cập,

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

Chỉ hai điều này là đủ để thực hiện hoạt động Ajax.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.