MVC 3:如何在通过 ajax 加载时呈现没有布局页面的视图?
Posted
技术标签:
【中文标题】MVC 3:如何在通过 ajax 加载时呈现没有布局页面的视图?【英文标题】:MVC 3: How to render a view without its layout page when loaded via ajax? 【发布时间】:2011-07-16 03:49:31 【问题描述】:我正在学习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()
,我可以根据请求是否为Ajax 请求返回View()
或返回PartialView()
。我无法将常规视图返回给 Ajax 请求,因为那样它将使用布局页面,并且我会得到第二个注入的布局页面副本。但是,我不喜欢这样,因为它迫使我为标准 GET 请求创建空视图,其中只包含 @Html.RenderPartial();
。
public ActionResult Index()
if (Request.IsAjaxRequest())
return PartialView("partialView");
else
return View();
然后在 Index.cshtml 中这样做:
@Html.RenderPartial("partialView");
2) 当请求不是 Ajax 时,我可以从 _viewstart 中删除布局指定并手动指定它:
public ActionResult Index()
if (Request.IsAjaxRequest())
return View(); // Return view with no master.
else
return View("Index", "_Layout"); // Return view with master.
有人有更好的建议吗?有没有办法在没有布局页面的情况下返回视图?如果它是一个 ajax 请求,明确地说“不包括你的布局”会比明确地包含布局要容易得多,如果它不是一个 ajax。
【问题讨论】:
【参考方案1】:在~/Views/ViewStart.cshtml
:
@
Layout = Request.IsAjaxRequest() ? null : "~/Views/Shared/_Layout.cshtml";
在控制器中:
public ActionResult Index()
return View();
【讨论】:
这个可以在viewstart中指定吗? @Matt Greer,你说它讨厌,我称之为 DRY,无论如何都是主观的东西 :-) 我不得不承认,一开始我并不喜欢它,但它节省的代码量似乎远远超过了它的缺点。这是一个简单的布尔值,如果并且并没有真正强加 IMO。我喜欢它而不是每次都将我的动作方法切成两半。另外,它会阻止我做你所说的 Matt,并且可能会在 action 方法中走下两条巨大的逻辑路径。我要么编写动作以在两种情况下工作相同,要么编写一个新动作。 您不能在基本控制器中执行此操作,在 ViewData 中设置一个属性并使用它吗?那么该行将是Layout = ViewBag.LayoutFile
。
我想我可以,但为什么要为一小行创建一个 baseController?【参考方案2】:
只需将以下代码放在页面顶部
@
Layout = "";
【讨论】:
这不起作用,因为我希望能够根据是否通过 AJAX 请求来打开或关闭布局。这仅允许您关闭布局,而不是切换它。 为什么会有投票??请解释一下,所以我也会投票赞成。 @UsmanY。你不需要投票。但是我愿意。我的争论转到 google.com.pk/#q=mvc3%20view%20without%20layout 。这是该查询的完美答案。 本主题是关于在两种不同场景下切换布局。这个答案只是将布局设置为空,无论场景是什么。 老兄,这行得通,真的很好。我使用的场景:未经授权的用户尝试登录,不希望错误页面向未经授权的用户显示链接等等!当然,它也适用于其他一切!【参考方案3】:我更喜欢并使用您的 #1 选项。我不喜欢#2,因为对我来说View()
意味着您要返回整个页面。一旦视图引擎完成它,它应该是一个完全充实且有效的 HTML 页面。 PartialView()
被创建用于返回任意 HTML 块。
我认为拥有一个仅称为局部视图的视图没什么大不了的。它仍然是 DRY,并允许您在两个场景中使用部分的逻辑。
许多人不喜欢使用Request.IsAjaxRequest()
分割他们的操作调用路径,我可以理解这一点。但是 IMO,如果您所做的只是决定是调用 View()
还是 PartialView()
,那么分支没什么大不了的,并且易于维护(和测试)。如果您发现自己使用IsAjaxRequest()
来确定您的大部分操作如何进行,那么制作一个单独的 AJAX 操作可能会更好。
【讨论】:
【参考方案4】:您只需要创建两个布局:
一个空的布局
主布局
然后在_viewStart文件中编写如下代码:
@
if (Request.IsAjaxRequest())
Layout = "~/Areas/Dashboard/Views/Shared/_emptyLayout.cshtml";
else
Layout = "~/Areas/Dashboard/Views/Shared/_Layout.cshtml";
当然,也许这不是最好的解决方案
【讨论】:
【参考方案5】:您不必为此创建一个空视图。
在控制器中:
if (Request.IsAjaxRequest())
return PartialView();
else
return View();
返回 PartialViewResult 将在呈现响应时覆盖布局定义。
【讨论】:
【参考方案6】:在 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
【讨论】:
【参考方案7】:对于 Ruby on Rails 应用程序,我可以通过指定来阻止加载布局
render layout: false
在我想用 ajax html 响应的控制器操作中。
【讨论】:
标签:c# asp.net,不是 ruby以上是关于MVC 3:如何在通过 ajax 加载时呈现没有布局页面的视图?的主要内容,如果未能解决你的问题,请参考以下文章