MVC 3:如何通过Ajax加载没有其布局页面的视图?


153

我正在学习渐进增强功能,并且对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(),我就可以在控制器中使用,根据请求是否为Ajax请求来返回View()或返回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,则要显式地包括布局要容易得多。

Answers:


259

~/Views/ViewStart.cshtml

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

并在控制器中:

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

3
可以在viewstart中指定吗?
CHEV

10
@Matt Greer,您称它为令人讨厌,我称其为DRY,无论如何都是主观的东西:-)
Darin Dimitrov

2
我不得不承认,起初我不喜欢它,但是它节省的代码量似乎远远超过了它的缺点。这是一个简单的布尔值,如果确实不加太多IMO。我比每次将动作方法切成两半要好。另外,它阻止了我执行您所说的Matt的操作,并有可能使该操作方法陷入两条巨大的逻辑道路。我编写的动作在两种情况下都可以工作,或者编写新的动作。
CHEV

1
您不能在基本控制器中执行此操作,在ViewData中设置属性并使用它吗?那行是Layout = ViewBag.LayoutFile
RPM1984 2011年

2
我想可以,但是真的为什么要为一小行创建一个baseController?
CHEV

92

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

@{
    Layout = "";
}

4
这不起作用,因为我希望能够根据是否通过AJAX请求来打开或关闭布局。这仅允许您关闭布局,而不能切换布局。
CHEV

4
为什么这会引起投票?请解释,所以我也会投赞成票。
Usman Younas

1
@UsmanY。您无需投票。但是我愿意。我的论点转到google.com.pk/#q=mvc3%20view%20without%20layout。这是对该查询的完美答案。
萨米(Sami)2013年

3
主题是关于在两种不同情况下切换布局。无论情况如何,此答案都只是将布局设置为空。
Rajshekar Reddy 2013年

杜德,这行得通,而且非常好。我使用的方案:未经授权的用户尝试登录,一个不希望错误页面显示指向未经授权的用户的链接等!当然,它也适用于其他所有功能!
JosephDoggie 2014年

13

我更喜欢并使用您的#1选项。我不喜欢#2,因为对我而言View()意味着您将返回整个页面。查看引擎完成后,它应该是充实且有效的HTML页面。PartialView()被创建为返回HTML的任意块。

我认为拥有只需要部分视图的视图并不重要。它仍然是DRY,并且允许您在两种情况下使用部分逻辑。

许多人不喜欢使用来分散操作的调用路径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时,不再有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


-5

对于Ruby on Rails应用程序,我可以通过render layout: false在控制器操作中指定要使用ajax html进行响应的方式来防止布局加载 。


6
标签:c#asp.net,不是红宝石
MrKekson
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.