MVC 3:当通过ajax加载时,如何在没有布局页面的情况下呈现视图?

时间:2011-03-15 21:37:27

标签: c# asp.net-mvc asp.net-mvc-3 master-pages razor

我正在了解Progressive Enhancement,我对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()或根据请求是否是Ajax请求返回PartialView()。我无法将常规视图返回到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 个答案:

答案 0 :(得分:251)

~/Views/ViewStart.cshtml

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

并在控制器中:

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

答案 1 :(得分:89)

只需将以下代码放在页面顶部

即可
@{
    Layout = "";
}

答案 2 :(得分:13)

我更喜欢并使用你的#1选项。我不喜欢#2,因为我View()暗示你要返回一整页。一旦视图引擎完成,它应该是一个完全充实且有效的HTML页面。创建PartialView()以返回任意HTML块。

我认为让一个只调用偏见的观点并不重要。它仍然是DRY,允许您在两种情况下使用partial的逻辑。

很多人不喜欢用Request.IsAjaxRequest()分割他们的动作的呼叫路径,我很欣赏。但IMO,如果你所做的只是决定是否调用View()PartialView()那么分支并不是一个大问题,并且易于维护(和测试)。如果您发现自己使用IsAjaxRequest()来确定动作的大部分内容,那么制作单独的AJAX动作可能会更好。

答案 3 :(得分:13)

创建两个布局:1。空布局,2。主要布局然后在_viewStart文件中写入此代码:

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

当然,也许这不是最好的解决方案

答案 4 :(得分:7)

您不必为此创建空视图。

在控制器中:

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

返回PartialViewResult将在呈现响应时覆盖布局定义。

答案 5 :(得分:1)

在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

答案 6 :(得分:-4)

对于Ruby on Rails应用程序,我能够通过指定来阻止加载布局 我想用ajax html响应的控制器操作中的render layout: false