自定义WebAPI接口帮助文档

自定义WebAPI接口帮助文档

环境:VS2013

搭建项目框架如下:


Web为WebAPI接口层,Model层用于存放接口的输入输出参数

在网上参考了很多文档,把help page改造方法整理如下:

1.使用nuget安装的最新的help page

vs2013在创建webAPI项目时是默认安装了help page的,不过生成的帮助文档不符合我们需要,可以卸载掉然后安装2.2版本的


搜索help page,找到安装即可


2.添加多文件支持类

在WebAPI项目Areas/HelpPage下添加类文件MultiXmlDocumentationProvider.cs


类内容如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Description;

namespace PP.JiJin.Web.Areas.HelpPage
{
    /// <summary>
    /// A custom <see cref="IDocumentationProvider"/> that reads the API documentation from a collection of XML documentation files. 
    /// </summary>
    public class MultiXmlDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider
    {
        /********* 
        ** Properties 
        *********/
        /// <summary>The internal documentation providers for specific files.</summary>  
        private readonly XmlDocumentationProvider[] Providers;


        /********* 
        ** Public methods 
        *********/
        /// <summary>Construct an instance.</summary>  
        /// <param name="paths">The physical paths to the XML documents.</param>  
        public MultiXmlDocumentationProvider(params string[] paths)
        {
            this.Providers = paths.Select(p => new XmlDocumentationProvider(p)).ToArray();
        }

        /// <summary>Gets the documentation for a subject.</summary>  
        /// <param name="subject">The subject to document.</param>  
        public string GetDocumentation(MemberInfo subject)
        {
            return this.GetFirstMatch(p => p.GetDocumentation(subject));
        }

        /// <summary>Gets the documentation for a subject.</summary>  
        /// <param name="subject">The subject to document.</param>  
        public string GetDocumentation(Type subject)
        {
            return this.GetFirstMatch(p => p.GetDocumentation(subject));
        }

        /// <summary>Gets the documentation for a subject.</summary>  
        /// <param name="subject">The subject to document.</param>  
        public string GetDocumentation(HttpControllerDescriptor subject)
        {
            return this.GetFirstMatch(p => p.GetDocumentation(subject));
        }

        /// <summary>Gets the documentation for a subject.</summary>  
        /// <param name="subject">The subject to document.</param>  
        public string GetDocumentation(HttpActionDescriptor subject)
        {
            return this.GetFirstMatch(p => p.GetDocumentation(subject));
        }

        /// <summary>Gets the documentation for a subject.</summary>  
        /// <param name="subject">The subject to document.</param>  
        public string GetDocumentation(HttpParameterDescriptor subject)
        {
            return this.GetFirstMatch(p => p.GetDocumentation(subject));
        }

        /// <summary>Gets the documentation for a subject.</summary>  
        /// <param name="subject">The subject to document.</param>  
        public string GetResponseDocumentation(HttpActionDescriptor subject)
        {
            return this.GetFirstMatch(p => p.GetDocumentation(subject));
        }


        /********* 
        ** Private methods 
        *********/
        /// <summary>Get the first valid result from the collection of XML documentation providers.</summary>  
        /// <param name="expr">The method to invoke.</param>  
        private string GetFirstMatch(Func<XmlDocumentationProvider, string> expr)
        {
            return this.Providers
                .Select(expr)
                .FirstOrDefault(p => !String.IsNullOrWhiteSpace(p));
        }
    } 
}

点击类中报错的地方,根据VS智能提示添加对应引用即可

3.修改项目生成输出XML文件

本例中,接口引用的输入输出参数类在另外一个子项目PP.TradeCenter.Model中,因此,右键PP.TradeCenter.Model子项目→属性


勾选“XML文档文件”,填写生成的xml文件路径,本例指定为App_Data\XmlDocument.xml

同理,对WebAPI项目做同样的修改


然后在WebAPI项目属性的生成事件中添加命令:

copy "$(SolutionDir)PP.TradeCenter.Model\App_Data\XmlDocument.xml" "$(ProjectDir)\App_Data\PP.TradeCenter.Model.XmlDocument.xml"


这条命令的含义是在项目生成时,将PP.TradeCenter.Model子项目中App_Data文件夹下XmlDocument.xml文件复制到当前子项目(即PP.TradeCenter.Web)的App_Data文件夹下,并重命名为PP.TradeCenter.Model.XmlDocument.xml

使用时将PP.TradeCenter.Model改成自己Model项目名称即可,PP.TradeCenter.Model.XmlDocument.xml这个文件名也可以根据自己需要命名,下一步注册时候需要使用

4.修改WebAPI项目下HelpPage的配置文件


增加一行代码:

config.SetDocumentationProvider(new MultiXmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml"), HttpContext.Current.Server.MapPath("~/App_Data/PP.TradeCenter.Model.XmlDocument.xml")));


这行代码里的两个xml文件名字需要和上一步子项目生成属性中配置的一致。

5.修改WebAPI的默认路由


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

VS2013创建的WebAPI项目默认的路由是没有action的,这个有点小坑

到这里已经配置完成了,生成项目即可

新建一个API控制器



最终生成的help文档如下:



6.输入参数验证

对接口的输入参数进行验证可以保证接口的安全

右键Model项目,添加引用



勾选对System.ComponentModel.DataAnnotations的引用,确认

然后我们右键这个添加的引用,选择“在对象浏览器中查看”


可以看到很多验证供选择:常用的有Require必填,Range验证数字范围,StringLength验证字符串长度,MaxLength最大长度、MinLength最小长度,Phone验证手机号,Email验证邮件地址,复杂的可以使用RegularExpression正则表达式验证


使用也比较方便,在输入参数对应属性上加上验证特性即可,示例如下:


验证添加完以后还不会生效,我们还需要把这些验证进行注册,微软官网示例的用法是在调用的类上加上

[MetadataType(typeof(input类名))]

webapi的用法参考:https://docs.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api

这里对输入参数验证进行一些整合

(1)在Model中Output中添加InputParamInvalidInfoOutput类、Result类、BusinessState类


InputParamInvalidInfoOutput类内容如下:

    /// <summary>
    /// Web Api输入参数异常信息
    /// </summary>
    public class InputParamInvalidInfoOutput
    {
        /// <summary>
        /// 输入参数
        /// </summary>
        public string Key { set; get; }

        /// <summary>
        /// 错误列表
        /// </summary>
        public List<string> Errors { set; get; }
    }

Result类,用于封装API接口返回结果内容如下:

    /// <summary>
    /// 返回结果
    /// </summary>
    public class Result
    {
        private int code = BusinessState.RESULT_UnLogin.Code;
        object body = new { };
        /// <summary>
        /// 业务码
        /// </summary>
        public int Code
        {
            get { return code; }
            set { code = value; }
        }
        /// <summary>
        /// 业务信息
        /// </summary>
        public string Msg { get; set; }
        /// <summary>
        /// 数据实体
        /// </summary>
        public object Body
        {
            get { return body; }
            set { body = value; }
        }
    }

    /// <summary>
    /// 返回结果
    /// </summary>
    /// <typeparam name="T">数据实体类型</typeparam>
    public class Result<T>
    {
        private int code = BusinessState.RESULT_UnLogin.Code;
        /// <summary>
        /// 业务码
        /// </summary>
        public int Code
        {
            get { return code; }
            set { code = value; }
        }
        /// <summary>
        /// 业务信息
        /// </summary>
        public string Msg { get; set; }

        T body = default(T);
        /// <summary>
        /// 数据实体
        /// </summary>
        public T Body
        {
            get { return body; }
            set { body = value; }

        }
    }

BusinessState类,用于定义Result类的Code属性编码

    /// <summary>
    /// 业务编码和提示信息
    /// </summary>
    public class CodeMsg
    {
        public CodeMsg(int code, string msg)
        {
            Code = code;
            Msg = msg;
        }
        /// <summary>
        /// 业务码
        /// </summary>
        public int Code { get; set; }
        /// <summary>
        /// 业务消息
        /// </summary>
        public string Msg { get; set; }
    }
    public class BusinessState
    {
        /// <summary>
        /// 成功结果
        /// </summary>
        public static CodeMsg SUCC = new CodeMsg(0, "成功");

        /// <summary>
        /// token过期
        /// </summary>
        public static CodeMsg RESULT_TOKEN_TIMEOUT = new CodeMsg(1, "请重新登录");//token过期
        public static CodeMsg RESULT_UnLogin = new CodeMsg(2, "未登录");
        public static CodeMsg RESULT_TOKEN_LOST = new CodeMsg(3, "请重新登录");//token失效
        public static CodeMsg RESULT_EXCEPTION = new CodeMsg(4, "系统异常,稍后重试");
        public static CodeMsg PARAM_INPUT_MODEL_INVALID = new CodeMsg(5, "查询参数无效,");
    }

(2)在webAPI子项目下新建Filter文件夹,添加类ValidateModelAttribute

ValidateModelAttribute类内容如下:

    public class ValidateModelAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (actionContext.ModelState.IsValid == false)
            {
                //获取model验证失败字段
                List<InputParamInvalidInfoOutput> errorList = new List<InputParamInvalidInfoOutput>();
                foreach(var key in actionContext.ModelState.Keys){
                    InputParamInvalidInfoOutput errorItem = new InputParamInvalidInfoOutput() { Key = string.Empty, Errors = new List<string>() };
                    errorItem.Key = key;
                    foreach (var error in actionContext.ModelState[key].Errors)
                    {
                        errorItem.Errors.Add(error.ErrorMessage);
                    }
                    errorList.Add(errorItem);
                }
                ErrorObj errObj = new ErrorObj() { ErrorList = errorList };
                var result = new Result<ErrorObj>()
                    {
                        Code = BusinessState.PARAM_INPUT_MODEL_INVALID.Code,
                        Msg = BusinessState.PARAM_INPUT_MODEL_INVALID.Msg
,
                        Body = errObj
                    };

                //PP.JiJin.BLL.LogBLL.Error("errObj=" + JsonHelper.Serializer(result));

                //组装Response
                HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);

                response.Content = new ObjectContent<Result<ErrorObj>>(result, new JsonMediaTypeFormatter());
                response.RequestMessage = actionContext.Request;

                //赋值Response
                actionContext.Response = response;
            }
        }

        public class ErrorObj
        {
            public List<InputParamInvalidInfoOutput> ErrorList { set; get; }
        }
(3)在WebAPI项目的路由配置文件中注册Model的验证逻辑



            //注册Model验证逻辑
            config.Filters.Add(new ValidateModelAttribute());

到此大功告成,使用谷歌浏览器插件postman测试下接口:


猜你喜欢

转载自blog.csdn.net/shujudeliu/article/details/80366713
今日推荐