MVC 3: Cara merender tampilan tanpa halaman tata letaknya ketika dimuat melalui ajax?

153

Saya belajar tentang Peningkatan Progresif dan saya punya pertanyaan tentang pandangan AJAXifying. Dalam proyek MVC 3 saya, saya memiliki halaman tata letak, halaman viewstart, dan dua tampilan biasa.

Halaman viewstart berada di root folder Views dan dengan demikian berlaku untuk semua tampilan. Ini menentukan bahwa semua tampilan harus digunakan _Layout.cshtmluntuk halaman tata letak mereka. Halaman tata letak berisi dua tautan navigasi, satu untuk setiap tampilan. Tautan digunakan @Html.ActionLink()untuk menampilkan diri ke halaman.

Sekarang saya telah menambahkan jQuery dan ingin membajak tautan ini dan menggunakan Ajax untuk memuat konten mereka di halaman secara dinamis.

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

Ada dua cara yang bisa saya pikirkan untuk melakukan ini, tetapi saya tidak terlalu menyukai keduanya:

1) Saya dapat mengambil seluruh konten Tampilan dan menempatkannya dalam tampilan sebagian, kemudian meminta tampilan utama memanggil tampilan sebagian saat itu dibuat. Dengan begitu, menggunakan Request.IsAjaxRequest()di controller, saya bisa kembali View()atau kembali PartialView()berdasarkan apakah permintaannya adalah permintaan Ajax atau tidak. Saya tidak bisa mengembalikan tampilan biasa ke permintaan Ajax karena kemudian akan menggunakan halaman tata letak dan saya akan mendapatkan salinan kedua dari halaman tata letak yang disuntikkan. Namun, saya tidak suka ini karena memaksa saya untuk membuat tampilan kosong hanya dengan @{Html.RenderPartial();}di dalamnya untuk permintaan GET standar.

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

Kemudian di Index.cshtml lakukan ini:

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

2) Saya dapat menghapus penunjukan tata letak dari _viewstart dan menentukan secara manual ketika permintaan BUKAN Ajax:

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

Adakah yang punya saran yang lebih baik? Apakah ada cara untuk mengembalikan tampilan tanpa halaman tata letaknya? Akan lebih mudah untuk secara eksplisit mengatakan "jangan sertakan tata letak Anda" jika itu adalah permintaan ajax, daripada secara eksplisit menyertakan tata letak jika itu bukan ajax.

Chev
sumber

Jawaban:

259

Di ~/Views/ViewStart.cshtml:

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

dan di controller:

public ActionResult Index()
{
    return View();
}
Darin Dimitrov
sumber
3
Bisakah ini ditentukan di viewstart?
Chev
10
@ Matt Greer, Anda menyebutnya jahat, saya menyebutnya KERING, hal-hal subjektif tetap :-)
Darin Dimitrov
2
Harus saya akui, pada awalnya saya tidak suka, tetapi jumlah kode yang disimpannya tampaknya jauh lebih besar daripada kerugiannya. Ini adalah boolean sederhana jika dan tidak benar-benar memaksakan banyak IMO. Saya menyukainya lebih baik daripada memotong metode tindakan saya menjadi dua setiap kali. Plus itu mencegah saya dari melakukan apa yang Anda katakan Matt dan berpotensi turun dua jalur logika raksasa dalam metode tindakan. Saya menulis tindakan untuk bekerja sama di kedua kasus, atau menulis tindakan baru.
Chev
1
tidak bisakah Anda melakukan ini di pengontrol dasar, mengatur properti di ViewData dan menggunakannya? Maka garis akan menjadi Layout = ViewBag.LayoutFile.
RPM1984
2
Saya kira saya bisa, tapi sungguh mengapa membuat baseController untuk satu baris kecil?
Chev
92

Cukup letakkan kode berikut di bagian atas halaman

@{
    Layout = "";
}
roncansan
sumber
4
Ini tidak berfungsi karena saya ingin dapat mengaktifkan atau menonaktifkan tata letak berdasarkan apakah diminta atau tidak melalui AJAX. Ini hanya memungkinkan Anda untuk mematikan tata letak, bukan mengaktifkannya.
Chev
4
Mengapa ini memiliki Suara? tolong jelaskan, jadi saya akan memilihnya juga.
Usman Younas
1
@UsmanY. Anda tidak perlu memilihnya. Tapi saya lakukan. Arguemnt saya buka google.com.pk/#q=mvc3%20view%20without%20layout . Dan ini adalah jawaban sempurna untuk pertanyaan itu.
Sami
3
Topiknya adalah tentang mengubah tata letak pada dua skenario yang berbeda. Jawaban ini hanya mengatur tata letak untuk mengosongkan apa pun skenarionya.
Rajshekar Reddy
Kawan, ini bekerja dan itu sangat bagus. Skenario yang saya gunakan: Pengguna yang tidak sah mencoba masuk, orang tidak ingin halaman kesalahan menampilkan tautan dan sebagainya ke pengguna yang tidak sah! Tentu saja, ini berfungsi untuk semua hal lain juga!
JosephDoggie
13

Saya lebih suka, dan menggunakan, opsi # 1 Anda. Saya tidak suka # 2 karena bagi saya View()menyiratkan Anda mengembalikan seluruh halaman. Ini harus menjadi halaman HTML yang sepenuhnya disempurnakan dan valid setelah mesin tampilan selesai dengannya. PartialView()telah dibuat untuk mengembalikan potongan HTML sewenang-wenang.

Saya tidak berpikir itu masalah besar untuk memiliki pandangan yang hanya menyebut sebagian. Itu masih KERING, dan memungkinkan Anda untuk menggunakan logika parsial dalam dua skenario.

Banyak orang tidak suka memecah-mecah jalur panggilan tindakan mereka Request.IsAjaxRequest(), dan saya bisa menghargai itu. Tetapi IMO, jika semua yang Anda lakukan adalah memutuskan apakah akan menelepon View()atau PartialView()kemudian cabang itu bukan masalah besar dan mudah dipelihara (dan diuji). Jika Anda menemukan diri Anda menggunakan IsAjaxRequest()untuk menentukan sebagian besar dari bagaimana tindakan Anda dimainkan, maka membuat tindakan AJAX terpisah mungkin lebih baik.

Matt Greer
sumber
13

Buat dua tata letak: 1. tata letak kosong, 2. tata letak utama dan kemudian tulis dalam file _viewStart kode ini:

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

tentu saja, mungkin itu bukan solusi terbaik

Arash Karami
sumber
8

Anda tidak harus membuat tampilan kosong untuk ini.

Di controller:

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

mengembalikan PartialViewResult akan menimpa definisi tata letak saat memberikan respons.

Souhaieb Besbes
sumber
2

Dengan ASP.NET 5 tidak ada variabel Permintaan tersedia lagi. Anda dapat mengaksesnya sekarang dengan Context.Request

Juga tidak ada lagi Metode IsAjaxRequest (), Anda harus menulisnya sendiri, misalnya di Extensions \ 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");
        }
    }
}

Saya mencari beberapa saat sekarang tentang ini dan berharap itu akan membantu beberapa orang lain juga;)

Sumberdaya: https://github.com/aspnet/AspNetCore/issues/2729

Drotak
sumber
-5

Untuk aplikasi Ruby on Rails, saya dapat mencegah tata letak dari memuat dengan menentukan render layout: falsedalam tindakan pengontrol yang ingin saya tanggapi dengan ajax html.

pengguna4381244
sumber
6
tag: c # asp.net, bukan ruby
MrKekson