部署WebApi随笔
一、跨域
NuGet引用Microsoft.AspNet.WebApi.Cors
WebApiConfig.cs中配置:
// Web API 配置和服务 config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
二、清除默认返回XML格式
Global.asax中配置:
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
三、Oracle配置
NuGet引用Oracle.ManagedDataAccess
1、根据插件生成App.config中的配置添加到Web.config中
2、引用Oracle.ManagedDataAccess.Client
四、log4net
1、NuGet引用log4net
2、AssemblyInfo.cs中配置:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.config", Watch = true)]
3、新建Log4Net.config配置文件
属性-复制到输出目录改为如果较新则复制
Log4Net.config中配置:
<!-- Level的级别,由高到低 --> <!-- None > Fatal > ERROR > WARN > DEBUG > INFO > ALL--> <log4net> <!--信息日志类--> <logger name="loginfo"> <level value="INFO" /> <appender-ref ref="InfoAppender" /> </logger> <!--错误日志类--> <logger name="logerror"> <level value="ERROR" /> <appender-ref ref="ErrorAppender" /> </logger> <!--信息日志附加介质--> <!-- name属性指定其名称,type则是log4net.Appender命名空间的一个类的名称--> <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender"> <!--日志输出到exe程序这个相对目录下--> <param name="File" value="Log4Net\\LogInfo\\" /> <!--输出的日志不会覆盖以前的信息--> <param name="AppendToFile" value="true" /> <!--日志文件的最大大小--> <param name="MaximumFileSize" value="2MB" /> <!--备份文件的个数--> <param name="MaxSizeRollBackups" value="10" /> <!--是否使用静态文件名--> <param name="StaticLogFileName" value="false" /> <!--日志文件名--> <param name="DatePattern" value="yyyyMMdd".txt"" /> <!--文件创建的方式--> <param name="RollingStyle" value="Composite" /> <!--过滤器--> <lockingMode type="Asia.Mobile.ApiService.Filter.MinimalLockDeleteEmpty"></lockingMode> <!--信息日志布局--> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="日志时间:%d [%t] <BR>%n日志级别:%-5p <BR>%n日 志 类:%c [%x] <BR>%n%m <BR>%n " /> </layout> </appender> <appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender"> <param name="File" value="Log4Net\\LogError\\" /> <param name="AppendToFile" value="true" /> <param name="MaxSizeRollBackups" value="100" /> <param name="MaxFileSize" value="10240" /> <param name="StaticLogFileName" value="false" /> <param name="DatePattern" value="yyyyMMdd".txt"" /> <param name="RollingStyle" value="Date" /> <lockingMode type="Asia.Mobile.ApiService.Filter.MinimalLockDeleteEmpty"></lockingMode> <!--错误日志布局--> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="<HR COLOR=red>%n异常时间:%d [%t] <BR>%n异常级别:%-5p <BR>%n异 常 类:%c [%x] <BR>%n%m <BR>%n <HR Size=1>" /> </layout> </appender> </log4net>
View Code
4、新增Log4NetHelper.cs帮助类
public class Log4NetHelper { public static readonly log4net.ILog loginfo = log4net.LogManager.GetLogger("loginfo"); public static readonly log4net.ILog logerror = log4net.LogManager.GetLogger("logerror"); public static void WriteLog(string info) { if (loginfo.IsInfoEnabled) { loginfo.Info(info); } } public static void WriteLog(string info, Exception ex) { if (logerror.IsErrorEnabled) { logerror.Error(info, ex); } } }
View Code
5、新建logFilter.cs过滤器
在控制器上添加:[ApiLogFilterAttribute]
五、swagger
1、NuGet引用Swashbuckle
2、新增实现了ISwaggerProvider的接口类:
在App_Start文件夹中添加SwaggerControllerDescProvider.cs
/// <summary> /// 显示swagger控制器的描述 /// </summary> 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; } }
View Code
3、新增SwaggerConfig.js,设置成嵌入式资源
功能:1、汉化 2、界面控制器的面熟
'use strict'; window.SwaggerTranslator = { _words: [], translate: function () { var $this = this; $('[data-sw-translate]').each(function () { $(this).html($this._tryTranslate($(this).html())); $(this).val($this._tryTranslate($(this).val())); $(this).attr('title', $this._tryTranslate($(this).attr('title'))); }); }, setControllerSummary: function () { $.ajax({ type: "get", async: true, url: $("#input_baseUrl").val(), dataType: "json", success: function (data) { var summaryDict = data.ControllerDesc; var id, controllerName, strSummary; $("#resources_container .resource").each(function (i, item) { id = $(item).attr("id"); if (id) { controllerName = id.substring(9); strSummary = summaryDict[controllerName]; if (strSummary) { $(item).children(".heading").children(".options").first().prepend('<li class="controller-summary" title="' + strSummary + '">' + strSummary + '</li>'); } } }); } }); }, _tryTranslate: function (word) { return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word; }, learn: function (wordsMap) { this._words = wordsMap; } }; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated": "警告:已过时", "Implementation Notes": "实现备注", "Response Class": "响应类", "Status": "状态", "Parameters": "参数", "Parameter": "参数", "Value": "值", "Description": "描述", "Parameter Type": "参数类型", "Data Type": "数据类型", "Response Messages": "响应消息", "HTTP Status Code": "HTTP状态码", "Reason": "原因", "Response Model": "响应模型", "Request URL": "请求URL", "Response Body": "响应体", "Response Code": "响应码", "Response Headers": "响应头", "Hide Response": "隐藏响应", "Headers": "头", "Try it out!": "试一下!", "Show/Hide": "显示/隐藏", "List Operations": "显示操作", "Expand Operations": "展开操作", "Raw": "原始", "can't parse JSON. Raw result": "无法解析JSON. 原始结果", "Model Schema": "模型架构", "Model": "模型", "apply": "应用", "Username": "用户名", "Password": "密码", "Terms of service": "服务条款", "Created by": "创建者", "See more at": "查看更多:", "Contact the developer": "联系开发者", "api version": "api版本", "Response Content Type": "响应Content Type", "fetching resource": "正在获取资源", "fetching resource list": "正在获取资源列表", "Explore": "浏览", "Show Swagger Petstore Example Apis": "显示 Swagger Petstore 示例 Apis", "Can't read from server. It may not have the appropriate access-control-origin settings.": "无法从服务器读取。可能没有正确设置access-control-origin。", "Please specify the protocol for": "请指定协议:", "Can't read swagger JSON from": "无法读取swagger JSON于", "Finished Loading Resource Information. Rendering Swagger UI": "已加载资源信息。正在渲染Swagger UI", "Unable to read api": "无法读取api", "from path": "从路径", "server returned": "服务器返回" }); $(function () { window.SwaggerTranslator.translate(); window.SwaggerTranslator.setControllerSummary(); });
View Code
4、配置SwaggerConfig.cs
public class SwaggerConfig { public static void Register() { var thisAssembly = typeof(SwaggerConfig).Assembly; GlobalConfiguration.Configuration .EnableSwagger(c => { c.SingleApiVersion("v1", "Asia.Mobile.ApiService"); //添加下述代码 var xmlFile = string.Format("{0}/bin/Asia.Mobile.ApiService.XML", System.AppDomain.CurrentDomain.BaseDirectory); if (System.IO.File.Exists(xmlFile)) { c.IncludeXmlComments(xmlFile); } c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); c.CustomProvider((defaultProvider) => new SwaggerControllerDescProvider(defaultProvider, xmlFile)); }) .EnableSwaggerUi(c => { c.InjectJavaScript(Assembly.GetExecutingAssembly(), "Asia.Mobile.ApiService.Scripts.SwaggerConfig.js"); }); } }
View Code
5、配置项目的XML文档文件
6、取消警告提示
6、分组
新增描述信息过滤器:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class ControllerGroupAttribute : Attribute { /// <summary> /// 当前Controller所属模块 请用中文 /// </summary> public string GroupName { get; private set; } /// <summary> /// 当前controller用途 请用中文 /// </summary> public string Useage { get; private set; } /// <summary> /// Controller描述信息 构造 /// </summary> /// <param name="groupName">模块名称</param> /// <param name="useage">当前controller用途</param> public ControllerGroupAttribute(string groupName, string useage) { if (string.IsNullOrEmpty(groupName) || string.IsNullOrEmpty(useage)) { throw new ArgumentNullException("groupName||useage"); } GroupName = groupName; Useage = useage; } }
View Code
给Controller加上这个Attribute,再给SwaggerConfig.cs进行分组操作:
c.GroupActionsBy(apiDesc => apiDesc.GetControllerAndActionAttributes<ControllerGroupAttribute>().Any() ? apiDesc.GetControllerAndActionAttributes<ControllerGroupAttribute>().First().GroupName + "_" + apiDesc.GetControllerAndActionAttributes<ControllerGroupAttribute>().First().Useage : "无模块归类");
View Code
赞 (0)