以目前流行的前后端分离模式来看,ABP框架更适用于后端开发,而对API接口的管理就成了一项必不可少的功能。
1.安装Swashbuckle.AspNetCore
使用Nuget管理器在分布式服务层和展现层AbpDemo.Web安装Swashbuckle.AspNetCore程序包,包含Swashbuckle.AspNetCore.Swagger、Swashbuckle.AspNetCore.SwaggerGen、Swashbuckle.AspNetCore.SwaggerUI三项。
2.配置Swagger选项
对于Swagger的配置主要是在AbpDemo.Web项目中的Startup启动类。
在ConfigureServices方法中添加配置:
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1",
new OpenApiInfo {
Title = "AbpDemo",
Version = "v1.0",
Description="",
TermsOfService=new Uri("https://github.com/ludewig"),
Contact = new OpenApiContact { Name="ludewig",Email="panshuairg@hotmail.com",Url=new Uri("https://github.com/ludewig") }
});
options.DocInclusionPredicate((docName, description) => true);
});
在Configure方法中添加配置:
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Demo API v1");
});
此时启动项目,输入默认地址http://xxx:xx/swagger/index.html就可以访问swagger的API接口管理界面。
3.添加注释信息
但是现在界面包含的信息还比较少,在代码中的注释还没加进来。
打开应用层AbpDemo.Application的属性界面,选择“生成”选项,勾选“XML文档文件”,这样再次编译项目时,代码注释会以XML文件形式生成到AbpDemo.Web项目中。
同时还要在AbpDemo.Web项目中修改Startup启动类以便于Swagger能够读取到生成的XML文件。
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1",
new OpenApiInfo {
Title = "AbpDemo",
Version = "v1.0",
Description="",
TermsOfService=new Uri("https://github.com/ludewig"),
Contact = new OpenApiContact { Name="ludewig",Email="panshuairg@hotmail.com",Url=new Uri("https://github.com/ludewig") }
});
options.DocInclusionPredicate((docName, description) => true);
var filePath = Path.Combine(AppContext.BaseDirectory, "AbpDemo.Application.xml");
options.IncludeXmlComments(filePath);
});
4.使用API接口管理界面
经过上面的配置步骤后再次启动项目,可以查看到swagger的界面了。
通过swagger的API管理界面,可以对API接口的输入输出数据结构进行查看和测试。
5.ABP框架中Swagger的其他配置
5.1关于CSRF
按照前面的步骤完成对Swagger的配置后,启动项目,测试接口却发现报错了。这其实是ABP框架本身的机制导致的。ABP框架默认是开启CSRF保护的,也就是启动了对Cross-Site Request Forgery (CSRF) 跨站请求伪造的防护机制,客户端必须携带可信的token令牌才能访问API接口。解决这个问题有两种方式:
- 关闭CSRF保护
在Startup启动类的ConfigureServices方法中注释如下代码
services.AddControllersWithViews(options =>
{
//注释下列代码关闭CSRF保护
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
})
- 添加CSRF token
添加用于写入token信息的脚本文件,设置文件属性为“嵌入的资源”并注入到项目中。在Startup启动类中注入脚本文件。
app.UseSwaggerUI(options =>
{
//...
options.InjectJavascript("ui/abp.js");//注入脚本文件
});
脚本文件内容如下:
var getCookieValue = function(key) {
var equalities = document.cookie.split('; ');
for (var i = 0; i < equalities.length; i++) {
if (!equalities[i]) {
continue;
}
var splitted = equalities[i].split('=');
if (splitted.length !== 2) {
continue;
}
if (decodeURIComponent(splitted[0]) === key) {
return decodeURIComponent(splitted[1] || '');
}
}
return null;
};
var csrfCookie = getCookieValue("XSRF-TOKEN");
var csrfCookieAuth = new SwaggerClient.ApiKeyAuthorization("X-XSRF-TOKEN", csrfCookie, "header");
swaggerUi.api.clientAuthorizations.add("X-XSRF-TOKEN", csrfCookieAuth);
5.2添加自定义首页
路径http://xxxx:xx/swagger/index.html对应的首页是系统默认的API管理界面,内嵌在Swashbuckle.AspNetCore程序包中,页面包含内容如下:
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>%(DocumentTitle)</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
<style>
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
box-sizing: inherit;
}
body
{
margin:0;
background: #fafafa;
}
</style>
%(HeadContent)
</head>
<body>
<div id="swagger-ui"></div>
<!-- Workaround for https://github.com/swagger-api/swagger-editor/issues/1371 -->
<script>
if (window.navigator.userAgent.indexOf("Edge") > -1) {
console.log("Removing native Edge fetch in favor of swagger-ui's polyfill")
window.fetch = undefined;
}
</script>
<script src="./swagger-ui-bundle.js"> </script>
<script src="./swagger-ui-standalone-preset.js"> </script>
<script>
window.onload = function() {
var configObject = JSON.parse('%(ConfigObject)');
var oauthConfigObject = JSON.parse('%(OAuthConfigObject)');
// If validatorUrl is not explicitly provided, disable the feature by setting to null
if (!configObject.hasOwnProperty("validatorUrl"))
configObject.validatorUrl = null
// If oauth2RedirectUrl isn't specified, use the built-in default
if (!configObject.hasOwnProperty("oauth2RedirectUrl"))
configObject.oauth2RedirectUrl = window.location.href.replace("index.html", "oauth2-redirect.html").split('#')[0];
// Apply mandatory parameters
configObject.dom_id = "#swagger-ui";
configObject.presets = [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset];
configObject.layout = "StandaloneLayout";
// Begin Swagger UI call region
const ui = SwaggerUIBundle(configObject);
ui.initOAuth(oauthConfigObject);
// End Swagger UI call region
window.ui = ui
}
</script>
</body>
</html>
可以看到默认的首页已经提供了配置对象ConfigObject、验证授权配置对象OAuthConfigObject、验证地址ValidatorUrl、验证授权重定向地址OAuth2RedirectUrl。
如果觉得官方提供的首页在样式或功能上不满足要求,可以创建自定义的首页添加到wwwroot目录下,并设置文件属性为“嵌入的资源”。然后在Startup启动类的Configure方法中设置自定义的首页。
app.UseSwaggerUI(options =>
{
//...
options.IndexStream = () => Assembly.GetExecutingAssembly().GetManifestResourceStream("AbpDemo.Web.wwwroot.swagger.ui.index.html");
//...
});
更多详细功能可以参考swagger官方文档