本篇分为以下几个部分:
- 1.Swagger的简单应用
- 2.Miniprofier的后台配置
- 3.跨域配置
- 4.在angular中显示Miniprofier
- 5.在vue中显示Miniprofier
- 6.在swagger中显示Miniprofier
Swagger的简单应用
1、首先新建一个Api项目
2、使用Nuget添加Swashbuckle.AspNetCore,我使用的版本为1.1.0(版本不一样,后面的配置可能不一样)
3、为了在swagger上显示注释,右键项目MiniprofilerApi,属性=>生成=>输出为XML文档文件
4、右键项目=>编辑.csproj添加如下代码,避免一些警告:
4、在Startup类的ConfigureServices方法和Configure方法中配置如下:
5、添加接口注释:
6、修改项目运行端口,访问路径,关闭ssl,右键项目=>属性=>调试,配置如下:
7、启动项目,界面效果如下:
Miniprofier的后台配置
1、安装MiniProfiler.AspNetCore.Mvc
2、在Startup类的ConfigureServices方法和Configure方法中配置如下:
3、运行程序:访问http://localhost:5000/mini-profiler-resources/results
跨域配置:
在angular中显示Miniprofier
1、在页面创建Miniprofier需要的js和css
import { Component } from \'@angular/core\';
import { HttpClient } from \'@angular/common/http\';
@Component({
selector: \'app-root\',
templateUrl: \'./app.component.html\',
styleUrls: [\'./app.component.css\']
})
export class AppComponent {
private src: string = \'http://localhost:5000/mini-profiler-resources/\';
private scriptSrc: string = `${this.src}includes.min.js`;
private cssSrc: string = `${this.src}includes.min.css`;
private id: string = \'mini-profiler\';
private dataPath: string = `${this.src}`;
private dataVersion: string = \'\';
private dataPosition: string = \'right\';
private dataChildren: boolean = true;
private dataMaxTraces: number = 35;
private dataAuthorized: boolean = true;
private dataStartHidden: string = \'false\';
private dataToggleShortcut: string = \'Alt+P\';
private dataTrivialMilliseconds: number = 35;
private dataTrivial: boolean = true;
private dataControls: boolean = true;
private dataCurrentId: string = \'\';
private dataIds: string = \'\';
private scriptAsync: boolean = true;
private innerHTML: string = \'\';
constructor(private http: HttpClient){
}
ngAfterViewInit(): void {
//添加Miniprofier的js
this.appendDivElement();
//添加Miniprofier的css
this.appendCssLink();
}
//请求后台接口
send(): void{
let serverurl: string = "http://localhost:5000//api/Values";
this.http.get(serverurl)
.toPromise()
.then(response => {
console.log()
}).catch(error => {
});
}
private appendDivElement(): void {
const body = document.body as HTMLDivElement;
const script = document.createElement(\'script\');
script.innerHTML = this.innerHTML;
script.src = this.scriptSrc;
script.setAttribute(\'data-version\', this.dataVersion);
script.setAttribute(\'data-path\', this.dataPath);
script.setAttribute(\'data-position\', this.dataPosition);
script.setAttribute(\'id\', this.id);
script.setAttribute(\'data-current-id\', this.dataCurrentId);
script.setAttribute(\'data-ids\', this.dataIds);
script.setAttribute(\'data-trivial\', this.dataTrivial.toString());
script.setAttribute(\'data-children\', this.dataChildren.toString());
script.setAttribute(\'data-max-traces\', this.dataMaxTraces.toString());
script.setAttribute(\'data-controls\', this.dataControls.toString());
script.setAttribute(\'data-authorized\', this.dataAuthorized.toString());
script.setAttribute(\'data-start-hidden\', this.dataStartHidden.toString());
script.setAttribute(\'data-toggle-shortcut\', this.dataToggleShortcut);
script.setAttribute(\'data-trivial-milliseconds\', this.dataTrivialMilliseconds.toString());
script.async = this.scriptAsync;
body.appendChild(script);
}
private appendCssLink(): void {
const body = document.body as HTMLDivElement;
const css = document.createElement(\'link\');
css.href = this.cssSrc;
css.rel = \'stylesheet\';
body.appendChild(css);
}
}
View Code
2、添加Http拦截器,动态显示监听结果
import { Injectable } from \'@angular/core\';
import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpResponse, HttpHeaders }
from \'@angular/common/http\';
import { Observable } from \'rxjs\';
import { tap } from \'rxjs/operators\';
declare var MiniProfiler: any;
@Injectable()
export class MiniProfilerInterceptor implements HttpInterceptor {
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
tap(evt => {
if (evt instanceof HttpResponse) {
if (evt && evt.headers) {
this.makeMiniProfilerRequests(evt.headers);
}
}
})
)
}
private makeMiniProfilerRequests(headers: HttpHeaders) {
const miniProfilerHeaders = headers.getAll(\'x-miniprofiler-ids\');
if (!miniProfilerHeaders) {
return;
}
miniProfilerHeaders.forEach(miniProfilerIdHeaderValue => {
const ids = JSON.parse(miniProfilerIdHeaderValue) as string[];
MiniProfiler.fetchResults(ids);
});
}
}
View Code
3、在app.module.ts中的配置
import { BrowserModule } from \'@angular/platform-browser\';
import { NgModule } from \'@angular/core\';
import { AppComponent } from \'./app.component\';
import { HttpClientModule, HTTP_INTERCEPTORS } from \'@angular/common/http\';
import { MiniProfilerInterceptor } from \'./mini-profiler-http\';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: MiniProfilerInterceptor, multi: true
}],
bootstrap: [AppComponent]
})
export class AppModule { }
View Code
4、在app.component.html页面添加一个请求按钮
<div style="text-align:center;margin:100px auto">
<button (click)="send()">click</button>
</div>
View Code
5、页面效果
在vue中显示Miniprofier
和在angular中的操作步骤一致,下面放主要代码:
1、App.vue 主组件
<template>
<div id="app">
<MiniProfiler
:scriptSrc="scriptSrc"
:dataPath="src"
:cssSrc="cssSrc"/>
<Dummy />
</div>
</template>
<script lang="ts">
import { Component, Vue } from \'vue-property-decorator\';
import MiniProfiler from \'./components/MiniProfiler.vue\';
import Dummy from \'./components/Dummy.vue\';
import axios from \'axios\';
@Component({
components: {
MiniProfiler,
Dummy,
},
})
export default class App extends Vue {
private src: string = \'http://localhost:5000/mini-profiler-resources/\';
private scriptSrc: string = `${this.src}includes.min.js`;
private cssSrc: string = `${this.src}includes.min.css`;
}
</script>
<style>
#app {
font-family: \'Avenir\', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
View Code
2、Dummy.vue 子组件用于发送接口请求
<template>
<button type="button" @click="getProfiler">Click Me!</button>
</template>
<script lang="ts">
import { Component, Vue } from \'vue-property-decorator\';
import axios from \'axios\';
@Component
export default class Dummy extends Vue {
private getProfiler() {
axios.get(\'http://localhost:5000/api/values\');
}
}
</script>
View Code
3、MiniProfiler.vue 子组件用于添加拦截器和创建Miniprofier需要的js和css
<template>
</template>
<script lang="ts">
import { Component, Prop, Vue } from \'vue-property-decorator\';
import axios from \'axios\';
@Component
export default class MiniProfiler extends Vue {
@Prop({ default: \'mini-profiler\' }) private id!: string;
@Prop() private scriptSrc!: string;
@Prop() private cssSrc!: string;
@Prop() private dataPath!: string;
@Prop({ default: \'\' }) private dataVersion!: string;
@Prop({ default: \'right\' }) private dataPosition!: string;
@Prop({ default: true }) private dataChildren!: boolean;
@Prop({ default: 35 }) private dataMaxTraces!: number;
@Prop({ default: true }) private dataAuthorized!: boolean;
@Prop({ default: false }) private dataStartHidden!: string;
@Prop({ default: \'Alt+P\' }) private dataToggleShortcut!: string;
@Prop({ default: 35 }) private dataTrivialMilliseconds!: number;
@Prop({ default: true }) private dataTrivial!: boolean;
@Prop({ default: true }) private dataControls!: boolean;
@Prop({ default: \'\' }) private dataCurrentId!: string;
@Prop({ default: \'\' }) private dataIds!: string;
@Prop({ default: true }) private scriptAsync!: boolean;
@Prop({ default: \'\' }) private innerHTML!: string;
private created(): void {
this.axiosSetUp();
this.appendDivElement();
this.appendCssLink();
}
private axiosSetUp(): void {
const key: string = \'MiniProfiler\';
axios.interceptors.response.use(function success(config) {
const miniProfiler: any = (window as any)[key];
const miniProfilerIds = JSON.parse(config.headers[\'x-miniprofiler-ids\']) as string[];
miniProfiler.fetchResults(miniProfilerIds);
return config;
}, function bug(error) {
return Promise.reject(error);
});
}
private appendDivElement(): void {
const body = document.body as HTMLDivElement;
const script = document.createElement(\'script\');
script.innerHTML = this.innerHTML;
script.src = this.scriptSrc;
script.setAttribute(\'data-version\', this.dataVersion);
script.setAttribute(\'data-path\', this.dataPath);
script.setAttribute(\'data-position\', this.dataPosition);
script.setAttribute(\'id\', this.id);
script.setAttribute(\'data-current-id\', this.dataCurrentId);
script.setAttribute(\'data-ids\', this.dataIds);
script.setAttribute(\'data-trivial\', this.dataTrivial.toString());
script.setAttribute(\'data-children\', this.dataChildren.toString());
script.setAttribute(\'data-max-traces\', this.dataMaxTraces.toString());
script.setAttribute(\'data-controls\', this.dataControls.toString());
script.setAttribute(\'data-authorized\', this.dataAuthorized.toString());
script.setAttribute(\'data-start-hidden\', this.dataStartHidden.toString());
script.setAttribute(\'data-toggle-shortcut\', this.dataToggleShortcut);
script.setAttribute(\'data-trivial-milliseconds\', this.dataTrivialMilliseconds.toString());
script.async = this.scriptAsync;
body.appendChild(script);
}
private appendCssLink(): void {
const body = document.body as HTMLDivElement;
const css = document.createElement(\'link\');
css.href = this.cssSrc;
css.rel = \'stylesheet\';
body.appendChild(css);
}
}
</script>
View Code
4、界面效果
在swagger中显示Miniprofier
1、将性能分析监测信息从后端发送到Swagger界面。
首先给swagger添加拦截器
拦截器代码如下:
using Microsoft.AspNetCore.Http;
using StackExchange.Profiling;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace MiniprofilerApi.MiniProfierHelp
{
public class InjectMiniProfiler : IDocumentFilter
{
private readonly IHttpContextAccessor _httpContext;
public InjectMiniProfiler(IHttpContextAccessor httpContext)
{
_httpContext = httpContext;
}
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
{
swaggerDoc.Info.Contact = new Contact()
{
Name = MiniProfiler.Current.RenderIncludes(_httpContext.HttpContext).ToString()
};
}
}
}
View Code
此时运行项目,swagger界面显示如下:
2、通过js解析MIniprofier的脚本,代码如下:
(function () {
window.angular=true;
//Create a mini profiler script tag with the right properites
var MiniProfiler = $(\'#api_info > div:nth-child(3)\').text();
const attributes = [
\'src\', \'data-version\', \'data-path\', \'data-current-id\', \'data-ids\',
\'data-position\', \'data-trivial-milliseconds\', \'data-max-traces\',
\'data-authorized\', \'data-toggle-shortcut\', \'data-ignored-duplicate-execute-types\'
];
var GetAttr = function (input, attributeName) {
const myRegexp = attributeName + \'="(.*?)"\';
const re = new RegExp(myRegexp, "g");
const match = re.exec(input);
return match[1];
}
var s = document.createElement("script");
s.type = "text/javascript";
s.id = "mini-profiler";
s.async = true;
for (var i = 0; i < attributes.length; i++) {
var element = attributes[i];
s.setAttribute(element, GetAttr(MiniProfiler, element));
}
document.body.appendChild(s);
// Remove injected tag from view
$(\'#api_info > div:nth-child(3)\').text(\'\');
})();
View Code
配置swagger执行js:
3、界面效果如下:
全部源代码见:https://github.com/zrkcode/Miniprofiler.git
监听EF执行的Sql语句或更多NetCore+Miniprofiler相关配置见:https://miniprofiler.com/dotnet/AspDotNetCore
更多Swagger+NetCore配置见:https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-2.2&tabs=visual-studio