MVC 3: วิธีการที่จะทำให้มุมมองที่ไม่มีเค้าโครงหน้าของมันเมื่อโหลดผ่านอาแจ็กซ์?


153

ฉันกำลังเรียนรู้เกี่ยวกับการเพิ่มประสิทธิภาพแบบก้าวหน้าและฉันมีคำถามเกี่ยวกับมุมมอง AJAXifying ในโครงการ MVC 3 ของฉันฉันมีหน้าเลย์เอาต์หน้าเริ่มต้นและมุมมองธรรมดาสองมุมมอง

หน้าเริ่มต้นอยู่ในรูทของโฟลเดอร์มุมมองและใช้กับมุมมองทั้งหมด มันระบุว่ามุมมองทั้งหมดควรใช้_Layout.cshtmlสำหรับหน้าเค้าโครงของพวกเขา หน้าเลย์เอาต์มีลิงก์การนำทางสองลิงก์หนึ่งรายการสำหรับแต่ละมุมมอง การเชื่อมโยงการใช้งาน@Html.ActionLink()ที่จะทำให้ตัวเองไปยังหน้า

ตอนนี้ผมได้เพิ่ม jQuery และต้องการที่จะจี้เชื่อมโยงเหล่านี้และใช้อาแจ็กซ์ในการโหลดเนื้อหาของพวกเขาบนหน้าเว็บแบบไดนามิก

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

มีสองวิธีที่ฉันสามารถคิดทำ แต่ฉันไม่ชอบโดยเฉพาะอย่างยิ่ง:

1) ฉันสามารถนำเนื้อหาทั้งหมดของมุมมองและวางไว้ในมุมมองบางส่วนจากนั้นให้มุมมองหลักเรียกมุมมองบางส่วนเมื่อมีการแสดงผล ด้วยวิธีนี้Request.IsAjaxRequest()ในการใช้งานคอนโทรลเลอร์ฉันสามารถส่งคืนView()หรือส่งคืนข้อมูลPartialView()โดยพิจารณาว่าคำขอนั้นเป็นคำขอ Ajax หรือไม่ ฉันไม่สามารถคืนค่ามุมมองปกติไปยังคำขอ Ajax ได้เพราะจะใช้หน้าเลย์เอาต์และฉันจะได้รับสำเนาชุดที่สองของหน้าเลย์เอาต์ อย่างไรก็ตามฉันไม่ชอบสิ่งนี้เพราะมันบังคับให้ฉันสร้างมุมมองว่างเปล่าที่มีเพียงแค่@{Html.RenderPartial();}ในมุมมองสำหรับคำขอ GET มาตรฐาน

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

จากนั้นใน Index.cshtml ทำสิ่งนี้:

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

2) ฉันสามารถลบการกำหนดเค้าโครงจาก _viewstart และระบุด้วยตนเองเมื่อคำขอไม่ใช่ Ajax:

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

ไม่มีใครมีข้อเสนอแนะที่ดีกว่า? มีวิธีคืนมุมมองโดยไม่มีหน้าเลย์เอาต์หรือไม่ มันจะง่ายกว่ามากที่จะพูดอย่างชัดเจนว่า "ไม่รวมเลย์เอาต์ของคุณ" ถ้ามันเป็นคำขออาแจ็กซ์

คำตอบ:


259

ใน~/Views/ViewStart.cshtml:

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

และในตัวควบคุม:

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

3
สามารถระบุได้ในมุมมองเริ่มต้นหรือไม่?
Chev

10
@ Matt เกรียร์ที่คุณเรียกว่าน่ารังเกียจผมเรียกมันแห้งสิ่งอัตนัยล่ะค่ะ :-)
ดารินทร์ดิมิทรอฟ

2
ฉันต้องยอมรับว่าฉันไม่ชอบในตอนแรก แต่จำนวนรหัสที่บันทึกได้ดูเหมือนจะมีน้ำหนักเกินกว่าที่จะเป็นข้อเสีย มันเป็นบูลีนที่เรียบง่ายถ้าและไม่ได้กำหนด IMO มากนัก ฉันชอบที่ดีกว่าการตัดวิธีการกระทำของฉันในครึ่งทุกครั้ง นอกจากนี้ยังป้องกันไม่ให้ฉันทำสิ่งที่คุณพูดว่า Matt และอาจลงไปสองเส้นทางตรรกะขนาดใหญ่ในวิธีการดำเนินการ ฉันจะเขียนการกระทำเพื่อทำงานแบบเดียวกันทั้งสองกรณีหรือเขียนการกระทำใหม่
Chev

1
คุณไม่สามารถทำสิ่งนี้ในตัวควบคุมฐานตั้งค่าคุณสมบัติใน ViewData และใช้งานได้หรือไม่ จากนั้นจะเป็นLayout = ViewBag.LayoutFileเส้น
RPM1984

