ABP+AdminLTE+Bootstrap Table權(quán)限管理系統(tǒng)一期
Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMS
前往博客園總目錄:ABP+AdminLTE+Bootstrap Table權(quán)限管理系統(tǒng)一期
一,Web API
ABP的動(dòng)態(tài)WebApi實(shí)現(xiàn)了直接對(duì)服務(wù)層的調(diào)用(其實(shí)病沒有跨過ApiController
,只是將ApiControlle
r公共化击罪,對(duì)于這一點(diǎn)的處理類似于MVC沿量,對(duì)服務(wù)端的 調(diào)用沒有跨過HttpHandler
一樣)辩块,這樣不僅減少了ApiController
的開發(fā)趴久,也更能體現(xiàn)驅(qū)動(dòng)領(lǐng)域設(shè)計(jì)的層結(jié)構(gòu)融蹂。
WEBAPI同樣集成自AbpController
, 我們看到AbpController
封裝了很多方法,集成了很多東西,繼承自System.Web.Mvc.Controller
,abp包含一下功能
1. 本地化
2. 異常處理
3. 對(duì)返回的JsonResult進(jìn)行包裝
4. 審計(jì)日志
5. 權(quán)限認(rèn)證([AbpMvcAuthorize]特性)
6. 工作單元(默認(rèn)未開啟,通過添加[UnitOfWork]開啟)
7. 錯(cuò)誤機(jī)制的響應(yīng).
這里就不細(xì)講,會(huì)在第五章詳講.但是又多了結(jié)果緩存,ABP為WebAPI請(qǐng)求的響應(yīng)添加緩存控制header(no-cache,no-store)
廓潜。因此阱佛,它阻止瀏覽器緩存相應(yīng),甚至GET請(qǐng)求也會(huì)被阻止緩存耍缴±危可以在配置里禁用此功能。
HTTP特性:一般包含HttpGet
防嗡、HttepPost
,HttpDelete
,HttpPut
等特性.一般HttpGet
变汪、HttepPost
,HttpDelete
比較常用.
api路由:可以重定義路由,在外部調(diào)用的時(shí)候.如[Route("api/friends/{friendId}")]
二, SwaggerUI
前面已經(jīng)建好服務(wù)層的接口了,可以通過接口直接去請(qǐng)求數(shù)據(jù)庫.平時(shí)我們請(qǐng)求數(shù)據(jù)都是在控制器里面去注入接口,然后調(diào)用方法,其實(shí)還有一種更好的實(shí)現(xiàn),我們可以不通過控制器,直接在頁面js請(qǐng)求的時(shí)候直接請(qǐng)求服務(wù)接口,ABP集成了Swagger Api.而且這個(gè)界面非常的nice.
- swagger-ui 項(xiàng)目地址:https://github.com/swagger-api/swagger-ui
- swagger-ui 官網(wǎng)地址:https://swagger.io/swagger-ui/
- 選擇WEBAPI添加nuget包,輸入"Swagger ",會(huì)出來智能的出來Swashbuckle和Swagger.Net.UI兩個(gè)包,引用其中一個(gè)就可以了,但是不能同時(shí)引用,否則生成的時(shí)候回會(huì)報(bào)錯(cuò)路由錯(cuò)誤.
- 引用到項(xiàng)目中之后,打開WebApiModule.cs,創(chuàng)建ConfigureSwaggerUi方法
- 然后在重寫的然Initialize()中對(duì)他進(jìn)行調(diào)用。
運(yùn)行項(xiàng)目,依然是WEB為啟動(dòng)項(xiàng)目,不需要設(shè)置WEBAPI啟動(dòng),就看到了以下界面.
至此,ABP的WEBAPI基本已經(jīng)事項(xiàng),但是還是存在以下問題.
- 界面的說明都是英文的需要進(jìn)行漢化,既然是接口文檔,前端人員在用的時(shí)候需要文字說明.
- 控制器沒有描述
- 接口過多每次生成速度比較慢
- 關(guān)于調(diào)用接口會(huì)不會(huì)暴露,
- 移動(dòng)端調(diào)用方式
- 調(diào)用如何確保安全
- 身份驗(yàn)證的方式
首先我們先在application生成xml文檔勾選上
然后修改一下ConfigureSwaggerUi方法
在修改一下DTO注釋驗(yàn)證,當(dāng)然我們已經(jīng)加上驗(yàn)證了
運(yùn)行一下,效果出來了.
修改提示語言為中文,一個(gè) 是注入JavaScript文件蚁趁,一個(gè)是輸入css文件裙盾。所以如果這里可以對(duì)我們的SwaggerUI界面進(jìn)行自定義修改的。
- 需要將js文件路徑注入到SwaggerUI中他嫡。
2. 寫入js文件
然而你在運(yùn)行的發(fā)現(xiàn)報(bào)錯(cuò),其實(shí)這里有兩個(gè)套路,自古深情留不起,唯有套路得人心,謹(jǐn)記啊,所以看以下三點(diǎn):
3. 我們來看WEBAPI路徑
4. js文件設(shè)置嵌入的資源
- 還有一種是在webapimodule中關(guān)閉 CSRF功能
或者js里面寫入以下帶代碼.
做完以上四步,我們?cè)賮砜闯晒?
以上就是Swagger ui 運(yùn)用及部分漢化.
其他終端在調(diào)用接口是的時(shí)候的身份驗(yàn)證方式,第一種就是cookie認(rèn)證方式番官;
第二種就是token認(rèn)證方式:在訪問webapi之前,先要向目標(biāo)系統(tǒng)申請(qǐng)令牌(token)钢属,申請(qǐng)到令牌后徘熔,再使用令牌訪問webapi。Abp默認(rèn)提供了這種方式淆党;
第三種是基于OAuth2.0的token認(rèn)證方式:OAuth2.0認(rèn)證方式彌補(bǔ)了Abp自帶token認(rèn)證的短板酷师,即無法進(jìn)行token刷新,這些東西其實(shí)我也還沒有完全搞懂,會(huì)在后續(xù)學(xué)習(xí)的過程中加上。
/// <summary>
/// 中文轉(zhuǎn)換
/// </summary>
var SwaggerTranslator = (function () {
//定時(shí)執(zhí)行檢測(cè)是否轉(zhuǎn)換成中文,最多執(zhí)行500次 即500*50/1000=25s
var iexcute = 0,
//中文語言包
_words = {
"Warning: Deprecated": "警告:已過時(shí)",
"Implementation Notes": "實(shí)現(xiàn)備注",
"Response Class": "響應(yīng)類",
"Status": "狀態(tài)",
"Parameters": "參數(shù)",
"Parameter": "參數(shù)",
"Value": "值",
"Description": "描述",
"Parameter Type": "參數(shù)類型",
"Data Type": "數(shù)據(jù)類型",
"Response Messages": "響應(yīng)消息",
"HTTP Status Code": "HTTP狀態(tài)碼",
"Reason": "原因",
"Response Model": "響應(yīng)模型",
"Request URL": "請(qǐng)求URL",
"Response Body": "響應(yīng)體",
"Response Code": "響應(yīng)碼",
"Response Headers": "響應(yīng)頭",
"Hide Response": "隱藏響應(yīng)",
"Headers": "頭",
"Try it out!": "試一下染乌!",
"Show/Hide": "顯示/隱藏",
"List Operations": "顯示操作",
"Expand Operations": "展開操作",
"Raw": "原始",
"can't parse JSON. Raw result": "無法解析JSON. 原始結(jié)果",
"Model Schema": "模型架構(gòu)",
"Model": "模型",
"apply": "應(yīng)用",
"Username": "用戶名",
"Password": "密碼",
"Terms of service": "服務(wù)條款",
"Created by": "創(chuàng)建者",
"See more at": "查看更多:",
"Contact the developer": "聯(lián)系開發(fā)者",
"api version": "api版本",
"Response Content Type": "響應(yīng)Content Type",
"fetching resource": "正在獲取資源",
"fetching resource list": "正在獲取資源列表",
"Explore": "瀏覽",
"Show Swagger Petstore Example Apis": "顯示 Swagger Petstore 示例 Apis",
"Can't read from server. It may not have the appropriate access-control-origin settings.": "無法從服務(wù)器讀取山孔。可能沒有正確設(shè)置access-control-origin慕匠。",
"Please specify the protocol for": "請(qǐng)指定協(xié)議:",
"Can't read swagger JSON from": "無法讀取swagger JSON于",
"Finished Loading Resource Information. Rendering Swagger UI": "已加載資源信息饱须。正在渲染Swagger UI",
"Unable to read api": "無法讀取api",
"from path": "從路徑",
"Click to set as parameter value": "點(diǎn)擊設(shè)置參數(shù)",
"server returned": "服務(wù)器返回"
},
//定時(shí)執(zhí)行轉(zhuǎn)換
_translator2Cn = function () {
if ($("#resources_container .resource").length > 0) {
_tryTranslate();
}
if ($("#explore").text() == "Explore" && iexcute < 500) {
iexcute++;
setTimeout(_translator2Cn, 50);
}
},
//設(shè)置控制器注釋
_setControllerSummary = function () {
$.ajax({
type: "get",
async: true,
url: $("#input_baseUrl").val(),
dataType: "json",
success: function (data) {
var summaryDict = data.ControllerDesc;
var id, controllerName, strSummary;
$("#resources_container .resource").each(function (i, item) {
id = $(item).attr("id");
if (id) {
controllerName = id.substring(9);
strSummary = summaryDict[controllerName];
if (strSummary) {
$(item).children(".heading").children(".options").prepend('<li class="controller-summary" title="' + strSummary + '">' + strSummary + '</li>');
}
}
});
}
});
},
//嘗試將英文轉(zhuǎn)換成中文
_tryTranslate = function () {
$('[data-sw-translate]').each(function () {
$(this).html(_getLangDesc($(this).html()));
$(this).val(_getLangDesc($(this).val()));
$(this).attr('title', _getLangDesc($(this).attr('title')));
});
},
_getLangDesc = function (word) {
return _words[$.trim(word)] !== undefined ? _words[$.trim(word)] : word;
};
return {
Translator: function () {
document.title = "API描述文檔";
$('body').append('<style type="text/css">.controller-summary{color:#10a54a !important;word-break:keep-all;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:250px;text-align:right;cursor:default;} </style>');
$("#logo").html("接口描述").attr("href", "/Home/Index");
//設(shè)置控制器描述
_setControllerSummary();
_translator2Cn();
}
}
})();
//執(zhí)行轉(zhuǎn)換
SwaggerTranslator.Translator();
控制器描述和接口文檔緩存
public class CachingSwaggerProvider : ISwaggerProvider
{
private static ConcurrentDictionary<string, SwaggerDocument> _cache =
new ConcurrentDictionary<string, SwaggerDocument>();
private readonly ISwaggerProvider _swaggerProvider;
public CachingSwaggerProvider(ISwaggerProvider swaggerProvider)
{
_swaggerProvider = swaggerProvider;
}
public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
{
var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);
SwaggerDocument srcDoc = null;
//只讀取一次
if (!_cache.TryGetValue(cacheKey, out srcDoc))
{
srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);
srcDoc.vendorExtensions = new Dictionary<string, object> { { "ControllerDesc", GetControllerDesc() } };
_cache.TryAdd(cacheKey, srcDoc);
}
return srcDoc;
}
/// <summary>
/// 從API文檔中讀取控制器描述
/// </summary>
/// <returns>所有控制器描述</returns>
public static ConcurrentDictionary<string, string> GetControllerDesc()
{
string xmlpath = string.Format("{0}/bin/SwaggerDemo.XML", System.AppDomain.CurrentDomain.BaseDirectory);
ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>();
if (File.Exists(xmlpath))
{
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(xmlpath);
string type = string.Empty, path = string.Empty, controllerName = string.Empty;
string[] arrPath;
int length = -1, cCount = "Controller".Length;
XmlNode summaryNode = null;
foreach (XmlNode node in xmldoc.SelectNodes("http://member"))
{
type = node.Attributes["name"].Value;
if (type.StartsWith("T:"))
{
//控制器
arrPath = type.Split('.');
length = arrPath.Length;
controllerName = arrPath[length - 1];
if (controllerName.EndsWith("Controller"))
{
//獲取控制器注釋
summaryNode = node.SelectSingleNode("summary");
string key = controllerName.Remove(controllerName.Length - cCount, cCount);
if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key))
{
controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim());
}
}
}
}
}
return controllerDescDict;
}
}
漢化結(jié)果:
返回簡(jiǎn)書總目錄:ABP+AdminLTE+Bootstrap Table權(quán)限管理系統(tǒng)一期
前往博客園總目錄:ABP+AdminLTE+Bootstrap Table權(quán)限管理系統(tǒng)一期