Startup.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.ComponentModel.DataAnnotations;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Net.Http;
  9. using System.Text;
  10. using System.Web.Http;
  11. using System.Web.Http.Filters;
  12. using System.Web.Http.Metadata;
  13. using System.Web.Http.Routing;
  14. using System.Web.Http.Validation;
  15. using System.Web.Http.Validation.Providers;
  16. using System.Xml;
  17. using Microsoft.Owin;
  18. using Microsoft.Owin.Cors;
  19. using Newtonsoft.Json;
  20. using Newtonsoft.Json.Serialization;
  21. using Owin;
  22. using Swashbuckle.Application;
  23. using Swashbuckle.Swagger;
  24. using XdCxRhDW.App.WebAPI;
  25. [assembly: OwinStartup(typeof(XdCxRhDW.App.WebAPI.Startup))]
  26. namespace XdCxRhDW.App.WebAPI
  27. {
  28. class Startup
  29. {
  30. public void Configuration(IAppBuilder app)
  31. {
  32. HttpConfiguration config = new HttpConfiguration();
  33. IEnumerable<ModelValidatorProvider> modelValidatorProviders = config.Services.GetModelValidatorProviders();
  34. DataAnnotationsModelValidatorProvider provider = (DataAnnotationsModelValidatorProvider)
  35. modelValidatorProviders.Single(x => x is DataAnnotationsModelValidatorProvider);
  36. provider.RegisterDefaultValidatableObjectAdapter(typeof(CustomModelValidator));
  37. JsonSerializerSettings setting = new JsonSerializerSettings()
  38. {
  39. //日期类型默认格式化处理
  40. DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
  41. DateFormatString = "yyyy-MM-dd HH:mm:ss",
  42. //驼峰样式
  43. ContractResolver = new CamelCasePropertyNamesContractResolver(),
  44. //空值处理
  45. //NullValueHandling = NullValueHandling.Ignore,
  46. //设置序列化的最大层数
  47. MaxDepth = 10,
  48. //解决json序列化时的循环引用问题
  49. ReferenceLoopHandling = ReferenceLoopHandling.Ignore
  50. };
  51. config.Formatters.JsonFormatter.SerializerSettings = setting;
  52. config.Formatters.Remove(config.Formatters.XmlFormatter);
  53. config.Filters.Add(new HandlerErrorAttribute());
  54. //config.Routes.MapHttpRoute("DefaultApiWithId", "Api/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = @"\d+" });
  55. config.Routes.MapHttpRoute("DefaultApiWithAction", "Api/{controller}/{action}");
  56. //config.Routes.MapHttpRoute("DefaultApiGet", "Api/{controller}", new { action = "Get" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) });
  57. //config.Routes.MapHttpRoute("DefaultApiPost", "Api/{controller}", new { action = "Post" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) });
  58. ConfigureSwagger(config);
  59. //添加路由路径
  60. config.MapHttpAttributeRoutes();
  61. app.UseCors(CorsOptions.AllowAll);
  62. //app.Use<LoggingMiddleware>();
  63. app.UseWebApi(config);
  64. }
  65. private static void ConfigureSwagger(HttpConfiguration config)
  66. {
  67. var thisAssembly = typeof(Startup).Assembly;
  68. config.EnableSwagger(c =>
  69. {
  70. c.SingleApiVersion("v1", "多模式融合定位平台Http接口");
  71. //设置接口描述xml路径地址
  72. var webApiXmlPath1 = $"{AppDomain.CurrentDomain.BaseDirectory}{Path.GetFileNameWithoutExtension(System.AppDomain.CurrentDomain.FriendlyName)}.xml";
  73. c.IncludeXmlComments(webApiXmlPath1);
  74. var webApiXmlPath2 = $"{AppDomain.CurrentDomain.BaseDirectory}XdCxRhDw.Dto.xml";
  75. c.IncludeXmlComments(webApiXmlPath2);
  76. c.UseFullTypeNameInSchemaIds();
  77. //加入控制器描述
  78. c.CustomProvider((defaultProvider) => new SwaggerControllerDescProvider(defaultProvider, webApiXmlPath1));
  79. })
  80. .EnableSwaggerUi(c =>
  81. {
  82. c.InjectJavaScript(thisAssembly, "XdCxRhDW.App.WebAPI.Swagger.js");
  83. c.DocumentTitle("");
  84. });
  85. }
  86. public class HandlerErrorAttribute : ExceptionFilterAttribute
  87. {
  88. /// <summary>
  89. /// 控制器方法中出现异常,会调用该方法捕获异常
  90. /// </summary>
  91. /// <param name="context">提供使用</param>
  92. public override void OnException(HttpActionExecutedContext context)
  93. {
  94. base.OnException(context);
  95. Serilog.Log.Error(context.Exception, context.Exception.Message);
  96. //LogFile.WriteError(context.Exception.Message);
  97. throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.OK)
  98. {
  99. Content = new StringContent(
  100. JsonConvert.SerializeObject(
  101. new
  102. {
  103. code = -1,
  104. data = "",
  105. msg = context.Exception.Message
  106. }), Encoding.UTF8, "text/json")
  107. });
  108. }
  109. };
  110. public class SwaggerControllerDescProvider : ISwaggerProvider
  111. {
  112. private readonly ISwaggerProvider _swaggerProvider;
  113. private static ConcurrentDictionary<string, SwaggerDocument> _cache = new ConcurrentDictionary<string, SwaggerDocument>();
  114. private readonly string _xml;
  115. /// <summary>
  116. ///
  117. /// </summary>
  118. /// <param name="swaggerProvider"></param>
  119. /// <param name="xml">xml文档路径</param>
  120. public SwaggerControllerDescProvider(ISwaggerProvider swaggerProvider, string xml)
  121. {
  122. _swaggerProvider = swaggerProvider;
  123. _xml = xml;
  124. }
  125. public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
  126. {
  127. var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);
  128. SwaggerDocument srcDoc = null;
  129. //只读取一次
  130. if (!_cache.TryGetValue(cacheKey, out srcDoc))
  131. {
  132. srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);
  133. srcDoc.vendorExtensions = new Dictionary<string, object> { { "ControllerDesc", GetControllerDesc() } };
  134. _cache.TryAdd(cacheKey, srcDoc);
  135. }
  136. return srcDoc;
  137. }
  138. /// <summary>
  139. /// 从API文档中读取控制器描述
  140. /// </summary>
  141. /// <returns>所有控制器描述</returns>
  142. public ConcurrentDictionary<string, string> GetControllerDesc()
  143. {
  144. string xmlpath = _xml;
  145. ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>();
  146. if (File.Exists(xmlpath))
  147. {
  148. XmlDocument xmldoc = new XmlDocument();
  149. xmldoc.Load(xmlpath);
  150. string type = string.Empty, path = string.Empty, controllerName = string.Empty;
  151. string[] arrPath;
  152. int length = -1, cCount = "Controller".Length;
  153. XmlNode summaryNode = null;
  154. foreach (XmlNode node in xmldoc.SelectNodes("//member"))
  155. {
  156. type = node.Attributes["name"].Value;
  157. if (type.StartsWith("T:"))
  158. {
  159. //控制器
  160. arrPath = type.Split('.');
  161. length = arrPath.Length;
  162. controllerName = arrPath[length - 1];
  163. if (controllerName.EndsWith("Controller"))
  164. {
  165. //获取控制器注释
  166. summaryNode = node.SelectSingleNode("summary");
  167. string key = controllerName.Remove(controllerName.Length - cCount, cCount);
  168. if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key))
  169. {
  170. controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim());
  171. }
  172. }
  173. }
  174. }
  175. }
  176. return controllerDescDict;
  177. }
  178. }
  179. }
  180. public class CustomModelValidator : ModelValidator
  181. {
  182. public CustomModelValidator(IEnumerable<ModelValidatorProvider> modelValidatorProviders) : base(modelValidatorProviders)
  183. {
  184. }
  185. public override IEnumerable<ModelValidationResult> Validate(ModelMetadata metadata, object container)
  186. {
  187. if (metadata.IsComplexType && metadata.Model == null)
  188. {
  189. return new List<ModelValidationResult> { new ModelValidationResult { MemberName = metadata.GetDisplayName(), Message = "请求参数对象不能为空。" } };
  190. }
  191. if (typeof(IValidatableObject).IsAssignableFrom(metadata.ModelType))
  192. {
  193. var validationResult = (metadata.Model as IValidatableObject).Validate(new ValidationContext(metadata.Model));
  194. if (validationResult != null)
  195. {
  196. var modelValidationResults = new List<ModelValidationResult>();
  197. foreach (var result in validationResult)
  198. {
  199. modelValidationResults.Add(new ModelValidationResult
  200. {
  201. MemberName = string.Join(",", result.MemberNames),
  202. Message = result.ErrorMessage
  203. });
  204. }
  205. return modelValidationResults;
  206. }
  207. return null;
  208. }
  209. return GetModelValidator(ValidatorProviders).Validate(metadata, container);
  210. }
  211. }
  212. }