ASP.NET Web API Demo OwinSelfHost 自宿主 Swagger Swashbuckle 線上文檔

来源:https://www.cnblogs.com/s0611163/archive/2020/06/23/13175721.html
-Advertisement-
Play Games

新建Web API工程 選Empty,勾選Web API,不要選擇Web API,那樣會把MVC勾上,這裡不需要MVC Web API工程屬性 XML文件用於生成線上文檔 新建Windows服務作為Web API的宿主 WebApiHost工程屬性 控制台應用程式方便調試 Windows服務安裝Mi ...


新建Web API工程

 

選Empty,勾選Web API,不要選擇Web API,那樣會把MVC勾上,這裡不需要MVC

Web API工程屬性

 XML文件用於生成線上文檔

  新建Windows服務作為Web API的宿主

 

WebApiHost工程屬性

 控制台應用程式方便調試

 Windows服務安裝Microsoft.AspNet.WebApi.OwinSelfHost

 

工程WebApiDemo需要引用Microsoft.Owin.dll

 WebApiDemo安裝Swashbuckle

 應用程式入口

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;

namespace WebApiHost
{
    static class Program
    {
        /// <summary>
        /// 應用程式的主入口點。
        /// </summary>
        static void Main(string[] args)
        {
            RunDebug();
            StartService();
        }

        private static void StartService()
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new WebApiHostService()
            };
            ServiceBase.Run(ServicesToRun);
        }

        [Conditional("DEBUG")]
        private static void RunDebug()
        {
            new WebApiHostService().Start();
            Console.WriteLine("啟動成功");
            Console.ReadLine();
        }
    }
}
View Code

 啟動Web API服務

using Microsoft.Owin.Hosting;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Utils;

namespace WebApiHost
{
    public partial class WebApiHostService : ServiceBase
    {
        #region 構造函數
        public WebApiHostService()
        {
            InitializeComponent();
        }
        #endregion

        #region OnStart 啟動服務
        protected override void OnStart(string[] args)
        {
            int port = int.Parse(ConfigurationManager.AppSettings["WebApiServicePort"]);
            StartOptions options = new StartOptions();
            options.Urls.Add("http://127.0.0.1:" + port);
            options.Urls.Add("http://localhost:" + port);
            options.Urls.Add("http://+:" + port);
            WebApp.Start<Startup>(options);
            LogUtil.Log("Web API 服務 啟動成功");
        }
        #endregion

        #region OnStop 停止服務
        protected override void OnStop()
        {
            LogUtil.Log("Web API 服務 停止成功");
            Thread.Sleep(100); //等待一會,待日誌寫入文件
        }
        #endregion

        #region Start 啟動服務
        public void Start()
        {
            OnStart(null);
        }
        #endregion

    }
}
View Code

 配置Web API路由、攔截器以及初始化Swagger線上文檔

using Owin;
using WebApiDemo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;

namespace WebApiHost
{
    class Startup
    {
        public void Configuration(IAppBuilder appBuilder)
        {
            HttpConfiguration config = new HttpConfiguration();

            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            config.Filters.Add(new MyExceptionFilter());
            config.Filters.Add(new MyActionFilter());

            SwaggerConfig.Register(config);

            appBuilder.UseWebApi(config);
        }
    }
}
View Code

介面實現

1、繼承ApiController

2、RoutePrefix設置路由首碼

3、SwaggerResponse用於生成線上文檔描述

using Models;
using Swashbuckle.Swagger.Annotations;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Utils;

namespace WebApiDemo.Controllers
{
    /// <summary>
    /// 測試介面
    /// </summary>
    [RoutePrefix("api/test")]
    public class TestController : ApiController
    {
        #region TestGet 測試GET請求
        /// <summary>
        /// 測試GET請求
        /// </summary>
        /// <param name="val">測試參數</param>
        [HttpGet]
        [Route("TestGet")]
        [SwaggerResponse(HttpStatusCode.OK, "返回JSON", typeof(JsonListResult<TestGetResult>))]
        public HttpResponseMessage TestGet(string val)
        {
            List<TestGetResult> list = new List<TestGetResult>();

            for (int i = 1; i <= 10; i++)
            {
                TestGetResult item = new TestGetResult();
                item.testValue1 = i.ToString();
                item.testValue2 = i;
                item.testValue3 = "這是傳入參數:" + val;
                list.Add(item);
            }

            var jsonResult = new JsonListResult<TestGetResult>(list, list.Count);

            return ApiHelper.ToJson(jsonResult);
        }
        #endregion

