123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.ComponentModel.DataAnnotations;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Net.Http;
- using System.Runtime.Remoting.Contexts;
- using System.Text;
- using System.Web.Http;
- using System.Web.Http.Description;
- using System.Web.Http.Filters;
- using System.Web.Http.Metadata;
- using System.Web.Http.Routing;
- using System.Web.Http.Validation;
- using System.Web.Http.Validation.Providers;
- using System.Xml;
- using Microsoft.Owin;
- using Microsoft.Owin.Cors;
- using Newtonsoft.Json;
- using Newtonsoft.Json.Serialization;
- using Owin;
- using Swashbuckle.Application;
- using Swashbuckle.Swagger;
- using XdCxRhDW.App.WebAPI;
- [assembly: OwinStartup(typeof(XdCxRhDW.App.WebAPI.Startup))]
- namespace XdCxRhDW.App.WebAPI
- {
- class Startup
- {
- public void Configuration(IAppBuilder app)
- {
- HttpConfiguration config = new HttpConfiguration();
- IEnumerable<ModelValidatorProvider> modelValidatorProviders = config.Services.GetModelValidatorProviders();
- DataAnnotationsModelValidatorProvider provider = (DataAnnotationsModelValidatorProvider)
- modelValidatorProviders.Single(x => x is DataAnnotationsModelValidatorProvider);
- provider.RegisterDefaultValidatableObjectAdapter(typeof(CustomModelValidator));
- JsonSerializerSettings setting = new JsonSerializerSettings()
- {
- //日期类型默认格式化处理
- DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
- DateFormatString = "yyyy-MM-dd HH:mm:ss",
- //驼峰样式
- ContractResolver = new CamelCasePropertyNamesContractResolver(),
- //空值处理
- //NullValueHandling = NullValueHandling.Ignore,
- //设置序列化的最大层数
- MaxDepth = 10,
- //解决json序列化时的循环引用问题
- ReferenceLoopHandling = ReferenceLoopHandling.Ignore
- };
- config.Formatters.JsonFormatter.SerializerSettings = setting;
- config.Formatters.Remove(config.Formatters.XmlFormatter);
- config.Filters.Add(new HandlerErrorAttribute());
- //config.Routes.MapHttpRoute("DefaultApiWithId", "Api/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = @"\d+" });
- config.Routes.MapHttpRoute("DefaultApiWithAction", "Api/{controller}/{action}");
- //config.Routes.MapHttpRoute("DefaultApiGet", "Api/{controller}", new { action = "Get" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) });
- //config.Routes.MapHttpRoute("DefaultApiPost", "Api/{controller}", new { action = "Post" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) });
- ConfigureSwagger(config);
- //添加路由路径
- config.MapHttpAttributeRoutes();
- app.UseCors(CorsOptions.AllowAll);
- //app.Use<LoggingMiddleware>();
- app.UseWebApi(config);
- }
- private static void ConfigureSwagger(HttpConfiguration config)
- {
- var thisAssembly = typeof(Startup).Assembly;
- config.EnableSwagger(c =>
- {
- c.SingleApiVersion("v1", "多模式融合定位平台Http接口");
- //设置接口描述xml路径地址
- var webApiXmlPath1 = $"{AppDomain.CurrentDomain.BaseDirectory}{Path.GetFileNameWithoutExtension(System.AppDomain.CurrentDomain.FriendlyName)}.xml";
- c.IncludeXmlComments(webApiXmlPath1);
- var webApiXmlPath2 = $"{AppDomain.CurrentDomain.BaseDirectory}XdCxRhDw.Dto.xml";
- c.IncludeXmlComments(webApiXmlPath2);
- c.UseFullTypeNameInSchemaIds();
- //加入控制器描述
- c.CustomProvider((defaultProvider) => new SwaggerControllerDescProvider(defaultProvider, webApiXmlPath1));
- c.OperationFilter<FileUploadOperation>();
- })
- .EnableSwaggerUi(c =>
- {
- c.InjectJavaScript(thisAssembly, "XdCxRhDW.App.WebAPI.Swagger.js");
- c.DocumentTitle("");
- });
- }
- /// <summary>
- /// Swagger文件上传特性标注
- /// </summary>
- [AttributeUsage(AttributeTargets.Method)]
- public sealed class SwaggerFormAttribute : Attribute
- {
- public SwaggerFormAttribute()
- {
- this.Name = "文件";
- this.Description = "选择文件";
- }
- /// <summary>
- /// Swagger特性标注
- /// </summary>
- /// <param name="name"></param>
- /// <param name="description"></param>
- public SwaggerFormAttribute(string name, string description)
- {
- Name = name;
- Description = description;
- }
- /// <summary>
- /// 名称
- /// </summary>
- public string Name { get; private set; }
- /// <summary>
- /// 描述
- /// </summary>
- public string Description { get; private set; }
- }
-
- public class FileUploadOperation : IOperationFilter
- {
- public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
- {
- if (operation.parameters == null)
- {
- operation.parameters = new List<Parameter>();
- }
- var requestAttributes = apiDescription.GetControllerAndActionAttributes<SwaggerFormAttribute>();
- foreach (var attr in requestAttributes)
- {
- operation.parameters.Add(new Parameter
- {
- description = attr.Description,
- name = attr.Name,
- @in = "formData",
- required = true,
- type = "file",
- });
- operation.consumes.Add("multipart/form-data");
- }
- //if (operation.operationId.ToLower() == "apivaluesuploadpost")
- //{
- // operation.parameters.Clear();
- // operation.parameters.Add(new Parameter
- // {
- // name = "uploadedFile",
- // @in = "formData",
- // description = "Upload File",
- // required = true,
- // type = "file"
- // });
- // operation.consumes.Add("multipart/form-data");
- //}
- //判断上传文件的类型,只有上传的类型是IFormCollection的才进行重写。
- //var paras = apiDescription.ActionDescriptor.GetParameters();
- //if (paras.Any(w => w.ParameterType == typeof(IFormCollection)))
- //{
- // Dictionary<string, OpenApiSchema> schema = new Dictionary<string, OpenApiSchema>();
- // schema["fileName"] = new OpenApiSchema { Description = "Select file", Type = "string", Format = "binary" };
- // Dictionary<string, OpenApiMediaType> content = new Dictionary<string, OpenApiMediaType>();
- // content["multipart/form-data"] = new OpenApiMediaType { Schema = new OpenApiSchema { Type = "object", Properties = schema } };
- // operation.RequestBody = new OpenApiRequestBody() { Content = content };
- //}
- }
- }
- public class HandlerErrorAttribute : ExceptionFilterAttribute
- {
- /// <summary>
- /// 控制器方法中出现异常,会调用该方法捕获异常
- /// </summary>
- /// <param name="context">提供使用</param>
- public override void OnException(HttpActionExecutedContext context)
- {
- base.OnException(context);
- Serilog.Log.Error(context.Exception, context.Exception.Message);
- //LogFile.WriteError(context.Exception.Message);
- throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.OK)
- {
- Content = new StringContent(
- JsonConvert.SerializeObject(
- new
- {
- code = -1,
- data = "",
- msg = context.Exception.Message
- }), Encoding.UTF8, "text/json")
- });
- }
- };
- public class SwaggerControllerDescProvider : ISwaggerProvider
- {
- private readonly ISwaggerProvider _swaggerProvider;
- private static ConcurrentDictionary<string, SwaggerDocument> _cache = new ConcurrentDictionary<string, SwaggerDocument>();
- private readonly string _xml;
- /// <summary>
- ///
- /// </summary>
- /// <param name="swaggerProvider"></param>
- /// <param name="xml">xml文档路径</param>
- public SwaggerControllerDescProvider(ISwaggerProvider swaggerProvider, string xml)
- {
- _swaggerProvider = swaggerProvider;
- _xml = xml;
- }
- public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
- {
- var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);
- SwaggerDocument srcDoc = null;
- //只读取一次
- if (!_cache.TryGetValue(cacheKey, out srcDoc))
- {
- srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);
- srcDoc.vendorExtensions = new Dictionary<string, object> { { "ControllerDesc", GetControllerDesc() } };
- _cache.TryAdd(cacheKey, srcDoc);
- }
- return srcDoc;
- }
- /// <summary>
- /// 从API文档中读取控制器描述
- /// </summary>
- /// <returns>所有控制器描述</returns>
- public ConcurrentDictionary<string, string> GetControllerDesc()
- {
- string xmlpath = _xml;
- ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>();
- if (File.Exists(xmlpath))
- {
- XmlDocument xmldoc = new XmlDocument();
- xmldoc.Load(xmlpath);
- string type = string.Empty, path = string.Empty, controllerName = string.Empty;
- string[] arrPath;
- int length = -1, cCount = "Controller".Length;
- XmlNode summaryNode = null;
- 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("Controller"))
- {
- //获取控制器注释
- 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());
- }
- }
- }
- }
- }
- return controllerDescDict;
- }
- }
- }
- public class CustomModelValidator : ModelValidator
- {
- public CustomModelValidator(IEnumerable<ModelValidatorProvider> modelValidatorProviders) : base(modelValidatorProviders)
- {
- }
- public override IEnumerable<ModelValidationResult> Validate(ModelMetadata metadata, object container)
- {
- if (metadata.IsComplexType && metadata.Model == null)
- {
- return new List<ModelValidationResult> { new ModelValidationResult { MemberName = metadata.GetDisplayName(), Message = "请求参数对象不能为空。" } };
- }
- if (typeof(IValidatableObject).IsAssignableFrom(metadata.ModelType))
- {
- var validationResult = (metadata.Model as IValidatableObject).Validate(new ValidationContext(metadata.Model));
- if (validationResult != null)
- {
- var modelValidationResults = new List<ModelValidationResult>();
- foreach (var result in validationResult)
- {
- modelValidationResults.Add(new ModelValidationResult
- {
- MemberName = string.Join(",", result.MemberNames),
- Message = result.ErrorMessage
- });
- }
- return modelValidationResults;
- }
- return null;
- }
- return GetModelValidator(ValidatorProviders).Validate(metadata, container);
- }
- }
- }
|