3

我想使用 ASP.NET MVC 构建一个具有“单页界面”的 Web 应用程序。

我已经搜索了这是否至少是可能的,我认为答案是:不是通过简单的方式(阅读http://msdn.microsoft.com/en-us/magazine/cc507641.aspx#S2 second-last paragraph;那篇文章不过是从 2008 年 5 月开始的)。

我发现了其他通过使用 jQuery 进行编码/黑客攻击来实现这一点的示例。但是,如果可能的话,我正在寻找一个干净的解决方案,使用标准的 .NET 方法。

当您创建一个新的“MVC Web 应用程序”时,我想要的是完全相同的功能。但是,我想要链接到“ # Home/About”的链接,而不是重新加载整个页面的“/Home/About”链接,它只通过 AJAX 加载新部分。

使用 Html.RenderPartial 调用模板(部分视图)的标准方法正是我想要的,然后才通过 AJAX 请求加载它们。

当然,可能由于某种原因,我不能使用母版页呈现的这些模板(也许它总是希望在某个上下文中从某个地方或某个地方调用)。但是,对于如何构建模板页面并从母版页面获取它们,也许还有另一种干净的解决方案。

谁有一个很好的解决方案来实现这样的事情,单页界面?

PS:我正在使用 C# 安装 MVC 1.0 的 Visual Web Developer 2008 Express Edition 进行开发

[编辑] 下面我读到使用模板是可能的,而且 jQuery 看起来确实是不可避免的,所以我对其进行了测试。以下代码将 Html.ActionLink 创建的常规链接转换为锚链接(带 #)以包含历史记录,然后通过 AJAX 获取页面并仅注入我感兴趣的 html 部分(即 div 中的部分页面#部分视图):

$("a").each(function() {
    $(this).click(function() {
        $("div#partialView").load($(this).attr("href") + " div#partialView");
        location.hash = $(this).attr("href");
        return false;
    });
});

这些链接还允许优雅的降级。

但是我现在剩下的仍然是获取整个页面而不是仅获取部分页面。改变控制器没有帮助。它仍然为我提供了整个页面的 html,以及所有这些语句:

public ActionResult About()
{
    return View();
    return View("About");
    return PartialView();
    return PartialView("About");
}

我怎样才能只返回我感兴趣的部分的内容(即 Home/About.aspx 的内容)?我想要的是使用 AJAX 发布一个值(例如“requesttype=ajax”),以便我的控制器知道该页面是通过 AJAX 获取的,并且只返回部分页面;否则它将返回整个页面(即当您访问/Home/About 而不是#Home/About 时)。

更改 Global.asax.cs 是否为 AJAX 调用创建一个新的路由模式是一个好习惯,它只会返回部分页面?(我还没有研究这么多。)

[edit2] Robert Koritnik 是对的:我还需要一个 About.ascx 页面 (UserControl),其中只有该页面的小 HTML 内容。About.aspx 的第一行与母版页链接,MasterPageFile="~/..../Site.master"从而导致所有 HTML 都被打印出来。

但是为了能够在我的控制器中执行以下操作:

public ActionResult About()
{
    return Request.IsAjaxRequest() ? (ActionResult)PartialView() : View();
}

我需要更改找到PartialView(.ascx 文件) 和View(.aspx) 文件的方式,否则这两种方法将返回相同的页面 ( About.aspx,最终导致无限循环)。将以下内容放入 后Global.asax.cs,将返回正确的页面PartialView()View()

protected void Application_Start()
{
    foreach (WebFormViewEngine engine in ViewEngines.Engines.Where(c => c is WebFormViewEngine))
    {
        /* Normal search order:
        new string[] { "~/Views/{1}/{0}.aspx",
            "~/Views/{1}/{0}.ascx",
            "~/Views/Shared/{0}.aspx"
            "~/Views/Shared/{0}.ascx"
        };
        */

        // PartialViews match with .ascx files
        engine.PartialViewLocationFormats = new string[] { "~/Views/{1}/{0}.ascx", "~/Views/Shared/{0}.ascx" };

        // Views match with .aspx files
        engine.ViewLocationFormats = new string[] { "~/Views/{1}/{0}.aspx", "~/Views/Shared/{0}.aspx" };
    }

    RegisterRoutes(RouteTable.Routes);
}
4

5 回答 5

1

好吧,您可以通过 AJAX 请求加载 Partial View。例如,我将使用 jquery 进行 ajax 调用。

这些可能是控制器(名为 HomeController)中的操作:

public ActionResult About()
    {
        //Do some logic...
        //AboutView is the name of your partial view
        return View("AboutView");
    }

JQuery ajax 调用将返回的 html 放置在您想要的位置:

var resultDiv = $('#contentDIV');

    $.ajax({
        type: "POST",
        url: "/Home/About",
        success: function(responseHTML) {
            resultDiv.replaceWith(responseHTML);
        }
    });

[编辑问题已更新]

完全可以做你想做的事。第一个控制器动作可以让你返回部分视图,所以我的“AboutView”可能是这样的:

<table>
<tr>
    <th>
        Column1Header
    </th>
    <th>
        Column2Header
    </th>
</tr>
<tr>
    <td>
    ...
    </td>
    <td>
    ...
    </td>
</tr>

而这个 HTML 正是你在 jquery ajax 方法的成功处理程序上的 responseHTML 中所拥有的。

其次,如果请求是 ajax 请求,您可以在控制器操作中进行区分:

public ActionResult About()
    {
        //partial AboutView is returned if request is ajax
        if (Request.IsAjaxRequest())
            return View("AboutView");
        else //else it will be the default view (page) for this action: "About"
            return View();
    }
于 2009-10-15T17:39:06.067 回答
1

全视图与部分视图

好像你搞砸了什么。如果您创建一个About.aspx包含显示整个页面所需的所有 HTML 的页面,那么您是否说

return PartialView('About');

该视图仍会返回其中写入的所有 HTML。

您应该创建一个单独About.ascx的,仅包含页面本身的内容,而不包含作为整个页面一部分的标题和其他内容。

您的原始页面About.aspx在其内容中会包含这样的内容(以避免重复编写相同的内容两次):

<%= Html.RenderPartial("About") %>

你可以有两个控制器动作。一个返回常规视图,一个返回部分视图:

return View("About"); // returns About.aspx that holds the content of the About.ascx as well
return PartialView("About"); // only returns the partial About.ascx

关于 Global.asax 中的路线

与其为 Ajax 调用编写单独的路由,不如编写一个与操作过滤器类似的AcceptVerbsAttribute操作过滤器。这样,您来自客户端的请求将保持不变(从而防止用户手动请求错误的内容),但根据请求类型,将执行正确的控制器操作。

于 2009-10-16T16:32:01.363 回答
0

我们有一个网站可以做到这一点,你真的想在这里使用 jQuery 路由——从长远来看更容易实现。对于没有启用 javascript 的用户(如谷歌),您可以轻松地使其优雅降级。

于 2009-10-15T17:32:13.613 回答
0

您要求的不是很清楚,是完整的示例还是某些特定功能?对于简单的场景,您应该能够在没有 JQuery 的情况下执行此操作,您可以使用 Ajax 视图助手,如 ActionLink 方法。另外,我不太明白您对 RenderPartial 有什么问题,但也许您正在寻找类似 ASP.NET MVC Futures 的 RenderAction 之类的东西。

于 2009-10-15T17:39:34.720 回答
0

ASP.NET MVC 4(现在处于测试阶段)在 MVC 中添加了对单页应用程序的支持。

http://www.asp.net/single-page-application

更新:......他们从 MVC 4 RC 中删除了它

更新:......它在 2012 年秋季更新中回归

于 2012-02-22T20:10:26.520 回答