        #region TestPost 測試POST請求
        /// <summary>
        /// 測試POST請求
        /// </summary>
        /// <param name="data">POST數據</param>
        [HttpPost]
        [Route("TestPost")]
        [SwaggerResponse(HttpStatusCode.OK, "返回JSON", typeof(JsonResult<CommonSubmitResult>))]
        public HttpResponseMessage TestPost([FromBody] TestPostData data)
        {
            JsonResult jsonResult = null;

            if (data == null) return ApiHelper.ToJson(new JsonResult("請檢查參數格式", ResultCode.參數不正確));

            string msg = "操作成功,這是您傳入的參數:" + data.testArg;

            jsonResult = new JsonResult<CommonSubmitResult>(new CommonSubmitResult()
            {
                msg = msg,
                id = "1"
            });

            return ApiHelper.ToJson(jsonResult);
        }
        #endregion

    }

    #region 數據類
    /// <summary>
    /// TestGet介面返回結果
    /// </summary>
    public class TestGetResult
    {
        /// <summary>
        /// 測試數據1
        /// </summary>
        public string testValue1 { get; set; }

        /// <summary>
        /// 測試數據2
        /// </summary>
        public int testValue2 { get; set; }

        /// <summary>
        /// 測試數據3
        /// </summary>
        public string testValue3 { get; set; }
    }

    /// <summary>
    /// TestPost介面參數
    /// </summary>
    [MyValidate]
    public class TestPostData
    {
        /// <summary>
        /// 測試參數1
        /// </summary>
        [Required]
        public string testArg { get; set; }

        /// <summary>
        /// 測試日期參數
        /// </summary>
        [Required]
        [DateTime(Format = "yyyyMMddHHmmss")]
        public string testTime { get; set; }
    }

    /// <summary>
    /// TestPost介面返回結果
    /// </summary>
    public class TestPostResult
    {
        /// <summary>
        /// 測試數據1
        /// </summary>
        public string testValue1 { get; set; }
    }
    #endregion

}
View Code

MyValidate屬性表示該數據需要校驗

Required必填校驗
DateTime日期輸入格式校驗

輔助類ApiHelper.cs

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Web;

namespace Utils
{
    public class ApiHelper
    {
        public static HttpResponseMessage ToJson(object obj)
        {
            string str = JsonConvert.SerializeObject(obj);
            HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(str, Encoding.UTF8, "application/json") };
            return result;
        }

    }
}
View Code

 輔助類ServiceHelper.cs

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Utils
{
    /// <summary>
    /// 服務幫助類
    /// </summary>
    public class ServiceHelper
    {
        public static ConcurrentDictionary<Type, object> _dict = new ConcurrentDictionary<Type, object>();

        /// <summary>
        /// 獲取對象
        /// </summary>
        public static T Get<T>() where T : new()
        {
            Type type = typeof(T);
            object obj = _dict.GetOrAdd(type, (key) => new T());

            return (T)obj;
        }

        /// <summary>
        /// 獲取對象
        /// </summary>
        public static T Get<T>(Func<T> func) where T : new()
        {
            Type type = typeof(T);
            object obj = _dict.GetOrAdd(type, (key) => func());

            return (T)obj;
        }

    }
}
View Code

 JsonResult類

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Net;
using System.Web;

namespace Models
{
    /// <summary>
    /// Json返回
    /// </summary>
    public class JsonResult
    {
        /// <summary>
        /// 介面是否成功
        /// </summary>
        [Required]
        public virtual bool success { get; set; }

        /// <summary>
        /// 結果編碼
        /// </summary>
        [Required]
        public virtual ResultCode resultCode { get; set; }

        /// <summary>
        /// 介面錯誤信息
        /// </summary>
        public virtual string errorMsg { get; set; }

        /// <summary>
        /// 記錄總數(可空類型)
        /// </summary>
        public virtual int? total { get; set; }

        /// <summary>
        /// 預設構造函數
        /// </summary>
        public JsonResult() { }

        /// <summary>
        /// 介面失敗返回數據
        /// </summary>
        public JsonResult(string errorMsg, ResultCode resultCode)
        {
            this.success = false;
            this.resultCode = resultCode;
            this.errorMsg = errorMsg;
        }

    }

