MVC 3: Làm thế nào để hiển thị một khung nhìn mà không có trang bố trí của nó khi được tải qua ajax?


153

Tôi đang tìm hiểu về Tăng cường tiến bộ và tôi có một câu hỏi về quan điểm AJAXifying. Trong dự án MVC 3 của tôi, tôi có một trang bố cục, một trang xem và hai chế độ xem đơn giản.

Trang viewstart nằm trong thư mục gốc của thư mục Lượt xem và do đó áp dụng cho tất cả các lượt xem. Nó chỉ định rằng tất cả các khung nhìn nên sử dụng _Layout.cshtmlcho trang bố trí của chúng. Trang bố trí chứa hai liên kết điều hướng, một liên kết cho mỗi chế độ xem. Các liên kết sử dụng @Html.ActionLink()để hiển thị chính họ đến trang.

Bây giờ tôi đã thêm jQuery và muốn chiếm quyền điều khiển các liên kết này và sử dụng Ajax để tải nội dung của chúng trên trang một cách linh hoạt.

<script type="text/javascript">
    $(function () {
        $('#theLink').click(function () {
            $.ajax({
                url: $(this).attr('href'),
                type: "GET",
                success: function (response) {
                    $('#mainContent').html(response);
                }
            });
            return false;
        });
    });
</script>

Có hai cách tôi có thể nghĩ để làm điều này, nhưng tôi không đặc biệt thích một trong hai cách:

1) Tôi có thể lấy toàn bộ nội dung của Chế độ xem và đặt chúng ở chế độ xem một phần, sau đó có chế độ xem chính gọi chế độ xem một phần khi được hiển thị. Theo cách đó, bằng cách sử dụng Request.IsAjaxRequest()trong bộ điều khiển, tôi có thể trả lại View()hoặc trả về PartialView()dựa trên việc yêu cầu đó có phải là yêu cầu Ajax hay không. Tôi không thể trả lại chế độ xem thông thường cho yêu cầu Ajax vì sau đó nó sẽ sử dụng trang bố cục và tôi sẽ nhận được một bản sao thứ hai của trang bố trí được đưa vào. Tuy nhiên, tôi không thích điều này bởi vì nó buộc tôi phải tạo các chế độ xem trống chỉ với một @{Html.RenderPartial();}trong số chúng cho các yêu cầu GET tiêu chuẩn.

    public ActionResult Index()
    {
        if (Request.IsAjaxRequest())
            return PartialView("partialView");
        else
            return View();
    }

Sau đó, trong Index.cshtml làm điều này:

@{Html.RenderPartial("partialView");}

2) Tôi có thể xóa chỉ định bố cục khỏi _viewstart và chỉ định thủ công khi yêu cầu KHÔNG phải là Ajax:

    public ActionResult Index()
    {
        if (Request.IsAjaxRequest())
            return View(); // Return view with no master.
        else
            return View("Index", "_Layout"); // Return view with master.
    }

Có ai có một đề nghị tốt hơn? Có cách nào để trả về một khung nhìn mà không có trang bố trí của nó không? Sẽ dễ dàng hơn nhiều khi nói "không bao gồm bố cục của bạn" nếu đó là yêu cầu ajax, hơn là bao gồm rõ ràng bố cục nếu đó không phải là ajax.

Câu trả lời:


259

Trong ~/Views/ViewStart.cshtml:

@{
    Layout = Request.IsAjaxRequest() ? null : "~/Views/Shared/_Layout.cshtml";
}

và trong bộ điều khiển:

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

3
Điều này có thể được chỉ định trong viewstart?
Chev

10
@Matt Greer, bạn gọi nó là khó chịu, tôi gọi nó là DRY, công cụ chủ quan nào :-)
Darin Dimitrov

2
Tôi phải thừa nhận, lúc đầu tôi không thích nó, nhưng số lượng mã mà nó lưu có vẻ sẽ vượt xa nhược điểm của nó. Đó là một boolean đơn giản nếu và không thực sự áp đặt IMO nhiều. Tôi thích nó hơn là cắt các phương thức hành động của tôi một nửa mỗi lần. Thêm vào đó, nó ngăn tôi thực hiện những gì bạn nói Matt và có khả năng đi xuống hai con đường logic khổng lồ trong phương thức hành động. Tôi hoặc viết hành động để làm việc như nhau trong cả hai trường hợp, hoặc viết một hành động mới.
Chev

1
bạn không thể làm điều này trong bộ điều khiển cơ sở, đặt thuộc tính trong ViewData và sử dụng nó? Sau đó, dòng sẽ là Layout = ViewBag.LayoutFile.
RPM1984

