使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑

时间:2022-09-12 18:22:41

翻译:使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑

Part 3: 设计逻辑层:核心开发

如前所述,我们的解决方案如下所示:
使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑

下面我们讨论整个应用的结构,根据应用中不同组件的逻辑相关性,分离到不同的层中,层与层之间的通讯通过或者不通过限制。分层属于架构风格,在应用的长时间生命周期中,解决维护和扩展问题。
所以,让我们在解决方案中添加一个类库项目,命名为 Application.Common.

Application.Common :

这是一个类库项目, 提供公共功能,可以被不同的业务逻辑层使用。例如:安全,日志,跟踪,验证等等. 定义在这个层中的组件,不仅可以被不同的层使用,还可以在不同的应用中使用。为了未来容易使用,我们使用依赖注入和抽象,在应用中实现最小化的修改。

例如,在我们马上用到的,验证组件用来验证数据,定制的日志器来记录错误或者警告。

在添加了 Common 类库之后,解决方案的文件夹如下所示:
使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑

Application.Core:

这个层实现系统的核心处理逻辑,封装相关的所有业务逻辑。从基本上说,这个层通常实现领域处理的逻辑。这个层还经常通过核心层的工作单元,以便完成 PI 特性,主要的目标是明确区分和分离核心领域的逻辑与基础架构的具体细节,例如,数据访问和数据仓储的具体技术,像 ORM ,或者简单的数据访问库,或者面向方面的架构等等。通过分离系统的核心功能,我们就可以进一步增强系统的可维护性,甚至可以替换底层的组件,而很少影响到整个应用。

使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑
下一步,我们将在解决方案中添加名为 Application.DAL 的类库。

Application.DAL:

DAL 的职责是提供数据访问和数据的持久化处理;维护多个会话,连接到不同的数据库等等。这里的主要目标是通过接口和约定包装 EF 数据访问上下文对象,使得核心层不会直接依赖 EF。数据持久化组件提供驻留在系统内的数据访问,也提供系统外的数据访问。比如对外部系统提供服务的 Web 服务。因此,这里既包含类似 仓储模式的机制来支持对系统内的数据访问,还提供服务代理来使用其它外部系统通过 Web 服务提供的数据,另外,层中还提供可以对所有仓储使用的基类和组件。

使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑
下一步,我们将会在解决方案中添加一个名为 Application.Repository 的类库。

Application.Repository:

这个类库仅仅可以通过 Application.Manager 访问,对于领域中的每一个根实体对象,我们需要创建一个仓储,基本上,所谓的仓储就是封装了访问应用数据的处理逻辑的类和组件。而且,它们处理数据处理的核心功能,使得整个应用有更好的可维护性,并且可以在 Manager 和 Core 之间进行解耦。

使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑
下一步,我们需要创建名为 Application.DTO 类库。

Application.DTO:

还是一个类库,包含了与实体不同的数据类,其中仅有表示数据的属性,但是没有处理数据的方法,用来在表示层 Applicaiton.Web 和服务层 Application.Manager 之间进行通讯。数据传输对象是用来封装数据的对象,用来从系统的一个子系统将数据传递到另外一个子系统。这里我们使用 DTO 对象在 Manager 层和 UI 层之间传递数据。使用 DTO 的主要优点是可以在分布式的系统中减少数据的流量,在 MVC 模式中,也是重要的一个部分。我们也可以为方法的调用来封装数据,在方法包含4,5个以上的参数的时候,经常使用 DTO 来传递参数。

使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑
下一步,我们创建 Application.Manager 类库。

Application.Manager :

这个类库仅仅被 Applicaiton.Web 访问,对于我们在 Manager 中定义的每个模块,Manager 的主要职责是接受来自 UI 的请求,将数据传递到仓储中的领域对象中进行处理,将处理结果返回到界面层,这个层是 UI 层和仓储层之间的中间层。

使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑

Application.Web:

在前面的文章中,我们已经使用 javascript 中的模拟数据实现过该层。这里并不仅仅依赖于 ASP.NET MVC,界面可以包含用户的界面组件,像 HTML,.aspx, cshtml,MVC 等等,它也可以是是任何的 Windows 应用。这里通过方法与 Manager 层通讯,封装返回的结果,选择将错误信息显示在页面1 或者页面2 中。这个层使用 javascript 来家在表示层的模型,但实际的数据处理通过 ajax 请求发送到服务器处理,所以,服务器负责处理业务立即。而表示层处理表示逻辑问题。

