MVC 3: How to render a view without its layout page when loaded via ajax?
我正在学习渐进式增强,我有一个关于半开化观点的问题。在我的MVC 3项目中,我有一个布局页面、一个视图开始页面和两个普通视图。
VIEWStart页位于VIEWS文件夹的根目录中,因此适用于所有视图。它指定所有视图的布局页都应使用_Layout.cshtml。布局页面包含两个导航链接,每个视图一个。链接使用@Html.ActionLink()呈现到页面。
现在我已经添加了jquery,并希望劫持这些链接,并使用Ajax动态地将它们的内容加载到页面上。
1 2 3 4 5 6 7 8 9 10 11 12 13
| <script type="text/javascript">
$(function () {
$('#theLink').click(function () {
$.ajax({
url: $(this).attr('href'),
type:"GET",
success: function (response) {
$('#mainContent').html(response);
}
});
return false;
});
}); |
我有两种方法可以做到这一点,但我不特别喜欢这两种方法:
1)我可以获取整个视图的内容并将它们放在局部视图中,然后让主视图在呈现时调用局部视图。这样,使用控制器中的Request.IsAjaxRequest(),我可以根据请求是否为Ajax请求返回View()或返回PartialView()。我无法将常规视图返回到Ajax请求,因为这样它将使用布局页,并且将获得注入布局页的第二个副本。但是,我不喜欢这样,因为它强制我创建空视图,其中只有一个用于标准GET请求的@{Html.RenderPartial();}。
1 2 3 4 5 6 7
| public ActionResult Index()
{
if (Request.IsAjaxRequest())
return PartialView("partialView");
else
return View();
} |
然后在index.cshtml中执行以下操作:
1
| @{Html.RenderPartial("partialView");} |
2)当请求不是Ajax时,我可以从u viewstart中删除布局名称并手动指定:
1 2 3 4 5 6 7
| public ActionResult Index()
{
if (Request.IsAjaxRequest())
return View(); // Return view with no master.
else
return View("Index","_Layout"); // Return view with master.
} |
有人有更好的建议吗?是否有返回不带布局页的视图的方法?如果它是Ajax请求,那么显式地说"不包括您的布局"要比显式地包括非Ajax的布局容易得多。
在~/Views/ViewStart.cshtml中:
1 2 3
| @{
Layout = Request.IsAjaxRequest() ? null :"~/Views/Shared/_Layout.cshtml";
} |
在控制器中:
1 2 3 4
| public ActionResult Index()
{
return View();
} |
- 是否可以在ViewStart中指定?
- @切维斯,当然,我已经更新了我的答案。
- 呃,我觉得很讨厌。我的viewStart页面是关于最后一页的,我希望能找到某种逻辑。
- @马特·格里尔,你管它叫肮脏,我管它叫干燥,主观的东西。—)
- 我不得不承认,起初我不喜欢它,但它保存的代码数量似乎远远超过了它的缺点。这是一个简单的布尔如果,并没有真正施加太多的IMO。我喜欢它比每次把我的动作方法切成两半更好。另外,它阻止了我做你所说的马特,并可能在动作方法中沿着两条巨大的逻辑路径走下去。在这两种情况下,我要么编写相同的操作,要么编写新的操作。
- 你不能在一个基本控制器中这样做,在viewdata中设置一个属性并使用它吗?那么这条线就是Layout = ViewBag.LayoutFile。
- 我想我可以,但真的为什么要为一条小线路创建一个basecontroller?
- 如果视图试图向@section中注入内容,这将不起作用。
- @达林有没有办法把这个放在胶辊上?
- @Shimmy,是的,有一种方法,您可以使用视图方法的适当重载,它允许您在返回视图结果时指定布局。
- 这很好地工作,但是有没有一种方法可以只隐藏页眉,而显示布局文件的页脚部分?
- @Darin,我做了一篇Ajax文章,并使用了这里所说的返回视图();但是我的内容随着布局的更新而更新,但是这解决了这个问题。我有一个问题,正常使用@UrlAction vs Ajax post的帖子,哪一个可以快速返回视图?
- @希米看我的答案
- 我认为这打破了关注点分离的原则;一个观点不应该关心它的呈现方式。另一方的控制器拥有决定渲染结果的内容和方式所需的所有信息。
把下面的代码放在页面的顶部
- 这不起作用,因为我希望能够根据是否通过Ajax请求布局来打开或关闭布局。这只允许您关闭布局,而不切换它。
- 为什么要投票?请解释一下,我也会投赞成票。
- @ UsmanY。你不需要投票表决。但我知道。我的论点是去google.com.pk/q=mvc3%20view%20without%20layout.这是对那个问题的完美回答。
- 主题是关于在两个不同的场景中切换布局。这个答案只是将布局设置为空,不管场景是什么。
- 伙计,这很管用,而且很不错。我使用的场景是:未授权的用户试图登录,不希望错误页面显示链接,等等!当然,它也适用于其他一切!
- @乌斯曼,见以上评论
- 这就是我反对它的原因:我有两个单独的页面,一个用于UI,一个用于Ajax查询。在Ajax页面中,我不需要主页面布局。现在,在vs2013 upd4中,您只需删除"layout=something"行,它就会分解。但在VS2013 Rel1中,这还不够。即使没有这条线,也仍然包括版面布局。因此,在我的情况下,隐式地将其设置为"layout=''。这也说明"如果你想让这段代码100%工作,只要你真的想隐藏它,就使用layout=''。另外,我没有选择使用哪一种。客户决定:(
- 这可能无法回答OP中的问题,但我还是投了反对票,因为它回答了我需要回答的问题。
- 当我问到如何阻止为部分视图加载布局时,Google引导我找到了这个特别的答案,因为默认布局包括jquery加载,这导致了臭名昭著的"在初始化之前无法调用对话框上的方法;试图在我的部分视图中使用对话框调用方法open"。这就是为什么我反对这个答案。
创建两个布局:1。空布局,2.主布局,然后写在viewstart文件中此代码:
1 2 3 4 5 6 7 8 9
| @{
if (Request.IsAjaxRequest())
{
Layout ="~/Areas/Dashboard/Views/Shared/_emptyLayout.cshtml";
}
else
{
Layout ="~/Areas/Dashboard/Views/Shared/_Layout.cshtml";
}} |
当然,也许这不是最好的解决办法
我更喜欢和使用你的1选项。我不喜欢2,因为对我来说,View()意味着你要返回一整页。一旦视图引擎使用完它,它就应该是一个完整、有效的HTML页面。创建PartialView()是为了返回任意的HTML块。
我不认为有一个仅仅称之为局部的观点是什么大不了的。它仍然是干燥的,并且允许您在两个场景中使用分部的逻辑。
许多人不喜欢用Request.IsAjaxRequest()分割他们行动的调用路径,我可以理解。但是,在我看来,如果你所做的只是决定是叫View()还是PartialView(),那么这个分支就不是什么大问题,而且很容易维护(和测试)。如果您发现自己使用IsAjaxRequest()来确定大部分操作的执行方式,那么单独执行Ajax操作可能更好。
您不必为此创建空视图。
在控制器中:
1 2 3 4
| if (Request.IsAjaxRequest())
return PartialView();
else
return View(); |
返回partialView结果将在呈现响应时重写布局定义。
对于RubyonRails应用程序,我可以通过指定我想用Ajax HTML响应的控制器操作中的render layout: false。