美文网首页dotNET技术初心
Swagger for Asp.net 应用笔记

Swagger for Asp.net 应用笔记

作者: 灭蒙鸟 | 来源:发表于2016-08-31 15:40 被阅读3441次

简介

一直听说Swagger是做Web API文档的好工具,正好手头一个项目使用WebApi,决定使用Swagger来文档化接口,作为和前端交流的基础。下面是使用Swashbuckle.net 给ASP.net web API添加文档的简要步骤。

使用中如果碰到任何问题欢迎评论,一起讨论解决

项目引入Swagger

Swashbuckle是Swagger在dotnet环境中的实现,在ASP.net项目中加入后即可支持Swagger/UI。5.X版本支持ASP.net, 6.X(beta)版本支持ASP.net Core. 目前项目使用ASP.net for IIS,所以使用了5.4的版本。 关于selfhost和Owin Swashbuckle 的readme有很清楚的描述,可以自行查看。

使用nuget加入Swashbuckle的引用。
Paste_Image.png

安装好以后,在App_Start目录下,会有一个SwaggerConfig.cs文件,SwaggerConfig类通过[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]启动时运行。

nuget添加完引用,无须任何配置,编译后,访问 http://yoururl/swagger 即可看到所有API的文档说明,当然说明都很简单,没有太大价值。

SwaggerConfig简单介绍

SwaggerConfig.cs文件会自动添加到项目的App_Start目录下,代码本身包含大量注释掉的代码,清除后,代码如下:

 public class SwaggerConfig
   {
       public static void Register()
       {
           var thisAssembly = typeof(SwaggerConfig).Assembly;
            GlobalConfiguration.Configuration
               .EnableSwagger(c =>//用于启用和设置Swagger的配置信息。
                   {
                       c.SingleApiVersion("v1", "Cxx.xxx.Web");       
                      //a#                
                   })
               .EnableSwaggerUi(c =>
                   {//用于启用UI界面上的东西。
                      //b#
                  });
       }
   }
支持XML注释

