【问题标题】:ASP.Net Web Api + KnockoutJs + MVC4 - Tying it togetherASP.Net Web Api + KnockoutJs + MVC4 - 将其捆绑在一起
【发布时间】:2012-08-13 11:12:50
【问题描述】:

我正在开始一个新项目,并且热衷于使用对我来说是新的 KnockoutJS + Web Api,我对 Web Api 有很好的了解,但是目前很难理解 Knockout。

这是我希望我的应用如何工作的最初想法:

  • 我有一个标准的 MVC 控制器,例如 LeadsController
  • LeadsController 有一个名为 ListLeadsAction,虽然它实际上并没有返回任何数据,但只是返回一个带有模板的视图以显示来自 Knockout 的数据。
  • ListLeads 视图通过 ajax 调用我的 api 控制器 LeadsApiController 以获取要显示的潜在客户列表
  • 然后将潜在客户数据映射到 KnockoutJs ViewModel(我不想将我的视图模型从服务器端复制到 JavaScript 视图模型中)
  • 我想尽可能多地使用外部 JavaScript 文件,而不是让我的 HTML 页面充满 JavaScript。

我见过很多例子,但大多数都是在第一次加载页面时返回一些初始数据,而不是通过 ajax 调用。

所以我的问题是,当从 ajax 检索时,如何为 Knockout 创建我的 JavaScript viewModel,其中 ajax url 是使用Url.Content() 创建的。

另外,如果我需要在这个 ViewModel 上附加计算值,我将如何从服务器端扩展映射的视图模型。

如果我没有很好地解释自己,请让我知道您不确定的内容,我会尝试更新我的问题以更明确。

【问题讨论】:

    标签: asp.net-mvc knockout.js asp.net-web-api knockout-mapping-plugin


    【解决方案1】:

    我认为你的设计是个好主意。事实上,我现在正在使用这种设计开发一个应用程序!

    您不必在页面中嵌入初始数据。相反,当您的页面加载时,创建一个空视图模型,调用 ko.applyBindings,然后启动 AJAX 调用,该调用将在完成时填充视图模型:

    $(function () {
        var viewModel = {
            leads: ko.observableArray([]) // empty array for now
        };
    
        ko.applyBindings(viewModel);
    
        $.getJSON("/api/Leads", function (data) {
            var newLeads = ko.mapping.fromJS(data)(); // convert to view model objects
            viewModel.leads(newLeads); // replace the empty array with a populated one
        });
    });
    

    在 AJAX 调用完成之前,您需要在页面某处放置“正在加载”消息。

    要生成“/api/Leads”网址,请使用Url.RouteUrl

    <script>
        var apiUrl = '@Url.RouteUrl("DefaultApi", new { httproute = "", controller = "Leads" })';
    </script>
    

    (假设您在 Global.asax 或 App_Start\RouteConfig.cs 中配置的 API 路由命名为“DefaultApi”。)

    上面使用了敲除映射插件将 AJAX JSON 结果转换为敲除视图模型。默认情况下,生成的视图模型将为 JSON 中的每个属性提供一个可观察的属性。要对此进行自定义,例如添加额外的计算属性,请使用敲除映射插件的"create" callback

    在我的应用程序中进行到这一步之后,我发现我需要更多来自服务器端视图模型的元数据,这些元数据可用于客户端代码,例如需要哪些属性,以及对每个属性进行哪些验证。在剔除映射“创建”回调中,我想要这些信息以便在视图模型中自动生成额外的属性和计算的 observables。因此,在服务器端,我使用了一些 MVC 框架类和反射来检查视图模型并生成一些元数据作为嵌入到相关视图中的 JavaScript。在客户端,我有外部 JavaScript 文件,它们连接敲除映射回调并根据页面中提供的元数据生成视图模型。我的建议是首先在每个视图中手动编写淘汰视图模型自定义和其他 JavaScript,然后在重构时将通用 JavaScript 函数移到外部文件中。每个视图最终应该只包含特定于该视图的最小 JavaScript,此时您可以考虑编写一些 C# 来从服务器端视图模型注释生成该 JavaScript。

    【讨论】:

    • 嗨乔。你的方法是绝对正确的,我一直在看的很多教程/博客都有类似的解决方案。我一直在为我们正在启动的大型 Web 应用程序评估这种方法。我的它的问题是编写了很多我觉得很难管理的 JS。还有使用 MVC 和 WebAPI 控制器的意义何在?为什么要使用 MVC 控制器来传递一个空视图?似乎它在创造双重性。
    • MCV 返回页面的静态 HTML。 Web API 返回页面的视图模型 JSON 数据。如果您不喜欢“空”视图但仍想使用 Knockout,则可以改为将视图模型数据序列化为服务器上的 JSON 并将其注入 HTML 视图中,只要您不想使用 AJAX并且不要介意 HTML 不再是可缓存的。
    • 现在有很多用于管理大型 JS 应用程序的解决方案。在我写这个答案的那一年里,我们现在有 Breeze.js 和 Durandal 来组织一切并实施管道。查看 Breeze 的 TempHire 演示项目。
    • @JoeDaley 嗨,我刚刚阅读了您的答案,想知道您如何处理使用 knockoutjs 的视图的服务器端验证,即如果模型大多数无效,该怎么办在模型级别使用数据注释完成的验证现在无法用于这种 knockoutjs 方法。请帮忙。
    【解决方案2】:

    对于 url 问题,将其添加到您的 _Layout.cshtml 中,位于将使用它的文件之前的位置:

    <script>
        window._appRootUrl = '@Url.Content("~/")';
    </script>
    

    然后,您可以使用window._appRootUrl 组合字符串连接的网址或借助 URI.js 等 JavaScript 库。

    至于额外的计算值,您可能希望使用淘汰计算 observable。如果这是不可能的,或者您更喜欢在 .Net 中执行此操作,您应该能够仅使用 getter 创建一个属性,但是当您更新客户端上的其他属性(如果它依赖于它们)时,这不会更新。

    【讨论】:

    • 谢谢你的回答,今天下午会调查。我指的是使用敲除计算的可观察对象...只是想知道如何转换由敲除映射插件创建的 ViewModel 以向其添加新的计算值...我是否以某种方式扩展它?谢谢。
    猜你喜欢
    • 2012-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 2012-07-09
    • 1970-01-01
    • 2013-04-02
    相关资源
    最近更新 更多