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 MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...