使用Swagger的目的就是希望把代码中方法和类型的注释自动导出来。在Swashbuckle中,很简单。

  • 相关工程需要生成XML文档


    Paste_Image.png
  • 在Swagger.Config的Register方法的EnableSwagger匿名函数中加上对应的XML文件(可以添加在//a#代码后面。)

var baseDirectory = AppDomain.CurrentDomain.BaseDirectory +"\\bin\\"; var commentsFileName = Assembly.GetExecutingAssembly().GetName().Name + ".XML"; var commentsFile = Path.Combine(baseDirectory, commentsFileName); c.IncludeXmlComments(commentsFile);

上述代码把Web工程的XML注释加入到Swagger中。一般我们会把viewmodel或者其他类型定义在不同的工程中,通过下面的代码可以继续加入其它xml注释文件。(对应功能需要启用XML文档文件生成)
c.IncludeXmlComments(Path.Combine(baseDirectory, "CrXX.XX.xml"));

实现默认调用参数

Swagger本身支持直接调用,但是调用参数需要手动编写,一个比较简单的办法是自定义一个attribute,给viewmodel的参数加上默认参数。

  • 首先增加一个Swagger属性如下图:

     public class SwaggerDefaultValue : Attribute
     {
          public string Name { get; set; }
          public string Value { get; set; }
          public SwaggerDefaultValue(string value)
          {
              this.Value = value;
          }
    
          public SwaggerDefaultValue(string name, string value) : this(value)
          {
              this.Name = name;
          }
    }
    
  • 增加一个AddDefaultValues类,如下面代码

      public class AddDefaultValues : IOperationFilter
      {
        public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription     apiDescription)
        {
 
            IDictionary<string, object> parameterValuePairs =
            GetParameterValuePairs(apiDescription.ActionDescriptor);
            if (operation?.parameters != null)
            {
 
                foreach (var param in operation.parameters)
                {
                    if (param.schema != null && param.schema.@ref != null)
                    {
                        string schemaName = param.schema.@ref.Split('/').LastOrDefault();
                        if (schemaRegistry.Definitions.ContainsKey(schemaName))
                            foreach (var props in schemaRegistry.Definitions[schemaName].properties)
                            {
                                if (parameterValuePairs.ContainsKey(props.Key.ToLower()))//默认会转换为camelcase,所以强行转为小写
                                    props.Value.@default = parameterValuePairs[props.Key.ToLower()];//默认会转换为camelcase,所以强行转为小写
                            }
                    }
                    var parameterValuePair = parameterValuePairs.FirstOrDefault(p =>   p.Key.IndexOf(param.name, StringComparison.InvariantCultureIgnoreCase) >= 0);
                    param.@default = parameterValuePair.Value;
                }
            }
        }
 
      private IDictionary<string, object> GetParameterValuePairs(HttpActionDescriptor actionDescriptor)
      {
        IDictionary<string, object> parameterValuePairs = new Dictionary<string, object>();
 
        foreach (SwaggerDefaultValue defaultValue in actionDescriptor.GetCustomAttributes<SwaggerDefaultValue>())
        {
            parameterValuePairs.Add(defaultValue.Name, defaultValue.Value);
        }
 
        foreach (var parameter in actionDescriptor.GetParameters())
        {
            if (!parameter.ParameterType.IsPrimitive)
            {
                InitialType(parameterValuePairs, parameter.ParameterType);
            }
        }
 
        return parameterValuePairs;
      }
 
      void InitialType(IDictionary<string, object> parameterValuePairs, Type t)
      {
        foreach (PropertyInfo property in t.GetProperties())
        {
            var defaultValue = GetDefaultValue(property);
 
            if (defaultValue != null)
            {
 
                parameterValuePairs.Add(property.Name.ToLower(), defaultValue);//默认会转换为camelcase,所以强行转为小写
            }
        }
      }
 
      private static object GetDefaultValue(PropertyInfo property)
      {
        var customAttribute = property.GetCustomAttributes<SwaggerDefaultValue>().FirstOrDefault();
 
        if (customAttribute != null)
        {
            return customAttribute.Value;
        }
 
        return null;
      }  
}
  • 在Swagger.Config的Register方法的EnableSwagger匿名函数中对应的过滤器(可以添加在//a#代码后面。)
    c.OperationFilter<AddDefaultValues>();

  • 在具体的调用参数上加上默认参数,在swagger的界面上就会有默认参数啦。

 public class CheckMobile
 {
       [SwaggerDefaultValue("13482894351")]
       [Required]
       public string Mobile { get; set; }   
}
实现Oauth2 API的调用

我们的WebAPI基于OAuth2的验证,所以Swagger上并不能直接调用。如果希望Swagger能直接调用OAuth2保护的API。

  • 增加一个js到Web工程中, zhe


    Paste_Image.png

*js的内容如下

$('#input_apiKey').change(function () {
    var key = $('#input_apiKey')[0].value;
    var credentials = key.split(':'); //username:password expected
    $.ajax({
        url: "/Token",
        type: "post",
        contenttype: 'x-www-form-urlencoded',
        data: "grant_type=password&username=" + credentials[0] + "&password=" + credentials[1],
        success: function (response) {
            
            var bearerToken = 'Bearer ' + response.access_token;
            swaggerUi.api.clientAuthorizations.add('key', new SwaggerClient.ApiKeyAuthorization('Authorization', bearerToken, 'header'));
            
        },
        error: function (xhr, ajaxoptions, thrownerror) {
            alert("输入的用户名密码不对,不能登陆!");
        }
    });
});```
*在Swagger.config 的Register方法的EanbleSwaggerUI匿名函数中加上对应的JS,可以加在//b#后面
`c.InjectJavaScript(typeof(SwaggerConfig).Assembly, "CrXXX.XX.SwaggerLogin.js");`
>CrXXX.XX 需要改成web工程的名字

在Swagger界面上的API_Key输入框输入oauth2的用户名密码即可登录.

上面描述的是使用ASP.net 自带的OAuth认证库,不是真正的oauth2,如果采用IdenittyServer3的认证方法,需要参照[教程](http://knowyourtoolset.com/2015/08/secure-web-apis-with-swagger-swashbuckle-and-oauth2-part-2/) 来实现, 我会尽快翻译.
使用上面的方法要注意的是,在IdentityServer中的设置里面,Client需要
允许重定向到 "http://WebAPI地址/swagger/ui/o2c-html"

##### Swagger API文档的效果图

![Paste_Image.png](https://img.haomeiwen.com/i1697920/057deb18522917ce.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

相关文章

网友评论

    本文标题:Swagger for Asp.net 应用笔记

    本文链接:https://www.haomeiwen.com/subject/xbgqettx.html