微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ASP.NET Web API Demo OwinSelfHost 自宿主 Swagger Swashbuckle 在线文档

新建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;
 System.Collections.Generic;
 System.Diagnostics;
 System.Linq;
 System.ServiceProcess;
 System.Text;
 System.Threading.Tasks;

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

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

        [Conditional("DEBUG")]
         RunDebug()
        {
             WebApiHostService().Start();
            Console.WriteLine(启动成功);
            Console.ReadLine();
        }
    }
}
View Code

 启动Web API服务

 Microsoft.Owin.Hosting;
 System.ComponentModel;
 System.Configuration;
 System.Data;
 System.Threading;
 System.Threading.Tasks;
 Utils;

public partial  WebApiHostService : ServiceBase
    {
        #region 构造函数
        public WebApiHostService()
        {
            InitializeComponent();
        }
        #endregion

        #region OnStart 启动服务
        protected override void OnStart([] args)
        {
            int port = int.Parse(ConfigurationManager.AppSettings[WebApiServicePort]);
            StartOptions options =  StartOptions();
            options.Urls.Add(http://127.0.0.1:" + port);
            options.Urls.Add(http://localhost:http://+: port);
            WebApp.Start<Startup>(options);
            LogUtil.Log(Web API 服务 启动成功);
        }
        #region OnStop 停止服务
         OnStop()
        {
            LogUtil.Log(Web API 服务 停止成功);
            Thread.Sleep(100); //等待一会,待日志写入文件
        }
        #region Start 启动服务
         Start()
        {
            OnStart(null#endregion

    }
}
View Code

 配置Web API路由、拦截器以及初始化Swagger在线文档

 Owin;
 WebApiDemo;
 System.Web.Http;

 Startup
    {
         Configuration(IAppBuilder appBuilder)
        {
            HttpConfiguration config =  HttpConfiguration();

            config.MapHttpAttributeRoutes();

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

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

            SwaggerConfig.Register(config);

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

接口实现

1、继承ApiController

2、RoutePrefix设置路由前缀

3、SwaggerResponse用于生成在线文档描述

 Models;
 Swashbuckle.Swagger.Annotations;
 System.ComponentModel.DataAnnotations;
 System.Net;
 System.Net.Http;
 System.Web.Http;
 WebApiDemo.Controllers
{
    <summary>
     测试接口
    </summary>
    [RoutePrefix(api/test)]
     TestController : ApiController
    {
        #region TestGet 测试GET请求
         测试GET请求
        </summary>
        <param name="val">测试参数</param>
        [HttpGet]
        [Route(TestGet)]
        [SwaggerResponse(HttpStatusCode.OK,返回JSON",typeof(JsonListResult<TestGetResult>))]
        public HttpResponseMessage TestGet( val)
        {
            List<TestGetResult> list = new List<TestGetResult>();

            for (int i = 1; i <= 10; i++)
            {
                TestGetResult item =  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);
        }
        #region TestPost 测试POST请求
         测试POST请求
        <param name="data">POST数据        [HttpPost]
        [Route(TestPosttypeof(JsonResult<CommonSubmitResult> HttpResponseMessage TestPost([FromBody] TestPostData data)
        {
            JsonResult jsonResult = ;

            if (data == null) return ApiHelper.ToJson(new JsonResult(请检查参数格式string msg = 操作成功,这是您传入的参数: data.testArg;

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

            

    }

    #region 数据类
     TestGet接口返回结果
    </summary>
     TestGetResult
    {
         测试数据1
        string testValue1 { get; set; }

         测试数据2
        int testValue2 {  测试数据3
        string testValue3 { ; }
    }

     TestPost接口参数
    </summary>
    [MyValidate]
     TestPostData
    {
         测试参数1
                [required]
        string testArg {  测试日期参数
                [required]
        [DateTime(Format = yyyyMMddHHmmssstring testTime {  TestPost接口返回结果
     TestPostResult
    {
        ; }
    }
    

}
View Code

MyValidate属性表示该数据需要校验

required必填校验
DateTime日期输入格式校验

辅助类ApiHelper.cs

 Newtonsoft.Json;
 System.Web;

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

    }
}
View Code

 辅助类ServiceHelper.cs

 System.Collections.Concurrent;
 Utils
{
     服务帮助类
     ServiceHelper
    {
        static ConcurrentDictionary<Type,1)">object> _dict = new ConcurrentDictionary<Type,1)">object>();

         获取对象
        static T Get<T>() where T : ()
        {
            Type type = typeof(T);
            object obj = _dict.GetorAdd(type,(key) =>  T());

             (T)obj;
        }

        static T Get<T>(Func<T> func)  func());

             (T)obj;
        }

    }
}
View Code

 JsonResult类

 Models
{
     Json返回
     JsonResult
    {
         接口是否成功
        virtual bool success {  结果编码
        virtual ResultCode resultCode {  接口错误信息
        string errorMsg {  记录总数(可空类型)
        int? total {  认构造函数
         JsonResult() { }

         接口失败返回数据
        public JsonResult( errorMsg,ResultCode resultCode)
        {
            this.success = false;
            this.resultCode = resultCode;
            this.errorMsg = errorMsg;
        }

    }

    class JsonResult<T> : JsonResult
    {
        /* 子类重写属性解决JSON序列化属性顺序问题 */

        override ResultCode resultCode {  数据
        public T info {  接口成功返回数据
         JsonResult(T info)
        {
            true ResultCode.OK;
            this.info = info;
            this.total = ;
        }

    }

    class JsonListResult<T>public List<T> info { public JsonListResult(List<T> list,1)">int total)
        {
             list;
            this.total = total;
        }

        public JsonListResult(List<T> list,PagerModel pager)
        {
             pager.totalRows;
        }

    }

     结果编码
    enum ResultCode
    {
        OK = 20010011002用户不存在 = 1101密码不正确 = 1102120113011302错误 = 1401错误 = 1501
    }

     通用返回数据
     CommonSubmitResult
    {
         提示信息
        string msg {  记录ID
        string id {  CommonMsgResult
    {
        ; }
    }
}
View Code

异常拦截

异常在这里统一处理,接口方法中不需要再加try catch

 System.Web;
 System.Web.Http.Filters;
 WebApiDemo
{
     MyExceptionFilter : ExceptionFilterattribute
    {
        重写基类的异常处理方法
         OnException(HttpActionExecutedContext actionExecutedContext)
        {
            var result = 拦截到异常: actionExecutedContext.Exception.Message,ResultCode.服务器内部错误);

            LogUtil.Error(actionExecutedContext.Exception);

            actionExecutedContext.Response = ApiHelper.ToJson(result);

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

方法拦截

1、在拦截器中校验证token
2、在拦截器中校验POST和GET参数
3、在拦截器中写操作日志

 Microsoft.Owin;
 Swashbuckle.Swagger;
 System.Collections.ObjectModel;
 System.Reflection;
 System.Web.Http.Controllers;
 WebApiDemo
{
     拦截 MyActionFilter : ActionFilterattribute
    {
        #region 变量
        private Dictionary<string,1)">string> _dictActionDesc = ServiceHelper.Get<Dictionary<string>>(() => XmlUtil.GetActionDesc());
        #region OnActionExecuting 执行方法 执行方法 OnActionExecuting(HttpActionContext actionContext)
        {
            .OnActionExecuting(actionContext);

            token验证
            Collection<AllowAnonymousAttribute> attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>();
            if (attributes.Count == 0)
            {
                IEnumerable<string> value;
                if (actionContext.Request.Headers.TryGetValues(tokenout value))
                {
                    string token = value.ToArray()[];

                    if (false) todo:token验证
                    {
                        actionContext.Response = ApiHelper.ToJson(token不匹配或已过期;
                    }
                }
                else
                {
                    actionContext.Response = ApiHelper.ToJson(请求头中不存在token;
                }
            }

            post参数验证
            if (actionContext.Request.Method == HttpMethod.Post)
            {
                foreach (string key in actionContext.ActionArguments.Keys)
                {
                    object value = actionContext.ActionArguments[key];
                    if (value != )
                    {
                        if (value.GetType().GetCustomAttributes(typeof(MyValidateAttribute),1)">false).Length > )
                        {
                            string errMsg = ;
                            if (!ValidatePropertyUtil.Validate(value,1)"> errMsg))
                            {
                                JsonResult jsonResult =  JsonResult(errMsg,ResultCode.参数不正确);
                                actionContext.Response = ApiHelper.ToJson(jsonResult);
                                ;
                            }
                        }
                    }
                }
            }

            get参数验证
             HttpMethod.Get)
            {
                if (key == pageif ((int)value <= )
                            {
                                JsonResult jsonResult = page必须大于0;
                            }
                        }

                        pageSizeint)value > 10000pageSize大于10000,请分页查询;
                            }
                        }
                    }
                }
            }
        }
        #region OnActionExecutedAsync 执行方法 执行方法override Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext,CancellationToken cancellationToken)
        {
            return Task.Factory.StartNew(async () =>
            {
                try
                {
                    Type controllerType = actionExecutedContext.ActionContext.ControllerContext.Controller.GetType();
                    MethodInfo methodInfo = controllerType.getmethod(actionExecutedContext.ActionContext.ActionDescriptor.ActionName);

                    string action = controllerType.FullName + . methodInfo.Name;

                    if (_dictActionDesc.ContainsKey(action))
                    {
                        string jsonResult = ;
                        List<string> paramList = new List<();
                        string param = .Empty;
                        if (actionExecutedContext.Request.Method == HttpMethod.Post)
                        {
                             actionExecutedContext.ActionContext.ActionArguments.Keys)
                            {
                                 actionExecutedContext.ActionContext.ActionArguments[key];
                                null && value as HttpRequestMessage == )
                                {
                                    paramList.Add(JsonConvert.SerializeObject(value));
                                }
                            }
                            param = string.Join(aramList);

                            if (actionExecutedContext.Exception == )
                            {
                                byte[] bArr = await actionExecutedContext.ActionContext.Response.Content.ReadAsByteArrayAsync();
                                jsonResult = Encoding.UTF8.GetString(bArr);
                            }
                            
                            {
                                JsonResult jr = new JsonResult(actionExecutedContext.Exception.Message + \r\n actionExecutedContext.Exception.StackTrace,ResultCode.服务器内部错误);
                                jsonResult = JsonConvert.SerializeObject(jr);
                            }
                        }
                        
                        {
                            )
                                {
                                    paramList.Add(key + = value.ToString());
                                }
                                
                                {
                                    paramList.Add(key + );
                                }
                            }
                            param = &if (actionExecutedContext.ActionContext.Response.Content is StringContent)
                                {
                                     actionExecutedContext.ActionContext.Response.Content.ReadAsByteArrayAsync();
                                    jsonResult = Encoding.UTF8.GetString(bArr);
                                }
                                
                                {
                                    jsonResult = JsonConvert.SerializeObject(new JsonResult<object>());
                                }
                            }
                             JsonConvert.SerializeObject(jr);
                            }
                        }

                        string ip = ;
                        if (actionExecutedContext.Request.Properties.ContainsKey(MS_OwinContext))
                        {
                            OwinContext owinContext = actionExecutedContext.Request.Properties["] as OwinContext;
                            if (owinContext != 
                                {
                                    ip = owinContext.Request.RemoteIpAddress;
                                }
                                catch { }
                            }
                        }

                        todo:写操作日志
                        
                        ServiceHelper.Get<SysOperLogDal>().Log(action,//方法名
                            actionExecutedContext.Request.Method,//请求类型
                            _dictActionDesc[action],//方法注释
                            ip,//IP
                            actionExecutedContext.Request.RequestUri.LocalPath,//URL
                            param,//请求参数
                            jsonResult); //操作结果
                        */
                    }
                }
                 (Exception ex)
                {
                    LogUtil.Error(ex,1)">MyActionFilter OnActionExecutedAsync 写操作日志出错);
                }
            });
        }
        

    }
}
View Code

参数校验工具类

这里只做了必填和日期校验,且字段类型只是基础类型,有待完善

 System.Globalization;
 字段属性验证工具类
     ValidatePropertyUtil
    {
         验证数据 
         true:验证通过 false 验证不通过
        数据</param>
        <param name="errMsg">错误信息</param>
        bool Validate(object data,1)">out  errMsg)
        {
            PropertyInfo[] propertyInfoList = data.GetType().GetProperties();
            foreach (PropertyInfo propertyInfo  propertyInfoList)
            {
                if (propertyInfo.GetCustomAttributes(typeof(requiredAttribute),1)">)
                {
                     propertyInfo.GetValue(data);
                    if (value == )
                    {
                        errMsg = 属性 " + propertyInfo.Name +  必填return ;
                    }
                }

                object[] attrArr = propertyInfo.GetCustomAttributes(typeof(DateTimeAttribute),1)">);
                if (attrArr.Length > )
                {
                    DateTimeAttribute attr = attrArr[0]  DateTimeAttribute;
                     是日期时间格式,格式: attr.Format;
                        ;
                    }
                    
                    {
                        DateTime dt;
                        if (!DateTime.TryParseExact(value.ToString(),attr.Format,CultureInfo.InvariantCulture,DateTimeStyles.None,1)"> dt))
                        {
                            errMsg =  attr.Format;
                            ;
                        }
                    }
                }
            }

            errMsg = ;
        }
    }
}
View Code

swagger.js

复制到输出目录:不复制

生成操作:嵌入的资源

var SwaggerTranslator = (function () {
    定时执行检测是否转换成中文,最多执行500次  即500*50/1000=25s
    var _iexcute = 0;

    var _lock = 中文语言包
    var _words = {
        "Warning: Deprecated": "警告:已过时"arameters": "参数"arameter": "参数"arameter Type": "参数类型"显示/隐藏"显示操作"用户名"密码"获取资源"获取资源列表"显示 Swagger Petstore 示例 Apis"4045@ion. Rendering Swagger UI": "已加载资源信息。正在渲染Swagger UI"arameter value": "点击设置参数"
    };

    定时执行转换
    var _translator2Cn =  () {
        if ($("#resources_container .resource").length > 0) {
            _tryTranslate();
        }

        if ($("#explore").text() == "Explore" && _iexcute < 500) {
            _iexcute++;
            setTimeout(_translator2Cn,50);
        }
    };

    设置控制器注释
    var _setControllerSummary = if (!_lock) {
            _lock = ;
            $.ajax({
                type: "get""#input_baseUrl").val(),dataType: "json" (data) {
                    var summaryDict = data.ControllerDesc;
                    var id,controllerName,strSummary;
                    $("#resources_container .resource").each( (i,item) {
                        id = $(item).attr("id");
                         (id) {
                            controllerName = id.substring(9);
                            strSummary = summaryDict[controllerName];
                             (strSummary) {
                                $(item).children(".heading").children(".options").prepend('<li class="controller-summary" title="' + strSummary + '">' + strSummary + '</li>');
                            }
                        }
                    });

                    setTimeout( () {
                        _lock = ;
                    },100);
                }
            });
        }
    };

    尝试将英文转换成中文
    var _tryTranslate =  () {
        $('[data-sw-translate]').each( () {
            $(this).html(_getLangDesc($(this).html()));
            $(this).val(_getLangDesc($().val()));
            $(this).attr('title',_getLangDesc($(this).attr('title')));
        });
    };

    var _getLangDesc =  (word) {
        return _words[$.trim(word)] !== undefined ? _words[$.trim(word)] : word;
    };

     {
        translate:  () {
            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","/swagger/ui/index");
            设置控制器描述
            _setControllerSummary();
            _translator2Cn();
        }
    };
})();

执行转换
SwaggerTranslator.translate();
View Code

CachingSwaggerProvider.cs

 System.IO;
 System.Xml;

 用于汉化Swagger
     CachingSwaggerProvider : ISwaggerProvider
    {
        static ConcurrentDictionary<new ConcurrentDictionary<();

        readonly ISwaggerProvider _swaggerProvider;

         构造函数
         CachingSwaggerProvider(ISwaggerProvider swaggerProvider)
        {
            _swaggerProvider = swaggerProvider;
        }

         GetSwagger
        public SwaggerDocument GetSwagger(string rootUrl,1)"> apiVersion)
        {
            var cacheKey = string.Format({0}_{1};
                只读取一次
                if (!_cache.TryGetValue(cacheKey,1)"> srcDoc))
                {
                    srcDoc = _swaggerProvider.GetSwagger(rootUrl,apiVersion);

                    srcDoc.vendorExtensions = new Dictionary<object> { { ControllerDesc srcDoc;
            }
            
            {
                SwaggerDocument doc =  SwaggerDocument();
                doc.info =  Info();
                doc.info.title = 接口不存在 doc;
            }
        }

        api文档中读取控制器描述
        <returns>所有控制器描述</returns>
         GetControllerDesc()
        {
            string xmlpath = {0}/{1}.XML(SwaggerConfig).Assembly.GetName().Name);
            ConcurrentDictionary<string> controllerDescDict =  (File.Exists(xmlpath))
            {
                XmlDocument xmldoc =  XmlDocument();
                xmldoc.Load(xmlpath);
                string type = string.Empty,path = .Empty;

                [] arrPath;
                int length = -1,cCount = Controller.Length;
                XmlNode summaryNode = foreach (XmlNode node in xmldoc.SelectNodes(//member))
                {
                    type = node.Attributes[name].Value;
                    if (type.StartsWith(T:))
                    {
                        控制器
                        arrPath = type.Split('');
                        length = arrPath.Length;
                        controllerName = arrPath[length - 1];
                        if (controllerName.EndsWith())
                        {
                            获取控制器注释
                            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());
                            }
                        }
                    }
                }
            }
             controllerDescDict;
        }

    }
}
View Code

SwaggerOperationFilter.cs

文件上传与token参数

 System.Web.Http.Description;

 SwaggerOperationFilter : IOperationFilter
    {
         Apply(Operation operation,SchemaRegistry schemaRegistry,ApiDescription apiDescription)
        {
            if (operation.parameters == null) operation.parameters = new List<Parameter>if (apiDescription.RelativePath.Contains(/UploadFile))
            {
                operation.parameters.RemoveAt();

                operation.parameters.Add( Parameter
                {
                    name = folderformData文件required = string
                });

                operation.parameters.Add(file文件
                });

                operation.consumes.Add(multipart/form-data);
            }

            Collection<AllowAnonymousAttribute> attributes = apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>)
            {
                operation.parameters.Insert(0,1)">new Parameter { name = headerTokenrequired = true,type =  });
            }
        }
    }
}
View Code

SwaggerConfig.cs

 Swashbuckle.Application;
 System.Web;

[assembly: PreApplicationStartMethod(typeof(SwaggerConfig),1)">Register)]

 SwaggerConfig
    {
         Register(HttpConfiguration config)
        {
            var thisAssembly = (SwaggerConfig).Assembly;

            config
                .EnableSwagger(c =>
                    {
                         By default,the service root url is inferred from the request used to access the docs.
                         However,there may be situations (e.g. proxy and load-balanced environments) where this does not
                         resolve correctly. You can workaround this by providing your own code to determine the root URL.
                        //
                        c.RootUrl(req => GetRootUrlFromAppConfig());

                         If schemes are not explicitly provided in a Swagger 2.0 document,then the scheme used to access
                         the docs is taken as the default. If your API supports multiple schemes and you want to be explicit
                         about them,you can use the "Schemes" option as shown below.
                        c.Schemes(new[] { "http","https" });

                         Use "SingleApiVersion" to describe a single version API. Swagger 2.0 includes an "Info" object to
                         hold additional Metadata for an API. Version and title are required but you can also provide
                         additional fields by chaining methods off SingleApiVersion.
                        //
                        c.SingleApiVersion(v1WebApiDemo 测试接口文档);

                        c.OperationFilter<SwaggerOperationFilter>(); 添加过滤器,增加Token令牌验证

                        c.IncludeXmlComments(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory,1)">@"WebApiDemo.XML));

                        c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider)); 汉化Swagger两步:第一步

                         If you want the output Swagger docs to be indented properly,enable the "PrettyPrint" option.
                        c.PrettyPrint();

                         If your API has multiple versions,use "MultipleApiVersions" instead of "SingleApiVersion".
                         In this case,you must provide a lambda that tells Swashbuckle which actions should be
                         included in the docs for a given API version. Like "SingleApiVersion",each call to "Version"
                         returns an "Info" builder so you can provide additional Metadata per API version.
                        c.MultipleApiVersions(
                            (apiDesc,targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc,targetApiVersion),    (vc) =>
                            {
                                vc.Version("v2","Swashbuckle Dummy API V2");
                                vc.Version("v1","Swashbuckle Dummy API V1");
                            });

                         You can use "BasicAuth","ApiKey" or "OAuth2" options to describe security schemes for the API.
                         See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details.
                         NOTE: These only define the schemes and need to be coupled with a corresponding "security" property
                         at the document or operation level to indicate which schemes are required for an operation. To do this,1)"> you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
                         according to your specific authorization implementation
                        c.BasicAuth("basic")
                            .Description("Basic HTTP Authentication");
                         NOTE: You must also configure 'EnableApiKeySupport' below in the SwaggerUI section
                        c.ApiKey("apiKey")
                            .Description("API Key Authentication")
                            .Name("apiKey")
                            .In("header");
                        c.OAuth2("oauth2")
                            .Description("OAuth2 Implicit Grant")
                            .Flow("implicit")
                            .AuthorizationUrl("http://petstore.swagger.wordnik.com/apI/Oauth/dialog")
                        //    .TokenUrl("https://tempuri.org/token    .Scopes(scopes =>
                                scopes.Add("read","Read access to protected resources");
                                scopes.Add("write","Write access to protected resources");
                         Set this flag to omit descriptions for any actions decorated with the Obsolete attribute
                        c.IgnoreObsoleteActions();

                         Each operation be assigned one or more tags which are then used by consumers for varIoUs reasons.
                         For example,the swagger-ui groups operations according to the first tag of each operation.
                         override with any value.
                        c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());

                         You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate
                         the order in which operations are listed. For example,if the default grouping is in place
                         (controller name) and you specify a descending alphabetic sort order,then actions from a
                         ProductsController will be listed before those from a CustomersController. This is typically
                         used to customize the order of groupings in the swagger-ui.
                        c.OrderActionGroupsBy(new DescendingalphabeticComparer());

                         If you annotate Controllers and API Types with
                         Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx),you can incorporate
                         those comments into the generated docs and UI. You can enable this by providing the path to one or
                         more Xml comment files.
                        c.IncludeXmlComments(GetXmlCommentsPath());

                         Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the varIoUs types
                         exposed in your API. However,there may be occasions when more control of the output is needed.
                         This is supported through the "MapType" and "SchemaFilter" options:
                         Use the "MapType" option to override the Schema generation for a specific type.
                         It should be noted that the resulting Schema will be placed "inline" for any applicable Operations.
                         While Swagger 2.0 supports inline deFinitions for "all" Schema types,the swagger-ui tool does not.
                         It expects "complex" Schemas to be defined separately and referenced. For this reason,you should only
                         use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a
                         complex Schema,use a Schema filter.
                        c.MapType<ProductType>(() => new Schema { type = "integer",format = "int32" });

                         If you want to post-modify "complex" Schemas once they've been generated,across the board or for a
                         specific type,you can wire up one or more Schema filters.
                        c.SchemaFilter<ApplySchemavendorExtensions>();

                         In a Swagger 2.0 document,complex types are typically declared globally and referenced by unique
                         Schema Id. By default,Swashbuckle does NOT use the full type name in Schema Ids. In most cases,this
                         works well because it prevents the "implementation detail" of type namespaces from leaking into your
                         Swagger docs and UI. However,if you have multiple types in your API with the same class name,you'll
                         need to opt out of this behavior to avoid Schema Id conflicts.
                        c.UseFullTypeNameInSchemaIds();

                         Alternatively,you can provide your own custom strategy for inferring SchemaId's for
                         describing "complex" types in your API.
                        c.SchemaId(t => t.FullName.Contains('`') ? t.FullName.Substring(0,t.FullName.IndexOf('`')) : t.FullName);

                         Set this flag to omit schema property descriptions for any type properties decorated with the
                         Obsolete attribute
                        c.IgnoreObsoleteProperties();

                         In accordance with the built in JsonSerializer,Swashbuckle will,by default,describe enums as integers.
                         You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given
                         enum type. Swashbuckle will honor this change out-of-the-Box. However,if you use a different
                         approach to serialize enums as strings,you can also force Swashbuckle to describe them as strings.
                        c.DescribeAllEnumsAsstrings();

                         Similar to Schema filters,Swashbuckle also supports Operation and Document filters:
                         Post-modify Operation descriptions once they've been generated by wiring up one or more
                         Operation filters.
                        c.OperationFilter<AddDefaultResponse>();
                         If you've defined an OAuth2 flow as described above,you Could use a custom filter
                         to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required
                         to execute the operation
                        c.OperationFilter<AssignOAuth2SecurityRequirements>();

                         Post-modify the entire Swagger document by wiring up one or more Document filters.
                         This gives full control to modify the final SwaggerDocument. You should have a good understanding of
                         the Swagger 2.0 spec. - https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md
                         before using this option.
                        c.DocumentFilter<ApplyDocumentvendorExtensions>();

                         In contrast to WebApi,Swagger 2.0 does not include the query string component when mapping a URL
                         to an action. As a result,Swashbuckle will raise an exception if it encounters multiple actions
                         with the same path (sans query string) and HTTP method. You can workaround this by providing a
                         custom strategy to pick a winner or merge the descriptions for the purposes of the Swagger docs
                        c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());

                         Wrap the default SwaggerGenerator with additional behavior (e.g. caching) or provide an
                         alternative implementation for ISwaggerProvider with the CustomProvider option.
                        c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));
                    })
                .EnableSwaggerUi(c => Use the "DocumentTitle" option to change the Document title.
                         Very helpful when you have multiple Swagger pages open,to tell them apart.
                        c.DocumentTitle("My Swagger UI");

                         Use the "InjectStylesheet" option to enrich the UI with one or more additional CSS stylesheets.
                         The file must be included in your project as an "Embedded Resource",and then the resource's
                         "Logical Name" is passed to the method as shown below.
                        c.InjectStylesheet(containingAssembly,"Swashbuckle.Dummy.SwaggerExtensions.testStyles1.css");

                         Use the "InjectJavaScript" option to invoke one or more custom JavaScripts after the swagger-ui
                         has loaded. The file must be included in your project as an "Embedded Resource",1)"> "Logical Name" is passed to the method as shown above.
                        c.InjectJavaScript(thisAssembly,"Swashbuckle.Dummy.SwaggerExtensions.testScript1.js");

                         The swagger-ui renders boolean data types as a dropdown. By default,it provides "true" and "false"
                         strings as the possible choices. You can use this option to change these to something else,1)"> for example 0 and 1.
                        c.BooleanValues(new[] { "0","1" });

                        pecs against swagger.io's online validator and display the result
                         in a badge at the bottom of the page. Use these options to set a different validator URL or to disable the
                         feature entirely.
                        c.SetValidatorUrl("http://localhost/validator");
                        c.disableValidator();

                         Use this option to control how the Operation listing is displayed.
                         It can be set to "None" (default),"List" (shows operations for each resource),1)"> or "Full" (fully expanded: shows operations and their details).
                        c.DocExpansion(DocExpansion.List);

                         Specify which HTTP operations will have the 'Try it out!' option. An empty paramter list disables
                         it for all operations.
                        c.SupportedSubmitMethods("GET","HEAD");

                         Use the CustomAsset option to provide your own version of assets used in the swagger-ui.
                         It's typically used to instruct Swashbuckle to return your version instead of the default
                         when a request is made for "index.html". As with all custom content,the file must be included
                         in your project as an "Embedded Resource",and then the resource's "Logical Name" is passed to
                         the method as shown below.
                        c.CustomAsset("index",containingAssembly,"YourWebApiProject.SwaggerExtensions.index.html");

                         If your API has multiple versions and you've applied the MultipleApiVersions setting
                         as described above,you can also enable a select Box in the swagger-ui,that displays
                         a discovery URL for each version. This provides a convenient way for users to browse documentation
                         for different API versions.
                        c.EnablediscoveryUrlSelector();

                         If your API supports the OAuth2 Implicit flow,and you've described it correctly,according to
                         the Swagger 2.0 specification,you can enable UI support as shown below.
                        c.EnableOAuth2Support(
                            clientId: "test-client-id",1)">    clientSecret: null,1)">    realm: "test-realm",1)">    appName: "Swagger UI"
                        additionalQueryStringParams: new Dictionary<string,string>() { { "foo","bar" } }
                        );

                         If your API supports ApiKey,you can override the default values.
                         "apiKeyIn" can either be "query" or "header"
                        c.EnableApiKeySupport("apiKey","header");

                        c.InjectJavaScript(thisAssembly,1)">WebApiDemo.Swagger.swagger.js"); 汉化Swagger两步:第二步
                    });
        }
    }
}
View Code

辅助类XmlUtil.cs

 XML工具类
     XmlUtil
    {
         从XML读取注释
        <returns></returns>
        static Dictionary< GetActionDesc()
        {
            Dictionary<string> result = string xmlPath = (XmlUtil).Assembly.GetName().Name);
             (File.Exists(xmlPath))
            {
                XmlDocument xmlDoc =  XmlDocument();
                xmlDoc.Load(xmlPath);

                XmlNode summaryNode; string type; string desc; int pos;  key;
                in xmlDoc.SelectNodes())
                {
                    type = type = node.Attributes[M:PrisonWebApi.Controllers))
                    {
                        pos = type.IndexOf((if (pos == -1) pos = type.Length;
                        key = type.Substring(2,pos - 2);
                        summaryNode = node.SelectSingleNode();
                        desc = summaryNode.InnerText.Trim();
                        result.Add(key,desc);
                    }
                }
            }

             result;
        }
    }
}
View Code

WebApiHost工程的App.config

WebApiDemo工程的Global.asax.cs和Web.config文件没有用了 

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  startup>
    supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
  </appSettings<!--Web API 服务端口号-->
    add key="WebApiServicePort" value="8500" >
>
View Code

 在线文档截图

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