MVC 3: Как визуализировать представление без страницы макета при загрузке через ajax? - PullRequest
153 голосов
/ 16 марта 2011

Я узнаю о Прогрессивном улучшении , и у меня возник вопрос о представлениях AJAXifying.В моем проекте MVC 3 у меня есть страница макета, страница Viewstart и два простых представления.

Страница Viewstart находится в корне папки Views и, следовательно, применяется ко всем представлениям.Он указывает, что все представления должны использовать _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) Я могу взять содержимое всего представления и поместить его в частичное представление, а затем получить основнойview вызывает частичное представление, когда оно отображается.Таким образом, используя 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.

Ответы [ 7 ]

253 голосов
/ 16 марта 2011

В ~/Views/ViewStart.cshtml:

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

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

public ActionResult Index()
{
    return View();
}
89 голосов
/ 22 декабря 2011

Просто поместите следующий код в верхней части страницы

@{
    Layout = "";
}
13 голосов
/ 24 октября 2011

Создайте два макета: 1. пустой макет, 2. Основной макет, а затем записать в _viewStart файл этот код:

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

конечно, может быть, это не лучшее решение

13 голосов
/ 16 марта 2011

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

Я не думаю, что важно иметь представление, которое просто вызывает частичное.Это все еще СУХОЙ, и позволяет вам использовать логику частичного в двух сценариях.

Многим людям не нравится фрагментировать маршруты вызовов их действий с помощью Request.IsAjaxRequest(), и я могу это оценить.Но IMO, если все, что вы делаете, это решаете, звонить ли View() или PartialView(), тогда ветвь не имеет большого значения и ее легко поддерживать (и тестировать).Если вы обнаружите, что используете IsAjaxRequest() для определения больших частей того, как заканчивается ваше действие, тогда лучше сделать отдельное действие AJAX.

7 голосов
/ 11 февраля 2016

Вам не нужно создавать пустое представление для этого.

В контроллере:

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

возвращение PartialViewResult переопределит определение макета при рендеринге отклика.

1 голос
/ 11 июня 2019

В ASP.NET 5 больше нет переменной Request.Теперь вы можете получить к нему доступ с помощью 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

0 голосов
/ 20 декабря 2014

Для приложения Ruby on Rails я смог предотвратить загрузку макета, указав render layout: false в действии контроллера, на которое я хотел ответить ajax html.

...