MVC 3: Як візуалізувати подання без його макетної сторінки при завантаженні через ajax?


153

Я дізнаюся про « Прогресивне вдосконалення», і у мене виникає питання про AJAXifying погляди. У моєму проекті MVC 3 у мене є сторінка з макетом, сторінка перегляду та два простих подання.

Сторінка перегляду знаходиться в корені папки «Перегляди» і, таким чином, застосовується до всіх представлень даних. Він визначає, що всі перегляди повинні використовуватись _Layout.cshtmlдля своєї сторінки макета. Сторінка макета містить два посилання навігації, по одному для кожного перегляду. Посилання використовуються @Html.ActionLink()для відображення сторінки.

Тепер я додав jQuery і хочу викрасти ці посилання та використовувати Ajax для динамічного завантаження їх вмісту на сторінку.

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

Хтось має кращу пропозицію? Чи є спосіб повернути перегляд без його сторінки розмітки? Було б набагато простіше прямо сказати "не включати ваш макет", якщо це запит ajax, ніж було б явно включити макет, якщо це не ajax.

Відповіді:


259

В ~/Views/ViewStart.cshtml:

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

і в контролері:

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

3
Чи можна це вказати у програмі перегляду?
Шев

10
@Matt Greer, ви називаєте це противно, я називаю це ДУХО, суб'єктивні речі все одно :-)
Дарин Димитров

2
Треба визнати, спочатку мені це не сподобалось, але кількість збереженого коду, здавалося б, значно перевершує його, як і вниз. Це простий булевий, якщо і насправді не нав'язує багато ІМО. Мені це подобається краще, ніж рубати свої методи дії навпіл щоразу. Плюс це заважає мені робити те, що ви сказали, Метт, і, можливо, пройти два гігантські логічні шляхи в методі дій. Я або пишу дії, щоб вони працювали однаково в обох випадках, або пишу нову дію.
Шев

1
ви не могли цього зробити в базовому контролері, встановити властивість у ViewData і використовувати це? Тоді лінія була б Layout = ViewBag.LayoutFile.
RPM1984

2
Я гадаю, що міг би, але насправді для чого створити базовий контролер для однієї маленької лінії?
Шев

92

Просто поставте наступний код у верхній частині сторінки

@{
    Layout = "";
}

4
Це не працює, тому що я хочу мати можливість вмикати або вимикати макет залежно від того, запитується це через AJAX чи ні. Це дозволяє лише вимкнути макет, а не перемикати його.
Шев

4
Чому це повинно проголосувати ?? pls поясніть, тому я також проголосую за це.
Usman Younas

1
@UsmanY Не потрібно його голосувати. Але я роблю. Мій аргумент перейдіть на google.com.pk/#q=mvc3%20view%20without%20layout . І це ідеальна відповідь на цей запит.
Самі

3
Тема стосується перемикання макета за двома різними сценаріями. Ця відповідь просто встановлює макет порожнього, незалежно від сценарію.
Райджекар Редді

Чувак, це працює, і це справді приємно. Сценарій, який я використовую: Несанкціонований користувач намагається увійти, не хоче, щоб на сторінці помилок відображалися посилання та інше неавторизованому користувачеві! Звичайно, це працює і для всього іншого!
ДжозефДоггі

13

Я віддаю перевагу і використовую ваш варіант №1. Мені не подобається №2, тому що для мене View()означає, що ти повертаєш всю сторінку. Це має бути повністю розробленою та дійсною HTML-сторінкою після того, як механізм перегляду буде виконаний з нею. PartialView()створено для повернення довільних фрагментів HTML.

Я не думаю, що бачити, що просто називається частковою, не дуже важливо. Він досі сухий, і дозволяє використовувати логіку часткового у двох сценаріях.

Багатьом людям не подобається фрагментація шляхів виклику їх дії Request.IsAjaxRequest(), і я можу це оцінити. Але ІМО, якщо все, що ви робите, - це вирішити питання про те, чи зателефонувати 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 () більше немає, його потрібно написати самостійно, наприклад у розширеннях \ 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/isissue/2729


-5

Для програми Ruby on Rails мені вдалося запобігти завантаженню макета, вказавши render layout: falseв дії контролера, що я хочу відповісти html-файлом ajax.


6
теги: c # asp.net, а не рубін
MrKekson
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.