在最近的几篇文章中,创建了一个ASP.NET CoreWeb API 项目而不是 ASP.NET Core Web App 项目,因为正在实现一个 API 而不是一个 Web 应用程序。尽管如此, API 包括用于管理和测试 API 功能的默认页面,为了渲染这些页面和 .js 文件,最终实现了一个控制器来返回 .html 和 .js 文件,这显然是错误的方法。
在这篇文章中,将向展示如何创建一个ASP.NET CoreWeb API项目,该项目还包括渲染浏览器请求的文件。这其中有一些细微的差别!
Swagger 非常适合生成用于测试端点的 UI。本文的重点是展示如何在想要更用户友好且更复杂的页面(例如管理页面)的情况下添加 Web 页面。
因为有时候不需要 Razor 项目(VS2019 中的一个选项),也不想使用 Model-View-Controller 项目(VS2019 中的另一个选项),当然不需要 Blazor(VS2019 中的另一个选项)。只需要一个 API,它有一些内置页面,这些页面的功能比 Swagger 更多,但由于正在编写的是 API,所以不需要 Razor、Blazor 或 MVC。(就个人而言,认为无论 Web 应用程序的复杂性如何,都不应“需要”使用这三个选项中的任何一个,但这只是看法。)
所以,已经创建了一个Web API项目:
C# [ApiController] [Route("[controller]")] public class SpiffyController : ControllerBase { [HttpGet] public object Get() { return Content("Hello World", "text/html"); } }
然后,按照这个优秀的 StackOverflow 帖子:
C# app.UseDefaultFiles(); app.UseStaticFiles();
UseDefaultFiles:设置默认页面为访问者提供了网站的起点。要提供来自 wwwroot 的默认页面,而不需要完全合格的 URI,请调用 UseDefaultFiles 方法。
UseStaticFiles:静态文件存储在项目的 web 根目录中。默认目录是 {content root}/wwwroot。
创建 wwwroot 文件夹,并将 index.html 放入其中(以及想要在顶级目录中的任何其他内容):
HTML <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <title>TypeScript HTML App</title> </head> <body> <div> <button id="btnHi">Say hello</button> <div id="response"></div> <button id="btnGoodbye">Goodbye</button> </div> </body> </html>
goodbye.html 看起来像这样:
HTML <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title></title> </head> <body> <h2>Goodbye!</h2> </body> </html>
到目前为止,运行项目,可以看到:
然后创建一个 Scripts 文件夹,并添加一个 TypeScript 文件(注意把文件夹直接放在项目下):
这会给这样的消息:
所以这样做了,还设置了 ECMAScript 版本至少为 2017:
不想让 .js 文件进入同一个 Scripts 文件夹,只想让它们在 wwwroot/js 下:
所以去项目属性并重定向TypeScript编译器输出:
看到那起作用了:
但是 index.html 不知道如何加载将从TypeScript文件编译的 .js 文件。所以在 index.html 中添加这行:
HTML <script src="/js/app.js"></script>
现在,演示脚本文件看起来像这样:
JavaScript window.onload = () => { new App().init(); }; class App { public init() { document.getElementById("btnHi").onclick = () => this.Hi(); document.getElementById("btnGoodbye").onclick = () => window.open('goodbye.html', '_self'); } private Hi(): void { XhrService.get(`${window.location.origin}/Spiffy`).then(xhr => { document.getElementById("response").innerHTML = xhr.responseText; }); } }
使用 Require
开发人员将 RequireJS 描述为“JavaScript 文件和模块加载器”。RequireJS 加载纯 JavaScript 文件以及更定义的模块。它针对浏览器使用进行了优化,包括在 Web Worker 中使用,但也可以在其他 JavaScript 环境中使用,如 Rhino 和 Node。它实现了异步模块 API。使用像 RequireJS 这样的模块脚本加载器将提高代码速度和质量。另一方面,Webpack 被详细描述为“JavaScript 和朋友的打包器”。
以上是一个简单的例子,但如果 TypeScript 类在不同的文件中呢?倾向于使用 require 而不是像 Webpack 这样的打包器,如果没有其他原因,那是因为它更容易配置(在看来),已经习惯了。
不要这样做!会得到不需要的所有东西。这样做:
npm install --save @types/requirejs
这将安装 require 的 .d.ts 文件:
在 Scripts 文件夹中创建一个 AppConfig.ts 文件:
JavaScript import { App } from "./App"; require(['App'], () => { const appMain = new App(); appMain.run(); });
并将 app.ts 重构为两个文件:
App.ts JavaScript import { XhrService } from "./XhrService"; export class App { public run() { document.getElementById("btnHi").onclick = () => this.Hi(); document.getElementById("btnGoodbye").onclick = () => window.open('goodbye.html', '_self'); } private Hi(): void { XhrService.get(`${window.location.origin}/Spiffy`).then(xhr => { document.getElementById("response").innerHTML = xhr.responseText; }); } }
XhrService.ts JavaScript export class XhrService { public static async get(url: string): Promise { const xhr = new XMLHttpRequest(); return new Promise((resolve, reject) => { xhr.onreadystatechange = () => { if (xhr.readyState === 4) { if (xhr.status >= 200 && xhr.status < 300) { resolve(xhr); } else { reject(xhr); } } }; xhr.open("GET", url, true); xhr.setRequestHeader("Content-Type", "application/json"); xhr.send(); }); } }
运行Web API项目,无论是使用项目 Debug 属性选项中的 Launch Browser 作为控制器名称:
这将击中 API 端点,还是什么都不用:
这将渲染 index.html,其中实现了 App.ts 中的功能。
完整的项目目录现在看起来像这样:
可以在 Visual Studio 中调试TypeScript文件:
不幸的是,因为 TypeScript .ts 文件在 Scripts 文件夹中,而不是 wwwroot/js 文件夹中,Chrome 在尝试设置断点时会显示这个错误:
可以通过在 Startup.cs 中添加这行来解决这个问题:
C# app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Scripts")), RequestPath = "/Scripts" });
现在 Chrome 可以找到 .ts 文件,可以在 Chrome 控制台中调试:
现在有一个工作示例:
向ASP.NET CoreWeb App 项目添加 TypeScript。
添加 require,以便可以引用 TypeScript 文件,并且不使用打包器。
提供默认文件,如 index.js。
将 TypeScript .ts 文件与编译的 .js 文件分开。
帮助 Chrome 的调试器找到 .ts 文件。