    /// <summary>
    /// Json返回
    /// </summary>
    public class JsonResult<T> : JsonResult
    {
        /* 子類重寫屬性解決JSON序列化屬性順序問題 */

        /// <summary>
        /// 介面是否成功
        /// </summary>
        [Required]
        public override bool success { get; set; }

        /// <summary>
        /// 結果編碼
        /// </summary>
        [Required]
        public override ResultCode resultCode { get; set; }

        /// <summary>
        /// 介面錯誤信息
        /// </summary>
        public override string errorMsg { get; set; }

        /// <summary>
        /// 記錄總數(可空類型)
        /// </summary>
        public override int? total { get; set; }

        /// <summary>
        /// 數據
        /// </summary>
        public T info { get; set; }

        /// <summary>
        /// 介面成功返回數據
        /// </summary>
        public JsonResult(T info)
        {
            this.success = true;
            this.resultCode = ResultCode.OK;
            this.info = info;
            this.total = null;
        }

    }

    /// <summary>
    /// Json返回
    /// </summary>
    public class JsonListResult<T> : JsonResult
    {
        /* 子類重寫屬性解決JSON序列化屬性順序問題 */

        /// <summary>
        /// 介面是否成功
        /// </summary>
        [Required]
        public override bool success { get; set; }

        /// <summary>
        /// 結果編碼
        /// </summary>
        [Required]
        public override ResultCode resultCode { get; set; }

        /// <summary>
        /// 介面錯誤信息
        /// </summary>
        public override string errorMsg { get; set; }

        /// <summary>
        /// 記錄總數(可空類型)
        /// </summary>
        public override int? total { get; set; }

        /// <summary>
        /// 數據
        /// </summary>
        public List<T> info { get; set; }

        /// <summary>
        /// 介面成功返回數據
        /// </summary>
        public JsonListResult(List<T> list, int total)
        {
            this.success = true;
            this.resultCode = ResultCode.OK;
            this.info = list;
            this.total = total;
        }

        /// <summary>
        /// 介面成功返回數據
        /// </summary>
        public JsonListResult(List<T> list, PagerModel pager)
        {
            this.success = true;
            this.resultCode = ResultCode.OK;
            this.info = list;
            this.total = pager.totalRows;
        }

    }

    /// <summary>
    /// 結果編碼
    /// </summary>
    public enum ResultCode
    {
        OK = 200,

        token不匹配或已過期 = 1001,
        請求頭中不存在token = 1002,
        用戶不存在 = 1101,
        密碼不正確 = 1102,
        參數不正確 = 1201,
        操作失敗 = 1301,
        資源不存在 = 1302,
        其他錯誤 = 1401,

        伺服器內部錯誤 = 1501
    }

    /// <summary>
    /// 通用返回數據
    /// </summary>
    public class CommonSubmitResult
    {
        /// <summary>
        /// 提示信息
        /// </summary>
        public string msg { get; set; }

        /// <summary>
        /// 記錄ID
        /// </summary>
        public string id { get; set; }
    }

    /// <summary>
    /// 通用返回數據
    /// </summary>
    public class CommonMsgResult
    {
        /// <summary>
        /// 提示信息
        /// </summary>
        public string msg { get; set; }
    }
}
View Code

異常攔截器

異常在這裡統一處理,介面方法中不需要再加try catch

using Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web;
using System.Web.Http.Filters;
using Utils;

namespace WebApiDemo
{
    public class MyExceptionFilter : ExceptionFilterAttribute
    {
        //重寫基類的異常處理方法
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            var result = new JsonResult("攔截到異常:" + actionExecutedContext.Exception.Message, ResultCode.伺服器內部錯誤);

            LogUtil.Error(actionExecutedContext.Exception);

            actionExecutedContext.Response = ApiHelper.ToJson(result);

            base.OnException(actionExecutedContext);
        }
    }
}
View Code

方法攔截器

1、在攔截器中校驗證token
2、在攔截器中校驗POST和GET參數
3、在攔截器中寫操作日誌

using Microsoft.Owin;
using Models;
using Newtonsoft.Json;
using Swashbuckle.Swagger;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Utils;

namespace WebApiDemo
{
    /// <summary>
    /// 攔截器
    /// </summary>
    public class MyActionFilter : ActionFilterAttribute
    {
        #region 變數
        private Dictionary<string, string> _dictActionDesc = ServiceHelper.Get<Dictionary<string, string>>(() => XmlUtil.GetActionDesc());
        #endregion

