增加功能:增加swagger webapi文档
This commit is contained in:
parent
e66f5e0fdf
commit
8a38d58aef
|
@ -346,6 +346,7 @@ ASALocalRun/
|
|||
[Kk]eys/
|
||||
lib/
|
||||
*.db
|
||||
Bootstrap.Admin.xml
|
||||
|
||||
###### -- Custom Ignore Section, Make sure all files you add to the git repo are below this line -- ######
|
||||
|
||||
|
|
|
@ -7,12 +7,17 @@
|
|||
<MvcRazorCompileOnPublish>true</MvcRazorCompileOnPublish>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DocumentationFile>Z:\src\Longbow\BootstrapAdmin\Bootstrap.Admin\Bootstrap.Admin.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Bootstrap.Security.Mvc" Version="1.0.1" />
|
||||
<PackageReference Include="Longbow.Logging" Version="1.0.2" />
|
||||
<PackageReference Include="Longbow.Web" Version="1.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -141,13 +141,5 @@ namespace Bootstrap.Admin.Controllers
|
|||
{
|
||||
return View(new NavigatorBarModel(this));
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ActionResult Api()
|
||||
{
|
||||
return View(new NavigatorBarModel(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Swashbuckle.AspNetCore.Swagger;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Operation = Swashbuckle.AspNetCore.Swagger.Operation;
|
||||
|
||||
namespace Bootstrap.Admin
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class HttpHeaderOperation : IOperationFilter
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="operation"></param>
|
||||
/// <param name="context"></param>
|
||||
public void Apply(Operation operation, OperationFilterContext context)
|
||||
{
|
||||
if (operation.Parameters == null) operation.Parameters = new List<IParameter>();
|
||||
|
||||
if (context.MethodInfo.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Count() == 0)
|
||||
{
|
||||
operation.Parameters.Add(new NonBodyParameter()
|
||||
{
|
||||
Name = "Authorization", //添加Authorization头部参数
|
||||
In = "header",
|
||||
Type = "string",
|
||||
Required = false
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,22 +18,35 @@ using Microsoft.Extensions.Configuration;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using Swashbuckle.AspNetCore.Swagger;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Bootstrap.Admin
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class Startup
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="configuration"></param>
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.Configure<CookiePolicyOptions>(options =>
|
||||
|
@ -65,9 +78,26 @@ namespace Bootstrap.Admin
|
|||
JsonConvert.DefaultSettings = () => options.SerializerSettings;
|
||||
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
|
||||
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options => options.Cookie.Path = "/");
|
||||
}
|
||||
services.AddSwaggerGen(options =>
|
||||
{
|
||||
options.SwaggerDoc("v1", new Info
|
||||
{
|
||||
Version = "v1",
|
||||
Title = "BootstrapAdmin API"
|
||||
});
|
||||
|
||||
//Set the comments path for the swagger json and ui.
|
||||
var xmlPath = Path.Combine(AppContext.BaseDirectory, "Bootstrap.Admin.xml");
|
||||
options.IncludeXmlComments(xmlPath);
|
||||
options.OperationFilter<HttpHeaderOperation>(); // 添加httpHeader参数
|
||||
});
|
||||
}
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <param name="env"></param>
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
|
@ -93,6 +123,11 @@ namespace Bootstrap.Admin
|
|||
name: "default",
|
||||
template: "{controller=Home}/{action=Index}/{id?}");
|
||||
});
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(c =>
|
||||
{
|
||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "BootstrapAdmin API V1");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
@model NavigatorBarModel
|
||||
@{
|
||||
ViewBag.Title = "Api 文档";
|
||||
}
|
||||
@section javascript {
|
||||
<script src="~/js/apidoc.js" asp-append-version="true"></script>
|
||||
}
|
||||
@section css {
|
||||
<link href="~/css/api.css" rel="stylesheet" asp-append-version="true" />
|
||||
}
|
||||
<section>
|
||||
<div><h3>接口返回值定义</h3></div>
|
||||
<div><label class="control-label">布尔值:</label><div>成功返回True,失败返回False</div></div>
|
||||
<div><label class="control-label">对象:</label><div>Json字符串</div></div>
|
||||
</section>
|
||||
<section>
|
||||
<div><h3>接口请求定义</h3></div>
|
||||
<div><label class="control-label">内容类型</label><div>Content-Type:application/json; charset=utf-8</div></div>
|
||||
<div><label class="control-label">授权Token</label><div>Token:362a4733-341a-464d-ab12-e01554338839</div></div>
|
||||
</section>
|
|
@ -1,35 +0,0 @@
|
|||
h3 {
|
||||
margin-top: 0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.btn {
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.control-label {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.main-content > section:not(:first-child) {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.main-content > section > div {
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.main-content > section > div > div {
|
||||
display: inline-block;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.test {
|
||||
display: none;
|
||||
padding: 10px 0 0 0;
|
||||
color: #5cb85c;
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
$(function () {
|
||||
var ajax = function (options) {
|
||||
options = $.extend({
|
||||
test: false,
|
||||
div: undefined,
|
||||
anonymous: false,
|
||||
title: '未录入',
|
||||
url: '',
|
||||
method: 'get',
|
||||
data: '',
|
||||
headers: {},
|
||||
success: function (result) {
|
||||
},
|
||||
error: function (textStatus, errorThrown) {
|
||||
}
|
||||
}, options);
|
||||
if (options.url == '') {
|
||||
document.writeln("请求地址丢失!");
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
url: options.url,
|
||||
data: options.data,
|
||||
type: options.method,
|
||||
headers: options.headers,
|
||||
success: function (result) {
|
||||
if (!options.test) {
|
||||
var $body = $('#main-content');
|
||||
$body.append('<section></section>');
|
||||
var $section = $body.find('section').last();
|
||||
$section.append($.format('<h3>{0}</h3>', options.title));
|
||||
$section.append($.format('<div><label class="control-label">请求地址</label><div>{0}</div></div>', options.url));
|
||||
$section.append($.format('<div><label class="control-label">允许匿名</label><div>{0}</div></div>', options.anonymous ? "允许" : "不允许"));
|
||||
$section.append($.format('<div><label class="control-label">Headers</label><div>{0}</div></div>', JSON.stringify(options.headers)));
|
||||
$section.append($.format('<div><label class="control-label">HTTP方法</label><div>{0}</div></div>', options.method));
|
||||
$section.append($.format('<div><label class="control-label">传递参数</label><div>{0}</div></div>', JSON.stringify(options.data)));
|
||||
$section.append($.format('<div><label class="control-label">返回值</label><div>{0}</div></div>', JSON.stringify(result)));
|
||||
$section.append('<div><label class="control-label">试一试</label></div>');
|
||||
$section.append($.format('<div class="input-group"><input type="text" class="form-control" value=\'{1}\' data-val=\'{0}\' /><span class="input-group-btn"><button class="btn btn-default btn-success" type="button">试一试</button></span></div>', JSON.stringify(options), JSON.stringify(options.data)));
|
||||
$section.append('<div class="test"></div>')
|
||||
options.success(result);
|
||||
}
|
||||
else {
|
||||
if (options.div) {
|
||||
options.div.html($.format('<label class="control-label">测试结果:</label><div>{0}</div>', JSON.stringify(result))).show();
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function (XMLHttpRequest, textStatus, errorThrown) {
|
||||
var $body = $('body');
|
||||
var $section = $body.find('section').last();
|
||||
$section.append($.format('<div><label class="control-label">错误参数</label><div>textStatus:{0}</div><div>', textStatus));
|
||||
$section.append($.format('<div><label class="control-label">错误参数</label><div>errorThrown:{0}</div><div>', errorThrown));
|
||||
options.error(textStatus, errorThrown);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('body').on('click', 'button', function () {
|
||||
var $input = $(this).parent().prev();
|
||||
var options = $.extend(JSON.parse($input.attr('data-val')), { data: JSON.parse($input.val()) }, { test: true, div: $(this).parent().parent().next() });
|
||||
ajax(options);
|
||||
});
|
||||
|
||||
// 接口调用
|
||||
ajax({
|
||||
title: '用户登陆调用接口',
|
||||
anonymous: true,
|
||||
url: '../api/login', method: 'POST', data: { userName: 'Test', password: '1' }, success: function (result) {
|
||||
var token = result.Token;
|
||||
ajax({
|
||||
title: '用户登陆信息接口', url: '../api/login', headers: { Token: token },
|
||||
method: 'GET'
|
||||
});
|
||||
ajax({
|
||||
title: '指定用户信息接口', url: '../api/Users', headers: { Token: token },
|
||||
method: 'GET', data: { userName: "Test" }
|
||||
});
|
||||
ajax({
|
||||
title: '检查当前用户名是否可用接口', url: '../api/Users', headers: { Token: token },
|
||||
method: 'PUT', data: { UserName: "101", UserStatus: 9 }
|
||||
});
|
||||
ajax({
|
||||
title: '更改用户显示名称接口', url: '../api/Users', headers: { Token: token },
|
||||
method: 'PUT', data: { UserName: "101", UserStatus: 1, DisplayName: "1010" }
|
||||
});
|
||||
ajax({
|
||||
title: '更改用户密码接口', url: '../api/Users', headers: { Token: token },
|
||||
method: 'PUT', data: { UserName: "101", UserStatus: 2, Password: "1", NewPassword: "2" }
|
||||
});
|
||||
ajax({
|
||||
title: '新建用户接口', url: '../api/Users', headers: { Token: token },
|
||||
method: 'POST', data: { ID: 0, UserName: "102", Password: "1", DisplayName: "102" }
|
||||
});
|
||||
ajax({
|
||||
title: '更新用户接口', url: '../api/Users', headers: { Token: token },
|
||||
method: 'POST', data: { ID: 21, UserName: "102", Password: "1", DisplayName: "102" }
|
||||
});
|
||||
ajax({
|
||||
title: '删除用户接口', url: '../api/Users', headers: { Token: token },
|
||||
method: 'DELETE', data: { "": "50,51" }
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
|
@ -48,7 +48,7 @@ INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [C
|
|||
INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (14, 0, N'程序异常', 140, N'fa fa-cubes', N'~/Admin/Exceptions', N'0')
|
||||
INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (16, 0, N'工具集合', 160, N'fa fa-gavel', N'#', N'0')
|
||||
INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (17, 16, N'客户端测试', 10, N'fa fa-wrench', N'~/Admin/Mobile', N'0')
|
||||
INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (18, 16, N'API文档', 10, N'fa fa-wrench', N'~/Admin/Api', N'0')
|
||||
INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (18, 16, N'API文档', 10, N'fa fa-wrench', N'~/swagger', N'0')
|
||||
INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (19, 16, N'图标集', 10, N'fa fa-dashboard', N'~/Admin/FAIcon', N'0')
|
||||
SET IDENTITY_INSERT [dbo].[Navigations] OFF
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Ca
|
|||
INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (14, 0, '程序异常', 140, 'fa fa-cubes', '~/Admin/Exceptions', '0');
|
||||
INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (16, 0, '工具集合', 160, 'fa fa-gavel', '#', '0');
|
||||
INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (17, 16, '客户端测试', 10, 'fa fa-wrench', '~/Admin/Mobile', '0');
|
||||
INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (18, 16, 'API文档', 10, 'fa fa-wrench', '~/Admin/Api', '0');
|
||||
INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (18, 16, 'API文档', 10, 'fa fa-wrench', '~/swagger', '0');
|
||||
INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (19, 16, '图标集', 10, 'fa fa-dashboard', '~/Admin/FAIco', '0');
|
||||
|
||||
DELETE FROM GROUPS WHERE ID = 1;
|
||||
|
|
Loading…
Reference in New Issue