使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑
要理解各层之间通讯的最好方式,就是让我们重温一下初始的需求。

Screen 1: 联系人列表 - 显示所有联系人

1.1 界面需要显示数据库中所有的联系人信息. 
1.2 用户可以删除联系人.
1.3 用户可以编辑联系人信息.
1.4 用户可以创建新的联系人.
使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑
为了填充表格中的数据,在页面加载的时候,我们调用 ContactController 的 GetAllProfiles() 方法,这个方法返回数据库中所有的联系人信息,然后以 JSON 的形式返回到页面,我们将数据以 self.Profiles 的形式绑定到一个 javascript 对象,下面就是 contact.js 代码中 GetAllProfiles() 方法的定义。

var ProfilesViewModel = function () {
var self = this;
var url = "/contact/GetAllProfiles";
var refresh = function () {
$.getJSON(url, {}, function (data) {
self.Profiles(data);
});
};

在点击删除按钮的时候,我们调用 ContactController 的 GetAllProfiles() 方法,这个方法从数据库中删除联系人信息。下面是 contact.js 中 DeleteProfile() 方法的定义。

self.removeProfile = function (profile) {
if (confirm("Are you sure you want to delete this profile?")) {
var id = profile.ProfileId;
waitingDialog({});
$.ajax({
type: 'DELETE', url: 'Contact/DeleteProfile/' + id,
success: function () { self.Profiles.remove(profile); },
error: function (err) {
var error = JSON.parse(err.responseText);
$("<div></div>").html(error.Message).dialog({ modal: true,
title: "Error", buttons: { "Ok":
function () { $(this).dialog("close"); } } }).show();
},
complete: function () { closeWaitingDialog(); }
});
}
};

对于创建和编辑按钮来说,我们仅仅重定向到 CreateEdit 页面,如果 id 参数是 0 表示创建新联系人,对于编辑来说,id 就是编辑的联系人编号了。下面的代码就是 contact.js 中 的 createProfile 和  editProfile 方法

self.createProfile = function () {
window.location.href = '/Contact/CreateEdit/0';
}; self.editProfile = function (profile) {
window.location.href = '/Contact/CreateEdit/' + profile.ProfileId;
};

下面的图展示了主要的三个层之间的关系。

使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑

Screen 2: 创建新联系人

界面提供一个空白的联系人界面,并且提供一下功能.

2.1 用户可以输入用户的姓,名,邮件地址
2.2 通过点击添加号码按钮,允许添加任何个电话号码
2.3 用户可以删除任意电话号码. 
2.4 通过点击添加地址按钮,允许添加任意多个地址. 
2.5 用户可以删除任意的地址. 
2.6 点击保存按钮,可以保存用户输入的所有信息到数据库中,然后回到联系人列表页面. 
2.7 点击返回按钮,可以回到联系人列表. 
使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑

Screen 3: 更新联系人信息

这个界面显示联系人的详细信息.

3.1 用户可以编辑联系人的姓,名,邮件地址.
3.2 用户可以通过点击添加,删除号码按钮来添加,删除用户的电话号码.
3.3 用户可以通过点击添加,删除地址按钮来添加,删除用户的地址。
3.4 点击保存可以将用户的详细信息更新到数据库中,然后返回联系人列表
3.5 点击返回按钮可以回到联系人列表
使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑
如前面的实现所见,创建和编辑的需求使用的是同一个页面 CreateEdit.cshtml,通过 profileId 来进行区分,如果 profileId 是 0,表示新建,否则,就是编辑存在的信息,下面是实现的细节。

在任何情况下,在页面加载和初始化 PhoneType 和 AddressType 的时候,在 ContactController 控制器的 InitializePageData() 方法中,在 CreateEdit.js 中的下列代码初始化数组。

var AddressTypeData;
var PhoneTypeData; $.ajax({
url: urlContact + '/InitializePageData',
async: false,
dataType: 'json',
success: function (json) {
AddressTypeData = json.lstAddressTypeDTO;
PhoneTypeData = json.lstPhoneTypeDTO;
}
});

然后,对于编辑联系人信息来说,我们需要获取详细信息,通过 ContactController 中的GetProfileById() 方法实现,我们修改 CreateEdit.js 。

$.ajax({
url: urlContact + '/GetProfileById/' + profileId,
async: false,
dataType: 'json',
success: function (json) {
self.profile = ko.observable(new Profile(json));
self.phoneNumbers = ko.observableArray(ko.utils.arrayMap(json.PhoneDTO, function (phone) {
return phone;
}));
self.addresses = ko.observableArray(ko.utils.arrayMap(json.AddressDTO, function (address) {
return address;
}));
}
});

最后,我们使用两个方法保存数据,如果我们是创建新的联系人,调用 ContactController 的 SaveProfileInformtion() 方法,否则调用 UpdateProfileInformation() 方法,我们将 CreateEdit.js 修改如下。

$.ajax({
type: (self.profile().ProfileId > 0 ? 'PUT' : 'POST'),
cache: false,
dataType: 'json',
url: urlContact + (self.profile().ProfileId > 0 ? '/UpdateProfileInformation?id=' +
self.profile().ProfileId : '/SaveProfileInformation'),
data: JSON.stringify(ko.toJS(self.profile())),
contentType: 'application/json; charset=utf-8',
async: false,
success: function (data) {
window.location.href = '/contact';
},
error: function (err) {
var err = JSON.parse(err.responseText);
var errors = "";
for (var key in err) {
if (err.hasOwnProperty(key)) {
errors += key.replace("profile.", "") + " : " + err[key];
}
}
$("<div></div>").html(errors).dialog({ modal: true,
title: JSON.parse(err.responseText).Message, buttons: { "Ok":
function () { $(this).dialog("close"); } } }).show();
},
complete: function () {
}
});

使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑

总结

就是这样,希望你喜欢这篇文章,我不是一个专家,我希望你享受这个系列并且能够学到些什么。

如果有任何问题欢迎进行讨论,谢谢。

How to use code

从这里可以下载数据库的脚本:
Application_DB.sql
   在 VS 中运行程序,需要启用 Allow NuGet to download missing packages during build ,

使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑

或者看下面的链接说明。

http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages

最后,修改你的 Application.Web 项目中的数据库连接串。

参考资料

  • http://knockoutjs.com/
  • https://github.com/ericmbarnard/Knockout-Validation/wiki/Configuration
  • http://twitter.github.com/bootstrap/
  • http://docs.castleproject.org/Windsor.MainPage.ashx
  • http://microsoftnlayerapp.codeplex.com/
  • http://msdn.microsoft.com/en-us/library/ff921348.aspx

Last edited Jan 18 at 6:41 AM by anandranjanpandey, version 5

使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑的更多相关文章

  1. 翻译:使用 ASP&period;NET MVC 4&comma; EF&comma; Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑

    Part 3: 设计逻辑层:核心开发 如前所述,我们的解决方案如下所示: 下面我们讨论整个应用的结构,根据应用中不同组件的逻辑相关性,分离到不同的层中,层与层之间的通讯通过或者不通过限制.分层属于架构 ...

  2. 翻译:使用 ASP&period;NET MVC 4&comma; EF&comma; Knockoutjs and Bootstrap 设计和开发站点 - 3

    原文地址:http://ddmvc4.codeplex.com/ 原文名称:Design and Develop a website using ASP.NET MVC 4, EF, Knockout ...

  3. 翻译:使用 ASP&period;NET MVC 4&comma; EF&comma; Knockoutjs and Bootstrap 设计和开发站点 - 1

    原文地址:http://ddmvc4.codeplex.com/ 原文名称:Design and Develop a website using ASP.NET MVC 4, EF, Knockout ...

  4. 翻译:使用 ASP&period;NET MVC 4&comma; EF&comma; Knockoutjs and Bootstrap 设计和开发站点 - 4 - 验证

    验证: 快要完成我们程序的界面部分了.剩下的事情就是在用户点击 "保存" 的时候管理验证问题了.验证是主要需求,今天就是最无知的应用也不会忽视它.通过正确的验证,用户可以知道应该输 ...

  5. 翻译:使用 ASP&period;NET MVC 4&comma; EF&comma; Knockoutjs and Bootstrap 设计和开发站点 - 5 - 数据库设计

    数据库方面我们需要的主要功能如下: 联系人有姓名和电子邮件地址. 联系人可以拥有多个地址. 联系人可以拥有多个电话. 为了实现目标,我们需要在数据库中创建下列表.表与表的关系如下图所示: 数据库的脚本 ...

  6. 翻译:使用 ASP&period;NET MVC 4&comma; EF&comma; Knockoutjs and Bootstrap 设计和开发站点 - 2

    我们的目标: 需求 Screen 1: 联系人列表 - 查看所有联系人 1.1 这个 screen 将显示数据库中的所有联系人. 1.2 用户可以删除任何联系人.1.3 用户可以编辑任何联系人的详细信 ...

  7. ASP&period;NET MVC和EF集成AngularJS开发

    参考资料: 如何在ASP.NET MVC和EF中使用AngularJS AngularJS+ASP.NET MVC+SignalR实现消息推送 [AngularJs + ASP.NET MVC]使用A ...

  8. ASP&period;NET MVC 中应用Windows服务以及Webservice服务开发分布式定时器

    ASP.NET MVC 中应用Windows服务以及Webservice服务开发分布式定时器一:闲谈一下:1.现在任务跟踪管理系统已经开发快要结束了,抽一点时间来写一下,想一想自己就有成就感啊!!  ...

  9. 如何在ASP&period;NET MVC和EF中使用AngularJS

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) AngularJS作为一个越来越流行的前端框架,在使用ASP.NET MVC和实体框架开发W ...

