如何创建具有页面渲染、TypeScript 和 "require" 的 ASP.NET Core API 项目





5.00/5 (2投票s)
设置一个 ASP.NET Core API 项目,并使用 TypeScript 和 "require" 来渲染页面以及在浏览器中加载 JavaScript 文件。
目录
引言
在我最近的文章《自适应分层知识管理》(第一部分和第二部分)(好吧,这是无耻的自我宣传),我创建了一个 ASP.NET Core Web API 项目,而不是 ASP.NET Core Web App 项目,因为我正在实现一个 API,而不是一个 Web 应用程序。尽管如此,我的 API 包含用于管理和测试 API 功能的默认页面,并且为了渲染这些页面和 .js 文件,我最终实现了一个控制器来返回 .html 和 .js 文件,这是一种非常错误的做法。
在这篇简短的文章中,我将引导您完成如何创建一个 ASP.NET Core Web API 项目,该项目还包括渲染浏览器请求的文件。这里有一些细微差别!
为什么不使用 Swagger?
Swagger 非常适合为端点测试生成 UI。本文的重点是演示如何添加 Web 页面,以满足以下情况:a) 更用户友好,b) 更复杂,例如需要与多个端点交互的管理页面。
为什么不使用 ASP.NET Core Web App?
因为有时您不需要 Razor 项目(VS2019 中的一个选项),也不想要 Model-View-Controller 项目(VS2019 中的另一个选项),更不需要 Blazor(VS2019 中的又一个选项)。您只想拥有一个 API,其中包含一些内置页面,这些页面比 Swagger 功能更强大,但由于您编写的是 API,因此不需要 Razor、Blazor 或 MVC。(就我个人而言,我认为无论复杂程度如何,Web 应用程序都不应该“要求”使用这三个选项之一,但那是我的看法。)
基本设置
所以您已经创建了一个 Web API 项目
并且您有了漂亮的控制器
[ApiController]
[Route("[controller]")]
public class SpiffyController : ControllerBase
{
[HttpGet]
public object Get()
{
return Content("<b>Hello World</b>", "text/html");
}
}
然后,按照这个优秀的 StackOverflow 帖子
您在 Configure
方法的 Startup.cs 中添加这两行
app.UseDefaultFiles();
app.UseStaticFiles();
UseDefaultFiles
:设置默认页面为网站提供一个起点。要从 wwwroot 提供默认页面而不使用完全限定的 URI,请调用 UseDefaultFiles 方法-- 提供默认文档UseStaticFiles
:静态文件存储在项目 Web 根目录中。默认目录是 {content root}/wwwroot -- ASP.NET Core 中的静态文件
创建 wwwroot 文件夹并在其中放入 index.html(以及您在顶层想要的任何其他文件)
本文中我的 index.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 文件如下所示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<h2>Goodbye!</h2>
</body>
</html>
此时,运行项目,我们看到
和
太棒了,我们渲染了 index.html。
然后,您创建一个 Scripts 文件夹并添加一个 TypeScript 文件(请注意,我将该文件夹直接放在项目下)
这会给您带来这个消息
所以您这样做,并将 ECMAScript 版本设置为至少 2017
我不想让我的 .js 文件进入同一个 Scripts 文件夹,我只希望它们位于 wwwroot/js 下
因此,我转到项目属性并将 TypeScript 编译器输出重定向
我看到它起作用了
但是 index.html 不知道如何加载将从 TypeScript 文件编译的 .js 文件。因此,我们在 index.html 中添加了这行
<script src="/js/app.js"></script>
现在,我的演示脚本文件如下所示
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;
});
}
}
class XhrService {
public static async get(url: string, ): Promise<XMLHttpRequest> {
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();
});
}
}
现在,单击按钮,我们看到
和
使用 Require
开发者将 RequireJS 描述为“JavaScript 文件和模块加载器”。RequireJS 加载纯 JavaScript 文件以及更定义的模块。它针对浏览器使用进行了优化,包括在 Web Worker 中,但它也可以在其他 JavaScript 环境中使用,如 Rhino 和 Node。它实现了异步模块 API。使用模块化脚本加载器,如 RequireJS,将提高代码的速度和质量。另一方面,Webpack 被详细描述为“JavaScript 及其相关文件的打包器”。 -- require vs. webpack
上面的例子很简单,但如果我的 TypeScript 类在单独的文件中怎么办?我倾向于更喜欢使用 require
而不是像 Webpack 这样的打包器,即使只是因为它更容易配置(在我看来)并且我习惯了它。
不要这样做!您将获得所有不需要的东西。这样做
npm install --save @types/requirejs
这仅安装了 require
的 d.ts 文件
在 Scripts 文件夹中创建一个 AppConfig.ts 文件
import { App } from "./App"
require(['App'],
() => {
const appMain = new App();
appMain.run();
}
);
并将 app.ts 重构为两个文件
App.ts
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
export class XhrService {
public static async get(url: string,): Promise<XMLHttpRequest> {
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 或 Chrome 中进行调试
TypeScript 文件可以在 Visual Studio 中进行调试
不幸的是,因为 TypeScript .ts 文件位于 Scripts 文件夹中,而不是 wwwrooot/js 文件夹中,当您尝试设置断点时,Chrome 会显示此错误
我们可以通过在 Startup.cs 中 *添加* 此行来解决此问题
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.ContentRootPath, "Scripts")),
RequestPath = "/Scripts"
});
现在 Chrome 可以找到 .ts 文件,您可以在 Chrome 控制台中进行调试
结论
我们现在有一个工作示例
- 将 TypeScript 添加到 ASP.NET Core Web App 项目。
- 添加
require
,以便我们可以引用 TypeScript 文件,并且无需使用打包器。 - 提供默认文件,例如 index.js
- 将 TypeScript .ts 文件与已编译的 .js 文件分开。
- 帮助 Chrome 的调试器找到 .ts 文件。
现在,我可以去修复我在介绍中提到的那个我辉煌的项目了!
历史
- 2021 年 4 月 10 日:初始版本