2
ฉันคิดว่าฉันทำได้ แต่จริง ๆ แล้วทำไมต้องสร้าง baseController สำหรับหนึ่งบรรทัดเล็ก ๆ
Chev

92

เพียงแค่ใส่รหัสต่อไปนี้ที่ด้านบนของหน้า

@{
    Layout = "";
}

4
สิ่งนี้ไม่ทำงานเพราะฉันต้องการที่จะสามารถสลับรูปแบบการเปิดหรือปิดขึ้นอยู่กับว่ามีการร้องขอผ่าน AJAX หรือไม่ สิ่งนี้อนุญาตให้คุณปิดเค้าโครงเท่านั้นไม่ใช่สลับ
Chev

4
ทำไมจึงมีการโหวต กรุณาอธิบายดังนั้นฉันจะลงคะแนนด้วย
Usman Younas

1
@UsmanY คุณไม่จำเป็นต้องลงคะแนน แต่ฉันทำ. ไป arguemnt ของฉันเพื่อgoogle.com.pk/#q=mvc3%20view%20without%20layout และเป็นคำตอบที่สมบูรณ์แบบสำหรับคำค้นหานั้น
Sami

3
หัวข้อนี้เกี่ยวกับการสลับเค้าโครงในสถานการณ์ที่แตกต่างกันสองสถานการณ์ คำตอบนี้เพิ่งตั้งค่าเลย์เอาต์ให้ว่างไม่ว่าสถานการณ์จะเป็นเช่นไร
Rajshekar Reddy

เพื่อนมันใช้งานได้และมันดีจริงๆ สถานการณ์ที่ฉันใช้: ผู้ใช้ที่ไม่ได้รับอนุญาตพยายามเข้าสู่ระบบหนึ่งไม่ต้องการหน้าข้อผิดพลาดเพื่อแสดงลิงก์และอื่น ๆ ต่อผู้ใช้ที่ไม่ได้รับอนุญาต! แน่นอนว่ามันใช้ได้กับทุกสิ่งทุกอย่างด้วยเช่นกัน!
JosephDoggie

13

ฉันชอบและใช้ตัวเลือก # 1 ของคุณ ฉันไม่ชอบ # 2 เพราะโดยView()นัยแล้วฉันหมายความว่าคุณกำลังกลับมาทั้งหน้า มันควรจะเป็นเนื้อออกเต็มและหน้า HTML ที่ถูกต้องเมื่อเครื่องมือดูจะทำกับมัน PartialView()ถูกสร้างขึ้นเพื่อกลับชิ้น HTML โดยพลการ

ฉันไม่คิดว่ามันเป็นเรื่องใหญ่ที่จะมีมุมมองที่เรียกว่าบางส่วน มันยังแห้งและอนุญาตให้คุณใช้ตรรกะของบางส่วนในสองสถานการณ์

หลายคนไม่ชอบเส้นทางการโทรของพวกเขาด้วยการแยกส่วนRequest.IsAjaxRequest()และฉันก็ยินดีที่ แต่ IMO หากสิ่งที่คุณทำคือการตัดสินใจว่าจะโทรView()หรือPartialView()สาขานั้นไม่ใช่เรื่องใหญ่และง่ายต่อการบำรุงรักษา (และทดสอบ) หากคุณพบว่าตัวเองใช้IsAjaxRequest()เพื่อกำหนดส่วนใหญ่ของการกระทำของคุณเล่นแล้วการแยกการกระทำ AJAX น่าจะดีกว่า


13

สร้างเลย์เอาต์สองแบบ: 1. เลย์เอาต์เปล่า 2. เลย์เอาต์หลักแล้วเขียนในไฟล์ _viewStart รหัสนี้:

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

แน่นอนว่าบางทีมันอาจไม่ใช่ทางออกที่ดีที่สุด


8

คุณไม่จำเป็นต้องสร้างมุมมองที่ว่างเปล่าสำหรับสิ่งนี้

ในตัวควบคุม:

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

ส่งคืน PartialViewResult จะแทนที่คำจำกัดความของเค้าโครงเมื่อแสดงการตอบสนอง


2

ด้วย ASP.NET 5 จะไม่มีตัวแปรคำขออีกต่อไป คุณสามารถเข้าถึงได้ทันทีด้วย Context.Request

นอกจากนี้ยังไม่มีวิธี IsAjaxRequest () อีกต่อไปคุณต้องเขียนด้วยตัวเองเช่นใน 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");
        }
    }
}

ฉันค้นหาในขณะนี้และหวังว่าจะช่วยคนอื่นเช่นกัน)

ทรัพยากร: https://github.com/aspnet/AspNetCore/issues/2729


-5

สำหรับแอพพลิเคชั่น Ruby on Rails ฉันสามารถป้องกันการโหลดเลย์เอาต์ได้โดยระบุ render layout: falseในแอคชั่นคอนโทรลเลอร์ที่ฉันต้องการจะตอบด้วย ajax html


6
แท็ก: c # asp.net ไม่ใช่ทับทิม
MrKekson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.