随机推荐

  1. Flipping Parentheses&lpar;CSU1542 线段树&rpar;

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1542 赛后发现这套题是2014东京区域赛的题目,看了排名才发现自己有多low  = =! 题目大意 ...

  2. Merge Into For Update Example

    Merge Into article aa Using ( SELECT md5_id, Min(article_id) as Min_Article_ID from article )) and s ...

  3. cocos2d-x项目101次相遇&colon; Scenes , Director, Layers, Sprites

    cocos2d-x 101次相遇 / 文件夹  1   安装和环境搭建 -xcode  2   Scenes , Director, Layers, Sprites 3   建立图片菜单  4   在 ...

  4. 1289 大鱼吃小鱼 1305 Pairwise Sum and Divide 1344 走格子 1347 旋转字符串 1381 硬币游戏

    1289 大鱼吃小鱼 有N条鱼每条鱼的位置及大小均不同,他们沿着X轴游动,有的向左,有的向右.游动的速度是一样的,两条鱼相遇大鱼会吃掉小鱼.从左到右给出每条鱼的大小和游动的方向(0表示向左,1表示向右 ...

  5. Fetch XML and ConditionExpression operators

    https://msdynamicscrmblog.wordpress.com/2013/05/10/fetch-xml-and-conditionexpression-operators-using ...

  6. mongo学习笔记2--索引及表设计

    -背景: 鉴于我们使用mongo作为数据库,期间少不了需要添加索引和对业务表进行设计.因此以下我对mongo索引及表设计原则做了一些分享.希望对大家有用,如有错误还望指正~ MongDB的索引类型简介 ...

  7. 3、zabbix配置入门

    Zabbix模板 zabbix组件:    zabbix-server    zabbix-database    zabbix-web    zabbix-agent    zabbix-proxy ...

  8. mysql自定义函数并在存储过程中调用,生成一千万条数据

    mysql 自定义函数,生成 n 个字符长度的随机字符串 -- sql function delimiter $$ create function rand_str(n int) returns VA ...

  9. Delphi应用程序的调试(一)

    集成式调试器是Delphi IDE的一个重要特性.该调试器使用户能方便地设置断点.监视变量.检查对象等等.在运行程序时,使用该调试器能快速查找出程序发生了什么(或未发生什么).一个号的调试器对程序开发 ...

  10. PHP MySQL 连接数据库

    PHP连接MySQL的小实例 <?php  /*时间:2014-09-14  *作者:葛崇  *功能:PHP连接MySQL小实例  * */ /* SQL 脚本.直接贴到命令行运行. DROP  ...