2
Tôi cho rằng tôi có thể, nhưng thực sự tại sao lại tạo một BaseContoder cho một dòng nhỏ?
Chev

92

Chỉ cần đặt đoạn mã sau lên đầu trang

@{
    Layout = "";
}

4
Điều này không hoạt động vì tôi muốn có thể bật hoặc tắt bố cục dựa trên việc nó có được yêu cầu thông qua AJAX hay không. Điều này chỉ cho phép bạn tắt bố cục, không chuyển đổi nó.
Chev

4
Tại sao điều này có Bình chọn? xin vui lòng giải thích vì vậy tôi sẽ bỏ phiếu lên quá.
Usman Younas

1
@UsmanY. Bạn không cần phải bỏ phiếu. Nhưng tôi làm. Đối số của tôi truy cập google.com.pk/#q=mvc3%20view%20without%20layout . Và đó là câu trả lời hoàn hảo cho truy vấn đó.
Sami

3
Chủ đề là về việc thay đổi bố cục trên hai kịch bản khác nhau. Câu trả lời này chỉ đặt bố cục thành trống cho dù kịch bản là gì.
Rajshekar Reddy

Dude, điều này làm việc và nó thực sự tốt đẹp. Kịch bản tôi sử dụng: Người dùng trái phép cố gắng đăng nhập, người ta không muốn trang lỗi hiển thị các liên kết và tiếp tục với người dùng trái phép! Tất nhiên, nó cũng hoạt động cho mọi thứ khác!
JosephDoggie

13

Tôi thích và sử dụng tùy chọn số 1 của bạn. Tôi không thích # 2 vì với tôi View()ngụ ý rằng bạn đang trả lại toàn bộ trang. Nó phải là một trang HTML hợp lệ đầy đủ và hợp lệ một khi công cụ xem được thực hiện với nó. PartialView()đã được tạo để trả về các đoạn HTML tùy ý.

Tôi không nghĩ rằng đó là một vấn đề lớn để có một quan điểm chỉ gọi một phần. Nó vẫn DRY và cho phép bạn sử dụng logic của một phần trong hai tình huống.

Nhiều người không thích phân đoạn đường dẫn cuộc gọi hành động của họ Request.IsAjaxRequest()và tôi có thể đánh giá cao điều đó. Nhưng IMO, nếu tất cả những gì bạn đang làm là quyết định nên gọi View()hay PartialView()chi nhánh không phải là vấn đề lớn và dễ duy trì (và kiểm tra). Nếu bạn thấy mình đang sử dụng IsAjaxRequest()để xác định các phần lớn về cách hành động của bạn diễn ra, thì thực hiện một hành động AJAX riêng biệt có lẽ tốt hơn.


13

Tạo hai bố cục: 1. bố trí trống, 2. bố cục chính và sau đó viết vào tệp _viewStart mã này:

@{
if (Request.IsAjaxRequest())
{
    Layout = "~/Areas/Dashboard/Views/Shared/_emptyLayout.cshtml";
}
else
{
    Layout = "~/Areas/Dashboard/Views/Shared/_Layout.cshtml";
}}

Tất nhiên, có lẽ nó không phải là giải pháp tốt nhất


8

Bạn không phải tạo một chế độ xem trống cho việc này.

Trong bộ điều khiển:

if (Request.IsAjaxRequest())
  return PartialView();
else
  return View();

trả về PartialViewResult sẽ ghi đè định nghĩa bố cục khi hiển thị phản hồi.


2

Với ASP.NET 5 không có biến Yêu cầu có sẵn nữa. Bạn có thể truy cập nó ngay bây giờ với Context.Request

Ngoài ra, không còn Phương thức IsAjaxRequest () nữa, bạn phải tự viết nó, ví dụ như trong Tiện ích mở rộng \ httpRequestExtensions.cs

using System;
using Microsoft.AspNetCore.Http;

namespace Microsoft.AspNetCore.Mvc
{
    public static class HttpRequestExtensions
    {
        public static bool IsAjaxRequest(this HttpRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            return (request.Headers != null) && (request.Headers["X-Requested-With"] == "XMLHttpRequest");
        }
    }
}

Bây giờ tôi đã tìm kiếm cái này và hy vọng nó cũng sẽ giúp được một số người khác;)

Tài nguyên: https://github.com/aspnet/AspNetCore/issues/2729


-5

Đối với ứng dụng Ruby on Rails, tôi có thể ngăn không cho bố cục tải bằng cách chỉ định render layout: falsetrong hành động của bộ điều khiển mà tôi muốn phản hồi với ajax html.


6
tags: c # asp.net, không phải ruby
MrKekson
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.