如何使用页面渲染,TypeScript和“ require”创建ASP.NET Core API项目
我创建了一个ASP.NETCoreWebAPI项目而不是ASP.NETCoreWebApp项目,因为我正在实现一个API,而不是Web应用程序。但是,我的API包含用于管理和测试API函数的默认页面,并且为了渲染这些页面和.js文件,我最终实现了一个控制器来返回.html和.js文件,这非常错误的方法。
在这篇简短的文章中,我将指导您如何创建一个ASP.NETCoreWebAPI项目,该项目还包括浏览器请求的呈现文件。这有一些细微差别!
为什么不使用Swagger?
Swagger非常适合生成用于测试端点的UI。本文的要点是,它说明了如何在需要以下内容的情况下添加网页:a)更易于使用且b)更复杂(例如与多个端点交互的管理页面)。
那为什么不使用ASP.NETCoreWebApp呢?
因为有时候您不需要Razor项目(VS2019中的一个选项),也不需要Model-View-Controller项目(VS2019中的另一个选项),并且您当然不需要Blazor(VS2019中的另一个选项)。您只需要具有一些内置页面的API,这些API的功能比Swagger还要多,但是由于您正在编写的API,因此不需要Razor,Blazor或MVC。(就个人而言,无论多么复杂,我都不认为应该使用这三个选项之一来“要求”使用网络应用程序,但这就是我。)
基本设定
因此,您已经创建了一个WebAPI项目:
并且您拥有出色的控制器:
[ApiController] [Route("[controller]")] public class SpiffyController : ControllerBase { [HttpGet] public object Get() { return Content("<b>Hello World</b>", "text/html"); } }12345678910复制代码类型:[html]
然后,按照以下出色的StackOverflow文章:
你这两行添加到Startup.cs的Configure方法:
app.UseDefaultFiles(); app.UseStaticFiles();12复制代码类型:[html]
UseDefaultFiles:设置默认页面为访问者提供了网站的起点。要从wwwroot提供默认页面而不提供完全限定的URI,请调用UseDefaultFiles方法-服务默认文档
UseStaticFiles:静态文件存储在项目的Web根目录中。默认目录为{contentroot}/wwwroot-ASP.NETCore中的静态文件
创建文件夹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>123456789101112131415复制代码类型:[html]
和goodbye.html看起来像这样:
<!DOCTYPE html><html><head> <meta charset="utf-8" /> <title></title></head><body> <h2>Goodbye!</h2></body></html>12345678910复制代码类型:[html]
至此,运行项目,我们看到:
和:
太酷了,我们已经渲染了index.html。
然后,您创建一个Scripts文件夹并添加一个TypeScript文件(请注意,我将该文件夹直接放在项目下):
这会给您以下消息:
因此,您必须将ECMAScript版本设置为至少2017年:
我不希望我的.js文件进入同一Scripts文件夹,我只希望它们位于wwwroot/js下:
因此,我转到项目属性并重定向Typescript编译器输出:
我看到那行得通:
但是index.html不知道如何加载将从TypeScript文件编译的.js文件。因此,我们将以下行添加到index.html:
<script src="/js/app.js"></script>1复制代码类型:[html]
现在,我的演示脚本文件如下所示:
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(); }); } }12345678910111213141516171819202122232425262728293031323334353637383940复制代码类型:[html]
现在单击按钮,我们看到:
和:
使用需求
开发人员将RequireJS描述为“JavaScript文件和模块加载器”。RequireJS加载普通的JavaScript文件以及更多定义的模块。它针对浏览器内使用进行了优化,包括在WebWorker中使用,但可以在其他JavaScript环境(例如Rhino和Node)中使用。它实现了异步模块API。使用像RequireJS这样的模块化脚本加载器将提高代码的速度和质量。另一方面,Webpack被详细描述为“JavaScript和朋友的捆绑程序”。-要求vs.webpack
上面是一个简单的示例,但是如果我的TypeScript类位于单独的文件中怎么办?我倾向于使用require而不是像Webpack这样的捆绑程序,如果出于其他原因(我认为)更容易配置(我认为),我已经习惯了。
不要这样做!您会得到各种不需要的东西。改为执行此操作:
npminstall--save@types/requirejs
只需安装d.ts文件即可:
AppConfig.ts在“脚本”文件夹中创建一个文件:
import { App } from "./App" require(['App'], () => { const appMain = new App(); appMain.run(); } );12345678复制代码类型:[html]
并重构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; }); } }123456789101112131415复制代码类型:[html]
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(); }); } }12345678910111213141516171819202122复制代码类型:[html]
运行WebAPI项目,使用启动浏览器的项目Debug属性选项作为控制器名称:
它将到达API端点,或者什么都没有:
将index.html使用中实现的功能进行渲染App.ts。
现在,完整的项目目录如下所示:
在VisualStudio或Chrome中调试
可以在VisualStudio中调试TypeScript文件:
不幸的是,由于TypeScript.ts文件位于Scripts文件夹中,而不是wwwrooot/jsChrome文件夹中,当您尝试设置断点时会显示以下错误:
我们可以通过在以下行添加此行来解决此问题Startup.cs:
app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider( Path.Combine(env.ContentRootPath, "Scripts")), RequestPath = "/Scripts" });123456复制代码类型:[html]
现在,Chrome可以找到.ts文件,您可以在Chrome控制台中进行调试:
结论
现在,我们有一个可行的示例:
将TypeScript添加到ASP.NETCoreWebApp项目中。
通过添加require,我们可以引用TypeScript文件,而无需使用捆绑程序。
提供默认文件,例如index.js
将TypeScript.ts文件与已编译的.js文件分开。
帮助Chrome的调试器查找.ts文件。
现在,我可以修复介绍中提到的gloriosky项目!