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

Che*_*hev 152 c# asp.net-mvc master-pages razor asp.net-mvc-3

我正在学习渐进式增强功能,我对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>
Run Code Online (Sandbox Code Playgroud)

我可以通过两种方式来做到这一点,但我并不特别喜欢这两种方式:

1)我可以获取整个View的内容并将它们放在局部视图中,然后让主视图在渲染时调用局部视图.这样,Request.IsAjaxRequest()在控制器中使用,我可以根据请求是否是Ajax请求返回View()或返回PartialView().我无法将常规视图返回到Ajax请求,因为它将使用布局页面,我将获得注入的布局页面的第二个副本.但是,我不喜欢这个,因为它迫使我创建空视图,其中只有一个@{Html.RenderPartial();}用于标准GET请求.

    public ActionResult Index()
    {
        if (Request.IsAjaxRequest())
            return PartialView("partialView");
        else
            return View();
    }
Run Code Online (Sandbox Code Playgroud)

然后在Index.cshtml中执行以下操作:

@{Html.RenderPartial("partialView");}
Run Code Online (Sandbox Code Playgroud)

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.
    }
Run Code Online (Sandbox Code Playgroud)

有人有更好的建议吗?有没有办法在没有布局页面的情况下返回视图?如果它是一个ajax请求,那么明确地说"不包括你的布局"会比在明确包含布局(如果它不是ajax)要容易得多.

Dar*_*rov 254

~/Views/ViewStart.cshtml:

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

并在控制器中:

public ActionResult Index()
{
    return View();
}
Run Code Online (Sandbox Code Playgroud)

  • @Matt Greer,你叫它讨厌,我称之为DRY,主观的东西无论如何:-) (10认同)
  • 可以在viewstart中指定吗? (3认同)
  • 我不得不承认,起初我并不喜欢它,但它节省的代码量似乎远远超过了它的缺点.这是一个简单的布尔值,如果并没有真正强加IMO.我喜欢它,而不是每次都把我的动作方法切成两半.另外,它阻止我做你所说的马特,并可能在动作方法中沿着两条巨大的逻辑路径走下去.我要么在两种情况下编写动作都相同,要么写一个新动作. (2认同)
  • 我想我可以,但真的为什么为一条小线创建一个baseController? (2认同)

ron*_*san 89

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

@{
    Layout = "";
}
Run Code Online (Sandbox Code Playgroud)

  • 这不起作用,因为我希望能够根据是否通过AJAX请求来打开或关闭布局.这只允许您关闭布局,而不是切换它. (4认同)
  • 为什么这有投票?请解释一下,我也会投票. (3认同)
  • 主题是关于在两种不同场景下切换布局.这个答案只是将布局设置为空,无论场景是什么. (3认同)

Mat*_*eer 13

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

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

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


Ara*_*ami 13

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

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

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


Sou*_*bes 8

您不必为此创建空视图.

在控制器中:

if (Request.IsAjaxRequest())
  return PartialView();
else
  return View();
Run Code Online (Sandbox Code Playgroud)

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