一、下载O/RM框架Nuget包
1、右键解决方案名称,选择"解决方案的Nuget程序包",进行安装。如图:
二、下载PgSql的Nuget包
1、右键解决方案名称,选择"解决方案的Nuget程序包",进行安装。如图:
三、下载AutoFac组件Nuget包
1、右键解决方案名称,选择"解决方案的Nuget程序包",进行安装。如图:
四、下载AutoFac.Mvc5组件Nuget包
1、右键解决方案名称,选择"解决方案的Nuget程序包",进行安装。如图:
五、下载AutoFac.WebApi2组件Nuget包
1、右键解决方案名称,选择"解决方案的Nuget程序包",进行安装。如图:
六、下载Swagger组件Nuget包
1、右键解决方案名称,选择"解决方案的Nuget程序包",进行安装。如图:
七、对各层的引用关系进行配置
1、CK.Project.Web.Core无需引用任何项,默认跳过从CK.Project.Web.Application开始。
2、配置CK.Project.Web.EntityFramework.Core的引用关系
3、配置CK.Project.Web.WebApi的引用关系
八、配置PgSql的仓储类
1、选中CK.Project.Web.EntityFramework.Core,右键选择"新建文件夹",命名为"Repository",如图:
2、选中Repository,右键选择"添加"------>"类",命名为"PgRepository.cs",如图:
3、编写如下代码:
using SqlSugar; using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Text; using System.Threading.Tasks;
namespace CK.Project.Web.EntityFramework.Core { /// <summary> /// PgSql仓储模块 /// </summary> public class PgRepository<T> : SimpleClient<T> where T : class, new() { public PgRepository(ISqlSugarClient context = null) : base(context)//注意这里要有默认值等于null { if (context == null) { base.Context = new SqlSugarClient(new ConnectionConfig() { DbType = SqlSugar.DbType.PostgreSQL,//此处为设置数据库,支持各大主流数据库 InitKeyType = InitKeyType.Attribute,//此处为初始化配置类型,有按特性进行初始化,也有其他的进行初始化 IsAutoCloseConnection = true,//此处为是否自动关闭数据库连接,可以理解为是DBHelper里的Close()方法 MoreSettings = new ConnMoreSettings() { PgSqlIsAutoToLower = true //数据库存在大写字段的 //,需要把这个设为false ,并且实体和字段名称要一样 //如果数据库里的数据表本身就为小写,则改成true //详细可以参考官网https://www.donet5.com/Home/Doc }, ConnectionString = ConfigurationManager.AppSettings["pgsqlStr"] //此处为数据库连接字符串 });
base.Context.Aop.OnError = (ex) =&gt; { //此处为AOP切面编程代码块,常用于数据库连接日志记录 //或者查看详细的报错信息,打印ex的内容即可 }; } } }
}
4、在WebApi层的Web.Config的节点下编写数据库字符串,代码如下:
<add key="pgsqlStr" value="PORT={数据库端口号};DATABASE={数据库名};HOST={IP地址};PASSWORD={数据库密码};USER ID={数据库账号}" />
九、配置AutoFac.IoC依赖注入
1、在CK.Project.Web.WebApi层里的App_Start文件夹中新建名为"AutofacConfig.cs"文件。
2、编写如下代码:
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Web; using System.Web.Http; using System.Web.Mvc; using Autofac; using Autofac.Integration.Mvc; using Autofac.Integration.WebApi; using CK.Project.Web.EntityFramework.Core;
namespace CK.Project.Web.WebApi.App_Start { /// &lt;summary&gt; /// 依赖注入配置类 /// &lt;/summary&gt; public class AutofacConfig { public static void CoreAutoFacInit() { var builder = new ContainerBuilder(); HttpConfiguration config = GlobalConfiguration.Configuration; SetupResolveRules(builder); //注册所有的ApiControllers builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired(); var container = builder.Build(); //注册api容器需要使用HttpConfiguration对象 config.DependencyResolver = new AutofacWebApiDependencyResolver(container); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); } private static void SetupResolveRules(ContainerBuilder builder) { builder.RegisterGeneric(typeof(PgRepository&lt;&gt;)).As(typeof(PgRepository&lt;&gt;)); //WebAPI只用引用services和repository的接口,不用引用实现的dll。 //如需加载实现的程序集,将dll拷贝到bin目录下即可,不用引用dll
// 得到源目录的文件列表,该里面是包含文件以及目录路径的一个数组 string[] fileList = System.IO.Directory.GetFileSystemEntries(System.AppDomain.CurrentDomain.BaseDirectory + &quot;/bin&quot;); // 遍历所有的文件和目录 foreach (string file in fileList) { var _file = file.Substring(file.LastIndexOf(&quot;\\&quot;) + 1); if ((_file.ToUpper().IndexOf(&quot;CK.Project.Web&quot;) == 0 || _file.ToUpper().IndexOf(&quot;CK.PROJECT.WEB&quot;) == 0) &amp;amp;&amp;amp; _file.ToUpper().EndsWith(&quot;.DLL&quot;)) { var Application = Assembly.Load(_file.ToUpper().Replace(&quot;.DLL&quot;, &quot;&quot;)); builder.RegisterAssemblyTypes(Application, Application) .Where(t =&amp;gt; t.Name.EndsWith(&quot;AppService&quot;)) .AsImplementedInterfaces(); } } } }
} </code> </pre>
3、在Global.asax的Application_Start方法中加入如下代码:
//依赖注入 AutofacConfig.CoreAutoFacInit();
十、部署Swagger文档
1、在CK.Project.Web.WebApi层里的App_Start文件夹中新建名为"SwaggerConfig.cs"文件(如果已存在,则无需新建)。
using System.Web.Http; using WebActivatorEx; using CK.Project.Web.WebApi; using Swashbuckle.Application; using CK.Project.Web.WebApi.App_Start;
[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), &quot;Register&quot;)]
namespace CK.Project.Web.WebApi { public class SwaggerConfig { public static void Register() { var thisAssembly = typeof(SwaggerConfig).Assembly; var xmlFile = string.Format(&quot;{0}/bin/CK.Project.Web.WebApi.XML&quot;, System.AppDomain.CurrentDomain.BaseDirectory);
GlobalConfiguration.Configuration .EnableSwagger(c =&amp;amp;gt; { c.SingleApiVersion(&amp;quot;v1&amp;quot;, &amp;quot;CK.Project.Web.WebAPI接口文档&amp;quot;); if (System.IO.File.Exists(xmlFile)) { c.IncludeXmlComments(xmlFile); } // 得到源目录的文件列表,该里面是包含文件以及目录路径的一个数组 string[] fileList = System.IO.Directory.GetFileSystemEntries(System.AppDomain.CurrentDomain.BaseDirectory + &amp;quot;/bin&amp;quot;); // 遍历所有的文件和目录 foreach (string file in fileList) { var _file = file.Substring(file.LastIndexOf(&amp;quot;\\&amp;quot;) + 1); if (_file.ToUpper().IndexOf(&amp;quot;CK.PROJECT.WEB&amp;quot;) == 0) { if (_file.ToUpper().EndsWith(&amp;quot;APPLICATION.XML&amp;quot;) || _file.ToUpper().EndsWith(&amp;quot;CORE.XML&amp;quot;)) { if (System.IO.File.Exists(GetXmlCommentsPath(_file))) { c.IncludeXmlComments(GetXmlCommentsPath(_file)); } } } } c.IncludeXmlComments(string.Format(&amp;quot;{0}/bin/CK.Project.Web.WebApi.XML&amp;quot;, System.AppDomain.CurrentDomain.BaseDirectory)); c.CustomProvider((defaultProvider) =&amp;amp;gt; new CachingSwaggerProvider(defaultProvider)); }) .EnableSwaggerUi(c =&amp;amp;gt; { //路径规则,项目命名空间.文件夹名称.js文件名称 c.InjectJavaScript(thisAssembly, &amp;quot;CK.Project.Web.WebApi.Scripts.Swaggerui.swagger_lang.js&amp;quot;); }); }
private static string GetXmlCommentsPath(string name) { return string.Format(&amp;amp;quot;{0}/bin/{1}&amp;amp;quot;, System.AppDomain.CurrentDomain.BaseDirectory, name); }
}
} &lt;/code&gt; &lt;/pre&gt;
2、在CK.Project.Web.WebApi层里的App_Start文件夹中新建名为"CachingSwaggerProvider.cs"文件。
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Web; using System.Xml; using Swashbuckle.Swagger;
namespace CK.Project.Web.WebApi.App_Start { /// &amp;amp;lt;summary&amp;amp;gt; /// swagger显示控制器的描述 /// &amp;amp;lt;/summary&amp;amp;gt; public class CachingSwaggerProvider : ISwaggerProvider { private static ConcurrentDictionary&amp;amp;lt;string, SwaggerDocument&amp;amp;gt; _cache = new ConcurrentDictionary&amp;amp;lt;string, SwaggerDocument&amp;amp;gt;();
private readonly ISwaggerProvider _swaggerProvider; /// &amp;amp;amp;lt;summary&amp;amp;amp;gt; /// &amp;amp;amp;lt;/summary&amp;amp;amp;gt; /// &amp;amp;amp;lt;param name=&amp;amp;quot;swaggerProvider&amp;amp;quot;&amp;amp;amp;gt;&amp;amp;amp;lt;/param&amp;amp;amp;gt; public CachingSwaggerProvider(ISwaggerProvider swaggerProvider) { _swaggerProvider = swaggerProvider; } /// &amp;amp;amp;lt;summary&amp;amp;amp;gt; /// &amp;amp;amp;lt;/summary&amp;amp;amp;gt; /// &amp;amp;amp;lt;param name=&amp;amp;quot;rootUrl&amp;amp;quot;&amp;amp;amp;gt;&amp;amp;amp;lt;/param&amp;amp;amp;gt; /// &amp;amp;amp;lt;param name=&amp;amp;quot;apiVersion&amp;amp;quot;&amp;amp;amp;gt;&amp;amp;amp;lt;/param&amp;amp;amp;gt; /// &amp;amp;amp;lt;returns&amp;amp;amp;gt;&amp;amp;amp;lt;/returns&amp;amp;amp;gt; public SwaggerDocument GetSwagger(string rootUrl, string apiVersion) { var cacheKey = string.Format(&amp;amp;quot;{0}_{1}&amp;amp;quot;, rootUrl, apiVersion); SwaggerDocument srcDoc = null; //只读取一次 if (!_cache.TryGetValue(cacheKey, out srcDoc)) { srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);
srcDoc.vendorExtensions = new Dictionary&amp;amp;amp;amp;lt;string, object&amp;amp;amp;amp;gt; { { &amp;amp;amp;quot;ControllerDesc&amp;amp;amp;quot;, GetControllerDesc() } }; _cache.TryAdd(cacheKey, srcDoc); } return srcDoc; } /// &amp;amp;amp;amp;lt;summary&amp;amp;amp;amp;gt; /// 从API文档中读取控制器描述 /// &amp;amp;amp;amp;lt;/summary&amp;amp;amp;amp;gt; /// &amp;amp;amp;amp;lt;returns&amp;amp;amp;amp;gt;所有控制器描述&amp;amp;amp;amp;lt;/returns&amp;amp;amp;amp;gt; public static ConcurrentDictionary&amp;amp;amp;amp;lt;string, string&amp;amp;amp;amp;gt; GetControllerDesc() { string xmlpath = string.Format(&amp;amp;amp;quot;{0}/bin/CK.Project.Web.WebApi.XML&amp;amp;amp;quot;, System.AppDomain.CurrentDomain.BaseDirectory); ConcurrentDictionary&amp;amp;amp;amp;lt;string, string&amp;amp;amp;amp;gt; controllerDescDict = new ConcurrentDictionary&amp;amp;amp;amp;lt;string, string&amp;amp;amp;amp;gt;(); 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 = &amp;amp;amp;quot;Controller&amp;amp;amp;quot;.Length; XmlNode summaryNode = null; foreach (XmlNode node in xmldoc.SelectNodes(&amp;amp;amp;quot;//member&amp;amp;amp;quot;)) { type = node.Attributes[&amp;amp;amp;quot;name&amp;amp;amp;quot;].Value; if (type.StartsWith(&amp;amp;amp;quot;T:&amp;amp;amp;quot;)) { //控制器 arrPath = type.Split('.'); length = arrPath.Length; controllerName = arrPath[length - 1]; if (controllerName.EndsWith(&amp;amp;amp;quot;Controller&amp;amp;amp;quot;)) { //获取控制器注释 summaryNode = node.SelectSingleNode(&amp;amp;amp;quot;summary&amp;amp;amp;quot;); string key = controllerName.Remove(controllerName.Length - cCount, cCount); if (summaryNode != null &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; !string.IsNullOrEmpty(summaryNode.InnerText) &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; !controllerDescDict.ContainsKey(key)) { controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim()); } } } } } return controllerDescDict; }
}
} &amp;lt;/code&amp;gt; &amp;lt;/pre&amp;gt;
3、新建&quot;Scripts&quot;文件夹------&amp;gt;在里面新建&quot;Swaggerui&quot;文件夹------&amp;gt;在里面新建&quot;swagger_lang.js&quot;文件,用于对Swagger进行中文汉化脚本。
4、js内容如下:
/// &amp;lt;summary&amp;gt; /// 中文转换 /// &amp;lt;/summary&amp;gt; var SwaggerTranslator = (function () { //定时执行检测是否转换成中文,最多执行500次 即500*50/1000=25s var iexcute = 0, //中文语言包 _words = { &amp;quot;Warning: Deprecated&amp;quot;: &amp;quot;警告:已过时&amp;quot;, &amp;quot;Implementation Notes&amp;quot;: &amp;quot;实现备注&amp;quot;, &amp;quot;Response Class&amp;quot;: &amp;quot;响应类&amp;quot;, &amp;quot;Status&amp;quot;: &amp;quot;状态&amp;quot;, &amp;quot;Parameters&amp;quot;: &amp;quot;参数&amp;quot;, &amp;quot;Parameter&amp;quot;: &amp;quot;参数&amp;quot;, &amp;quot;Value&amp;quot;: &amp;quot;值&amp;quot;, &amp;quot;Description&amp;quot;: &amp;quot;描述&amp;quot;, &amp;quot;Parameter Type&amp;quot;: &amp;quot;参数类型&amp;quot;, &amp;quot;Data Type&amp;quot;: &amp;quot;数据类型&amp;quot;, &amp;quot;Response Messages&amp;quot;: &amp;quot;响应消息&amp;quot;, &amp;quot;HTTP Status Code&amp;quot;: &amp;quot;HTTP状态码&amp;quot;, &amp;quot;Reason&amp;quot;: &amp;quot;原因&amp;quot;, &amp;quot;Response Model&amp;quot;: &amp;quot;响应模型&amp;quot;, &amp;quot;Request URL&amp;quot;: &amp;quot;请求URL&amp;quot;, &amp;quot;Response Body&amp;quot;: &amp;quot;响应体&amp;quot;, &amp;quot;Response Code&amp;quot;: &amp;quot;响应码&amp;quot;, &amp;quot;Response Headers&amp;quot;: &amp;quot;响应头&amp;quot;, &amp;quot;Hide Response&amp;quot;: &amp;quot;隐藏响应&amp;quot;, &amp;quot;Headers&amp;quot;: &amp;quot;头&amp;quot;, &amp;quot;Try it out!&amp;quot;: &amp;quot;试一下!&amp;quot;, &amp;quot;Show/Hide&amp;quot;: &amp;quot;显示/隐藏&amp;quot;, &amp;quot;List Operations&amp;quot;: &amp;quot;显示操作&amp;quot;, &amp;quot;Expand Operations&amp;quot;: &amp;quot;展开操作&amp;quot;, &amp;quot;Raw&amp;quot;: &amp;quot;原始&amp;quot;, &amp;quot;can't parse JSON. Raw result&amp;quot;: &amp;quot;无法解析JSON. 原始结果&amp;quot;, &amp;quot;Model Schema&amp;quot;: &amp;quot;模型架构&amp;quot;, &amp;quot;Model&amp;quot;: &amp;quot;模型&amp;quot;, &amp;quot;apply&amp;quot;: &amp;quot;应用&amp;quot;, &amp;quot;Username&amp;quot;: &amp;quot;用户名&amp;quot;, &amp;quot;Password&amp;quot;: &amp;quot;密码&amp;quot;, &amp;quot;Terms of service&amp;quot;: &amp;quot;服务条款&amp;quot;, &amp;quot;Created by&amp;quot;: &amp;quot;创建者&amp;quot;, &amp;quot;See more at&amp;quot;: &amp;quot;查看更多:&amp;quot;, &amp;quot;Contact the developer&amp;quot;: &amp;quot;联系开发者&amp;quot;, &amp;quot;api version&amp;quot;: &amp;quot;api版本&amp;quot;, &amp;quot;Response Content Type&amp;quot;: &amp;quot;响应Content Type&amp;quot;, &amp;quot;fetching resource&amp;quot;: &amp;quot;正在获取资源&amp;quot;, &amp;quot;fetching resource list&amp;quot;: &amp;quot;正在获取资源列表&amp;quot;, &amp;quot;Explore&amp;quot;: &amp;quot;浏览&amp;quot;, &amp;quot;Show Swagger Petstore Example Apis&amp;quot;: &amp;quot;显示 Swagger Petstore 示例 Apis&amp;quot;, &amp;quot;Can't read from server. It may not have the appropriate access-control-origin settings.&amp;quot;: &amp;quot;无法从服务器读取。可能没有正确设置access-control-origin。&amp;quot;, &amp;quot;Please specify the protocol for&amp;quot;: &amp;quot;请指定协议:&amp;quot;, &amp;quot;Can't read swagger JSON from&amp;quot;: &amp;quot;无法读取swagger JSON于&amp;quot;, &amp;quot;Finished Loading Resource Information. Rendering Swagger UI&amp;quot;: &amp;quot;已加载资源信息。正在渲染Swagger UI&amp;quot;, &amp;quot;Unable to read api&amp;quot;: &amp;quot;无法读取api&amp;quot;, &amp;quot;from path&amp;quot;: &amp;quot;从路径&amp;quot;, &amp;quot;Click to set as parameter value&amp;quot;: &amp;quot;点击设置参数&amp;quot;, &amp;quot;server returned&amp;quot;: &amp;quot;服务器返回&amp;quot; }, //定时执行转换 _translator2Cn = function () { if ($(&amp;quot;#resources_container .resource&amp;quot;).length &amp;gt; 0) { _tryTranslate(); }
if ($(&amp;amp;quot;#explore&amp;amp;quot;).text() == &amp;amp;quot;Explore&amp;amp;quot; &amp;amp;amp;amp;&amp;amp;amp;amp; iexcute &amp;amp;amp;gt; 500) { iexcute++; setTimeout(_translator2Cn, 50); } }, //设置控制器注释 _setControllerSummary = function () { $.ajax({ type: &amp;amp;quot;get&amp;amp;quot;, async: true, url: $(&amp;amp;quot;#input_baseUrl&amp;amp;quot;).val(), dataType: &amp;amp;quot;json&amp;amp;quot;, success: function (data) { var summaryDict = data.ControllerDesc; var id, controllerName, strSummary; $(&amp;amp;quot;#resources_container .resource&amp;amp;quot;).each(function (i, item) { id = $(item).attr(&amp;amp;quot;id&amp;amp;quot;); if (id) { controllerName = id.substring(9); strSummary = summaryDict[controllerName]; if (strSummary) { $(item).children(&amp;amp;quot;.heading&amp;amp;quot;).children(&amp;amp;quot;.options&amp;amp;quot;).prepend('&amp;amp;amp;lt;li class=&amp;amp;quot;controller-summary&amp;amp;quot; title=&amp;amp;quot;' + strSummary + '&amp;amp;quot;&amp;amp;amp;gt;' + strSummary + '&amp;amp;amp;lt;/li&amp;amp;amp;gt;'); } } }); } }); }, //尝试将英文转换成中文 _tryTranslate = function () { $('[data-sw-translate]').each(function () { $(this).html(_getLangDesc($(this).html())); $(this).val(_getLangDesc($(this).val())); $(this).attr('title', _getLangDesc($(this).attr('title'))); }); }, _getLangDesc = function (word) { return _words[$.trim(word)] !== undefined ? _words[$.trim(word)] : word; }; return { Translator: function () { console.warn(&amp;amp;quot;1&amp;amp;quot;); document.title = &amp;amp;quot;API描述文档&amp;amp;quot;; $('body').append('&amp;amp;amp;lt;style type=&amp;amp;quot;text/css&amp;amp;quot;&amp;amp;amp;gt;.controller-summary{color:#10a54a !important;word-break:keep-all;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:250px;text-align:right;cursor:default;} &amp;amp;amp;lt;/style&amp;amp;amp;gt;'); $(&amp;amp;quot;#logo&amp;amp;quot;).html(&amp;amp;quot;接口描述&amp;amp;quot;).attr(&amp;amp;quot;href&amp;amp;quot;, &amp;amp;quot;/Home/Index&amp;amp;quot;); //设置控制器描述 _setControllerSummary(); _translator2Cn(); } } })(); //执行转换 SwaggerTranslator.Translator(); &amp;amp;lt;/code&amp;amp;gt; &amp;amp;lt;/pre&amp;amp;gt;
5、将项目的起始页设置为Swagger主页。
6、在特定页的右侧文本框写入&amp;quot;swagger/ui/index&amp;quot;后,按Ctrl+S保存即可。