        #region OnActionExecuting 執行方法前
        /// <summary>
        /// 執行方法前
        /// </summary>
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            base.OnActionExecuting(actionContext);

            //token驗證
            Collection<AllowAnonymousAttribute> attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>();
            if (attributes.Count == 0)
            {
                IEnumerable<string> value;
                if (actionContext.Request.Headers.TryGetValues("token", out value))
                {
                    string token = value.ToArray()[0];

                    if (false) //todo:token驗證
                    {
                        actionContext.Response = ApiHelper.ToJson(new JsonResult("token不匹配或已過期", ResultCode.token不匹配或已過期));
                        return;
                    }
                }
                else
                {
                    actionContext.Response = ApiHelper.ToJson(new JsonResult("請求頭中不存在token", ResultCode.請求頭中不存在token));
                    return;
                }
            }

            //post參數驗證
            if (actionContext.Request.Method == HttpMethod.Post)
            {
                foreach (string key in actionContext.ActionArguments.Keys)
                {
                    object value = actionContext.ActionArguments[key];
                    if (value != null)
                    {
                        if (value.GetType().GetCustomAttributes(typeof(MyValidateAttribute), false).Length > 0)
                        {
                            string errMsg = null;
                            if (!ValidatePropertyUtil.Validate(value, out errMsg))
                            {
                                JsonResult jsonResult = new JsonResult(errMsg, ResultCode.參數不正確);
                                actionContext.Response = ApiHelper.ToJson(jsonResult);
                                

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 基於角色的訪問控制 (RBAC) 是將系統訪問限製為授權用戶的一種方法,是圍繞角色和特權定義的與策略無關的訪問控制機制,RBAC的組件使執行用戶分配變得很簡單。 在組織內部,將為各種職務創建角色。執行某些操作的許可權已分配給特定角色。成員或職員(或其他系統用戶)被分配了特定角色,並且通過這些角色分配獲 ...
  • 剛開始學習VBA的時候,保存自定義數據用的隱藏工作表;後來學了VSTO,把自定義數據保存到XML文件中;最近繼續深入學習,發現可以直接在xlsx文件中保存自定義數據,這裡就列出使用方法。 除了以上幾種保存方式,還可以保存為JSON格式,或者直接在xlsx文件中寫入xml。各種方式都有適合的應用場景, ...
  • 用好數據映射,MongoDB via Dotnet Core開發變會成一件超級快樂的事。 一、前言 MongoDB這幾年已經成為NoSQL的頭部資料庫。 由於MongoDB free schema的特性,使得它在互聯網應用方面優於常規資料庫,成為了相當一部分大廠的主數據選擇;而它的快速佈署和開發簡單 ...
  • // A delegate type for hooking up change notifications. public delegate void ProgressChangingEventHandler(object sender, string e); /// <summary> /// ...
  • 概念介紹: 單鏈表是一種鏈式存取的數據結構,用一組地址任意的存儲單元存放線性表中的數據元素。 鏈表中的數據是以結點來表示的,每個結點的構成:元素(數據元素的映象) + 指針(指示後繼元素存儲位置),元素就是存儲數據的存儲單元,指針就是連接每個結點的地址數據 由圖可知: 鏈表在進行添加/刪除時,只需要 ...
  • .NET 人臉識別庫 ViewFaceCore 這是基於 SeetaFace6 人臉識別開發的 .NET 平臺下的人臉識別庫這是一個使用超簡單的人臉識別庫這是一個基於 .NET Standard 2.0 開發的庫這個庫已經發佈到 NuGet ,你可以一鍵集成到你的項目此項目可以免費商業使用 ⭐、開源 ...
  • 0. 前言 通過前兩篇我們實現瞭如何在Service層如何訪問數據,以及如何運用簡單的加密演算法對數據加密。這一篇我們將探索如何實現asp.net core的身份驗證。 1. 身份驗證 asp.net core的身份驗證有 JwtBearer和Cookie兩種常見的模式,在這一篇我們將啟用Cookie ...
  • 當我們使用DB First時,設計好的資料庫,我們怎麼生成一些實體類、通用的代碼、控制器、服務層、Dto呢。今天我來給大家介紹一下FreeSql項目中的一些工具。當然,不使用此ORM的小伙伴也能使用此工具,因為他是通用。 ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...