MVC WebAPI 三层分布式框架开发
2013-01-09 17:56
260 查看
前言:SOA(面向服务的架构)是目前企业应用开发过程中普遍采用的技术,基于MVC WebAPI三层分布式框架开发,以此适用于企业信息系统的业务处理,是本文论述的重点。此外,插件技术的应用,富客户端JQuery实现技术,本文也对其具体实现做以说明。相关示例解决方案可以参考GitHub资源,在文章结尾给出。
1. 系统分层体系架构设计
分布式三层系统简单分为数据访问层,业务逻辑层和前端展现层。分层架构设计是构建大型分布式系统的必要手段,因为可以使得系统健壮,可扩展。
SOA即面向服务的架构,可以帮助企业构建灵活,扩展性强的复杂业务系统,按照服务的理念进行功能交付,调用方也不用去知道实现一方的具体细节;双方是按照统一消息格式,接口方式进行交互的。
SOA的实现是基于以Web服务的方式发布Api接口,目前WebAPI是一种Restfule形式的Web服务,相比WCF的复杂性,WebAPI的开发效率更高,而且在配置时也不需要客户端和服务端的xml配置。
企业核心业务数据可以让桌面、Web、平板、手机或物联设备访问,所以需要统一API接口,WebApi作为业务逻辑处理服务能够满足接口访问和接口之间交互的需求。
2.基础类库模块
2.1 数据访问:Dapper-微型ORMapping框架
Dapper的优势:
1,Dapper是一个轻型的ORM类。代码就一个SqlMapper.cs文件,编译后就40K的一个很小的Dll.
2,Dapper很快。Dapper的速度接近与IDataReader,取列表的数据超过了DataTable。
3,Dapper支持Mysql,SqlLite,Mssql,Oracle等一系列的数据库,当然如果你知道原理也可以让它支持Mongo db
4,Dapper的r支持多表并联的对象。支持一对多 多对多的关系。并且没侵入性,想用就用,不想用就不用。无XML无属性。代码以前怎么写现在还怎么写。
5,Dapper原理通过Emit反射IDataReader的序列队列,来快速的得到和产生对象。性能实在高。
6,Dapper 是C#实现,支持.net framework 各种版本;
7,Dapper语法十分简单。并且无须迁就数据库的设计。
国外大型网站采用的有:
–StackOverflow, StackExcahnge等。。。
读取500条记录,并做简单对象的序列化操作时间对比如下图:
2.2 DataRepository类
•实现数据实体操作封装
-Insert—插入
-Update—更新
-Delete—删除
-Select—选取
-Paged—分页
2.3 ServiceBase类
•实现业务实体对象的操作封装
–Insert—插入
–Update—更新
–Delete—删除
–Select—选取
–Paged—分页
2.4 服务实现类
-实现Iservice接口
-继承ServiceBase基类
2.5 WebAPI服务发布
API Controller:
--[HttpGet]
--[HttpPost]
--[HttpPut]
--[HttpDelete]
2.6 动态加载插件
-系统的扩展性
-系统的变化性
-客户二次开发
-MEF
–运行时加载
2.7 AutoMapper—实体对象之间转换
•两个实体类
–EPProduct – 数据实体
–Product– 业务实体
•转化示例代码
–EPProduct p =ProductRepository.Get(long.Parse(id));
–AutoMapper.Mapper.CreateMap<EPProduct, Product>();
–Productentity =AutoMapper.Mapper.Map<EPProduct,
Product>(p)
2.8 面向接口编程--Ioc框架
•SimpleInjector
–静态类型
–编译阶段
•MEF
–动态类型
–运行时阶段
3.富客户端开发
3.1 Asp.NETMVC 富客户端开发
•Model
–WebAPI (服务接口)
•Controller
–路由
•View
–页面
–
•富客户端
–Ajax 局部刷新
– 鼠标、键盘响应事件等
–如Gmail邮箱等应用示例
3.2 Jquery插件
•Layout—Jquery Layout
•DataGrid – SlickGrid –性能非常高
•Tree– Jstree/Ztree –评价都不错
•Tab– Jquery Tools
•Toolbar– Jquery Tools
•Dialog– Jquery Tools
•Form–Jquery Tools
3.3 前端页面Ajax调用:
GET/POST/PUT/DELETE
3.4 如何调试?
•Fiddler--*****5star
FireBug for Firefox
•查看HTML,CSS,Javascript等
•监控下载图片资源时间线
•完善友好的调试
Firefox的RestClient插件—Rest Client测试插件
http://localhost:8081/ProductSys.WebAPI/api/order/insertwith?type="insertwith“
[HttpPost]
public HttpResponseMessageInsertWith(Order
entity, string type)
http://localhost:8081/ProductSys.WebAPI/api/order/4
[HttpDelete]
public HttpResponseMessage Delete(string id)
3.5 Web异常错误代码
•100-199– Informational
•200-299– Client request successful
•300-399– Client request redirected, further action necessary
•400-499– Client request incomplete
•500-599– Server error
4. Javascript 类语法
4.1 常见问题
•Namespace(命名空间)
–默认为全局范围,有潜在类型冲突隐患
•SelfExecuting Fuction (自执行匿名函数)
•Objectand Array (对象和数组初始化)
–不要使用new 关键字
•NullOr Empty (检查NULL)
4.2 Javascript-自执行匿名函数
4.3 对象和数组初始化
4.4 判断对象是否为NULL(c#)
4.5 判断对象是否为NULL(javascript)
4.6 设置缺省值(c#)
4.7 不同类型的比较操作符(==, !=)
•// Unexpected Comparisons using the== Operator
•0 == '' //true
•0 == '0' //true
•false == '0' //true
•null == undefined //true
•'\t\r\n ' == 0 //true
4.8 不同类型的比较操作符(===, !==)
•// Expected Comparisons using the ===Operator
•0 === '' //false
•0 === '0' //false
•false === '0' //false
•null === undefined //false
•'\t\r\n ' === 0 //false
4.9
不可取的数组遍历操作符for…in
4.10 正确的数组遍历操作符for…;…;
5. RequireJS 模块化脚本
RequireJS 是一个非常小巧的 JavaScript 模块载入框架,是 AMD 规范最好的实现者之一。最新版本的 RequireJS 压缩后只有 14K,堪称非常轻量。它还同时可以和其他的框架协同工作,使用 RequireJS 必将使的前端代码质量得以提升。
RequireJS 作为 JavaScript 文件的加载器,还是可以完成异步非阻塞的文件加载。
6. 网络资源
6.1 NuGet—快捷获取软件包
•充分利用开源软件包,避免重复制造轮子;
•也可以自己发布软件包,回馈社区,先进技术的积累可以节约项目成本。
6.2 技术资源
•Asp.net MVC WebAPI
–RestfulWeb Service的发展
•Jquery
–官网
–插件开发
•RequrieJS
–Javascript模块化开发框架
•Dapper
–微型ORMapping 框架
•EntityFramework
–Microsoft实体框架
7. 总结:
本文基于MVC WebAPI实现分布式三层架构,实现了通用数据访问操作,业务实体和数据实体的交互操作,业务模块之间的接口交互;实现了插件化的加载技术。此外限于篇幅,对于流程化的设计,会在下文论述,主要会谈及到工作流Api和WebApi的交互。
代码示例说明:
提供的示例RequireMVC199中,可以看一下ProductSys.WebApi的服务层代码,前端代码看RequireMvc199的WebApplication项目即可。
完整示例,可以看一下ProductList页面的代码,这个示例是完整的,包括文件:
WebApplication 包括:
\Controllers
--ProductController.cs
\ViewJS
\Controllers
\Product
--product-list.js
--product-detail.js
\Views
\Product
--productlist.cshtml
WebApi 包括:
ProductSys.WebApi
\Controllers
--ProductController.cs
ProductSys.ServiceImp
\Service
--ProductService.cs
解决方案下载地址: https://github.com/besley/Plat2012
新版本下载: http://github.com/besley/slickone
后记:
不断有朋友问到,是否有新版本?是否支持ORACLE?目前在最新的版本里已经解决这些问题。你可以在Slickflow的项目里面看到,即仍然是Mvc, WebApi和Dapper的架构,但是简化甚多,真是物至简方可尽其用,希望大家一起学习讨论。谢谢大家关注。
1. 系统分层体系架构设计
分布式三层系统简单分为数据访问层,业务逻辑层和前端展现层。分层架构设计是构建大型分布式系统的必要手段,因为可以使得系统健壮,可扩展。
SOA即面向服务的架构,可以帮助企业构建灵活,扩展性强的复杂业务系统,按照服务的理念进行功能交付,调用方也不用去知道实现一方的具体细节;双方是按照统一消息格式,接口方式进行交互的。
SOA的实现是基于以Web服务的方式发布Api接口,目前WebAPI是一种Restfule形式的Web服务,相比WCF的复杂性,WebAPI的开发效率更高,而且在配置时也不需要客户端和服务端的xml配置。
企业核心业务数据可以让桌面、Web、平板、手机或物联设备访问,所以需要统一API接口,WebApi作为业务逻辑处理服务能够满足接口访问和接口之间交互的需求。
2.基础类库模块
2.1 数据访问:Dapper-微型ORMapping框架
Dapper的优势:
1,Dapper是一个轻型的ORM类。代码就一个SqlMapper.cs文件,编译后就40K的一个很小的Dll.
2,Dapper很快。Dapper的速度接近与IDataReader,取列表的数据超过了DataTable。
3,Dapper支持Mysql,SqlLite,Mssql,Oracle等一系列的数据库,当然如果你知道原理也可以让它支持Mongo db
4,Dapper的r支持多表并联的对象。支持一对多 多对多的关系。并且没侵入性,想用就用,不想用就不用。无XML无属性。代码以前怎么写现在还怎么写。
5,Dapper原理通过Emit反射IDataReader的序列队列,来快速的得到和产生对象。性能实在高。
6,Dapper 是C#实现,支持.net framework 各种版本;
7,Dapper语法十分简单。并且无须迁就数据库的设计。
国外大型网站采用的有:
–StackOverflow, StackExcahnge等。。。
读取500条记录,并做简单对象的序列化操作时间对比如下图:
2.2 DataRepository类
•实现数据实体操作封装
-Insert—插入
-Update—更新
-Delete—删除
-Select—选取
-Paged—分页
2.3 ServiceBase类
•实现业务实体对象的操作封装
–Insert—插入
–Update—更新
–Delete—删除
–Select—选取
–Paged—分页
2.4 服务实现类
-实现Iservice接口
-继承ServiceBase基类
2.5 WebAPI服务发布
API Controller:
--[HttpGet]
--[HttpPost]
--[HttpPut]
--[HttpDelete]
2.6 动态加载插件
-系统的扩展性
-系统的变化性
-客户二次开发
-MEF
–运行时加载
2.7 AutoMapper—实体对象之间转换
•两个实体类
–EPProduct – 数据实体
–Product– 业务实体
•转化示例代码
–EPProduct p =ProductRepository.Get(long.Parse(id));
–AutoMapper.Mapper.CreateMap<EPProduct, Product>();
–Productentity =AutoMapper.Mapper.Map<EPProduct,
Product>(p)
2.8 面向接口编程--Ioc框架
•SimpleInjector
–静态类型
–编译阶段
•MEF
–动态类型
–运行时阶段
3.富客户端开发
3.1 Asp.NETMVC 富客户端开发
•Model
–WebAPI (服务接口)
•Controller
–路由
•View
–页面
–
•富客户端
–Ajax 局部刷新
– 鼠标、键盘响应事件等
–如Gmail邮箱等应用示例
3.2 Jquery插件
•Layout—Jquery Layout
•DataGrid – SlickGrid –性能非常高
•Tree– Jstree/Ztree –评价都不错
•Tab– Jquery Tools
•Toolbar– Jquery Tools
•Dialog– Jquery Tools
•Form–Jquery Tools
3.3 前端页面Ajax调用:
GET/POST/PUT/DELETE
/*** * HttpGet获取服务端数据 * @url 业务数据 * @data */ $.doHttpClientGet = function(url, fn) { $.getJSON(url, fn); } /*** * HttpPut更新数据到服务端 * @url 业务数据 * @data */ $.doHttpClientUpdate = function(url, data, fn) { $.ajax({ url: url, type: 'PUT', data: data, dataType: 'json', contentType: 'application/json', success: fn }); } /*** * HttpDelete删除数据 * @url 业务数据 * @data */ $.doHttpClientDelete = function(url, data, fn) { $.ajax({ url: url, type: 'DELETE', data: data, dataType: 'json', contentType: 'application/json', success: fn }); } /*** * HttpPost保存数据 * @url 业务数据 * @data */ $.doHttpClientSave = function(url, data, fn) { $.ajax({ url: url, type: 'POST', data: data, dataType: 'json', contentType: 'application/json', success: fn }); } /*** * ajax获取服务端数据 * @url 业务数据 * @data */ $.doAjaxGet = function(url, fn) { //$.getJSON(url, fn); $.ajax({ url: url, type: "GET", dataType: 'json', //data: data, contentType: 'application/json', success: fn }); } $.doAjaxPost = function(url, data, fn) { $.ajax({ url: url, type: 'POST', data: data, dataType: 'json', contentType: 'application/json', success: fn }); } //构造html的通用方法 $.buildHTML = function(tag, html, attrs) { // you can skip html param if (typeof (html) != 'string') { attrs = html; html = null; } var h = '<' + tag; for (attr in attrs) { if (attrs[attr] === false) continue; h += ' ' + attr + '="' + attrs[attr] + '"'; } return h += html ? ">" + html + "</" + tag + ">" : "/>"; } //构造JsTree的通用方法 $.fn.buildJsTree = function (url, fn) { var object = require(['jstree'], function(){ $.jstree._themes = "/PlatJS/Scripts/jstree/themes/"; var myTree = $(this).jstree({ "json_data": { "ajax": { "url": url, "type": "GET", "dataType": "json", "contentType": "application/json charset=utf-8", "success": fn } }, "plugins": ["themes", "json_data", "ui"] }); }) }
3.4 如何调试?
•Fiddler--*****5star
FireBug for Firefox
•查看HTML,CSS,Javascript等
•监控下载图片资源时间线
•完善友好的调试
Firefox的RestClient插件—Rest Client测试插件
http://localhost:8081/ProductSys.WebAPI/api/order/insertwith?type="insertwith“
[HttpPost]
public HttpResponseMessageInsertWith(Order
entity, string type)
http://localhost:8081/ProductSys.WebAPI/api/order/4
[HttpDelete]
public HttpResponseMessage Delete(string id)
3.5 Web异常错误代码
•100-199– Informational
•200-299– Client request successful
•300-399– Client request redirected, further action necessary
•400-499– Client request incomplete
•500-599– Server error
4. Javascript 类语法
4.1 常见问题
•Namespace(命名空间)
–默认为全局范围,有潜在类型冲突隐患
•SelfExecuting Fuction (自执行匿名函数)
•Objectand Array (对象和数组初始化)
–不要使用new 关键字
•NullOr Empty (检查NULL)
4.2 Javascript-自执行匿名函数
//Self-Executing Anonymous Func: Part 2 (Public & Private) (function( skillet, $, undefined ) { //Private Property var isHot = true; //Public Property skillet.ingredient = "Bacon Strips"; //Public Method skillet.fry = function() { var oliveOil; addItem( "\t\n Butter \n\t" ); addItem( oliveOil ); console.log( "Frying " + skillet.ingredient ); }; //Private Method function addItem( item ) { if ( item !== undefined ) { console.log( "Adding " + $.trim(item) ); } } }( window.skillet = window.skillet || {}, jQuery )); <pre name="code" class="javascript">//Public Properties console.log( skillet.ingredient ); //Bacon Strips //Public Methods skillet.fry(); //Adding Butter & Fraying Bacon Strips //Adding a Public Property skillet.quantity = "12"; console.log( skillet.quantity ); //12 //Adding New Functionality to the Skillet (function( skillet, $, undefined ) { //Private Property var amountOfGrease = "1 Cup"; //Public Method skillet.toString = function() { console.log( skillet.quantity + " " + skillet.ingredient + " & " + amountOfGrease + " of Grease" ); console.log( isHot ? "Hot" : "Cold" ); }; }( window.skillet = window.skillet || {}, jQuery )); try { //12 Bacon Strips & 1 Cup of Grease skillet.toString(); //Throws Exception } catch( e ) { console.log( e.message ); //isHot is not defined }
</pre>
4.3 对象和数组初始化
//建议申明对象或数组的写法 var person = {}, keys = []; //申明复杂对象或数组的写法 var person = { firstName: "Elijah", lastName: "Manor", sayFullName: function() { console.log( this.firstName + " " + this.lastName ); } }, keys = ["123", "676", "242", "4e3"];
4.4 判断对象是否为NULL(c#)
// <span style="color:#ff0000;">C# 例子. 不要在Javascript中这样写</span> if ( someString != null && someString.length > 0 ) { //Do something here... } // C# 例子 检查字符串是否为空 if ( !string.IsNullOrEmpty(someString) ) { //Do something here... }
4.5 判断对象是否为NULL(javascript)
Javascript中的正确写法 // Simplified JavaScript syntax to check for // undefined, null, & empty string values if ( someString ) { //Do something here... }
4.6 设置缺省值(c#)
<span style="color: rgb(255, 0, 0);">// C# 例子,不要在Javascript这样写</span> if ( someString == null ) { someString = "default Value"; } // Slightly better, but don't do this either someString = someString ? someString : "default value"; <pre name="code" class="javascript">请在Javascript按如下格式写 // JavaScript syntax to set a default value someString = someString || "default value";
4.7 不同类型的比较操作符(==, !=)
•// Unexpected Comparisons using the== Operator
•0 == '' //true
•0 == '0' //true
•false == '0' //true
•null == undefined //true
•'\t\r\n ' == 0 //true
4.8 不同类型的比较操作符(===, !==)
•// Expected Comparisons using the ===Operator
•0 === '' //false
•0 === '0' //false
•false === '0' //false
•null === undefined //false
•'\t\r\n ' === 0 //false
4.9
不可取的数组遍历操作符for…in
var myArray = [], name; myArray[5] = "test"; console.log( myArray.length ); //6 for ( name in myArray ) { console.log( name, myArray[name] ); //Outputs... // 5, test }
4.10 正确的数组遍历操作符for…;…;
var myArray = [], name; myArray[5] = "test"; console.log( myArray.length ); //6 for ( var i = 0, length = myArray.length; i < length; i++ ) { console.log( i, myArray[i] ); //Outputs... // 0, undefined // 1, undefined // 2, undefined // 3, undefined // 4, undefined // 5, test }
for ( var name in object ) { //Your code here } /* Check if object has property before iterating, because functions inherited from prototype are also included */ for ( var name in object ) { if ( object.hasOwnProperty(name) ) { //Your code here } }
5. RequireJS 模块化脚本
RequireJS 是一个非常小巧的 JavaScript 模块载入框架,是 AMD 规范最好的实现者之一。最新版本的 RequireJS 压缩后只有 14K,堪称非常轻量。它还同时可以和其他的框架协同工作,使用 RequireJS 必将使的前端代码质量得以提升。
RequireJS 作为 JavaScript 文件的加载器,还是可以完成异步非阻塞的文件加载。
define(['Controllers/Main/ListView'], function (ListView) { function start() { var users = JSON.parse(localStorage.users); ListView.render({ users: users }); } return { start: start }; });
6. 网络资源
6.1 NuGet—快捷获取软件包
•充分利用开源软件包,避免重复制造轮子;
•也可以自己发布软件包,回馈社区,先进技术的积累可以节约项目成本。
6.2 技术资源
•Asp.net MVC WebAPI
–RestfulWeb Service的发展
•Jquery
–官网
–插件开发
•RequrieJS
–Javascript模块化开发框架
•Dapper
–微型ORMapping 框架
•EntityFramework
–Microsoft实体框架
7. 总结:
本文基于MVC WebAPI实现分布式三层架构,实现了通用数据访问操作,业务实体和数据实体的交互操作,业务模块之间的接口交互;实现了插件化的加载技术。此外限于篇幅,对于流程化的设计,会在下文论述,主要会谈及到工作流Api和WebApi的交互。
代码示例说明:
提供的示例RequireMVC199中,可以看一下ProductSys.WebApi的服务层代码,前端代码看RequireMvc199的WebApplication项目即可。
完整示例,可以看一下ProductList页面的代码,这个示例是完整的,包括文件:
WebApplication 包括:
\Controllers
--ProductController.cs
\ViewJS
\Controllers
\Product
--product-list.js
--product-detail.js
\Views
\Product
--productlist.cshtml
WebApi 包括:
ProductSys.WebApi
\Controllers
--ProductController.cs
ProductSys.ServiceImp
\Service
--ProductService.cs
解决方案下载地址: https://github.com/besley/Plat2012
新版本下载: http://github.com/besley/slickone
后记:
不断有朋友问到,是否有新版本?是否支持ORACLE?目前在最新的版本里已经解决这些问题。你可以在Slickflow的项目里面看到,即仍然是Mvc, WebApi和Dapper的架构,但是简化甚多,真是物至简方可尽其用,希望大家一起学习讨论。谢谢大家关注。
相关文章推荐
- MVC WebAPI 三层分布式框架开发
- MVC WebAPI 三层分布式框架开发
- MVC WebAPI 三层分布式框架开发
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
- (转)第一次发博客-说说我的B/S开发框架(asp.net mvc + web api + easyui)
- B/S开发框架(asp.net mvc + web api + easyui)
- MVC WebAPI框架里设置异常返回格式统一
- golang web开发框架httprouter:开发简单的 REST API 服务器
- 基于MVC+EasyUI的Web开发框架经验总结(3)- 使用Json实体类构建菜单数据
- 基于MVC+EasyUI的Web开发框架经验总结(9)--在Datagrid里面实现外键字段的转义操作
- 【持久化框架】SpringMVC+Spring4+Mybatis3集成,开发简单Web项目+源码下载 【转】
- 基于MVC+EasyUI的web开发框架之使用云打印控件C-Lodop打印页面或套打报关运单信息
- Faygo一款最适合开发API的 Go Web 框架
- 基于MVC+EasyUI的Web开发框架经验总结(4)--使用图表控件Highcharts
- 基于MVC+EasyUI的Web开发框架经验总结(10)--在Web界面上实现数据的导入和导出
- 【持久化框架】SpringMVC+Spring4+Mybatis3集成,开发简单Web项目+源码下载
- 【持久化框架】SpringMVC+Spring4+Mybatis3集成,开发简单Web项目
- 【持久化框架】SpringMVC+Spring4+Mybatis3集成,开发简单Web项目+源码下载【转】
- ASP.NET MVC 框架是 .NET 平台 Web 开发的主流,但是并不适合初学者
- 基于MVC+EasyUI的Web开发框架经验总结(17)--布局和对话框自动适应大小的处理