N 层项目,包含 WCF OData 服务、Entity Framework、MVC3.0、Ninject DI、jSOn.net 和 Automapper






4.62/5 (5投票s)
N 层应用程序,包含 WCF OData 服务和 Entity Framework。
简要介绍
本文尝试解释可单元测试、解耦、部署灵活的 N 层架构。该架构还将解释 MVC 3.0 中的存储库模式。它还描述了如何使用 Ninject DI 容器注入依赖项,如何使用 Auto mapper 绑定 ViewModel 到 Model,以及如何使用 CSS3.0 媒体查询创建移动就绪的站点。
使用代码
该项目在 Visual Studio 2010 中使用 MVC 3.0 和 Entity Framework 4.1 创建,我还使用了 AutoMapper、jSon.net 和 Ninject 等第三方库。
在继续使用此示例项目之前,您需要遵循以下步骤。
在 SQL Server 中安装 Northwind 数据库(我使用的是 SQL Server Express 2008 R2),您也可以在旧版本中安装 Northwind 数据库。使用此命令(Install-Package Ninject)在 Nuget 包管理器控制台中安装 Ninject DI 容器。使用此命令(Install-Package AutoMapper -Pre)在 Nuget 包管理器控制台中安装 AutoMapper。修改 eShopping UI 项目中 Web.config 文件中的 NorthwindEntities 数据库连接字符串。如果您一切都已正确完成,只需运行项目。
此项目的架构
该项目包含五个层:
- eShopping.eShoppingDB 持久层
- eShopping.Business 域层或业务层
- eShopp.ing.Entities 业务实体层
- eShopping UI 层
- AuthenticationProvider
AuthenticationProvider (AuthenticationProvider)
我添加了 BasicAuthenticationProvider
类来模拟身份验证功能,如果用户已成功身份验证,则以下方法返回 true,并将当前用户设置为当前 http 上下文中的 IPrincipal
。
public static bool Authenticate(HttpContext context)
{
if (!HttpContext.Current.Request.Headers.AllKeys.Contains("Authorization"))
return false;
string authHeader = HttpContext.Current.Request.Headers["Authorization"];
IPrincipal principal;
if (TryGetPrincipal(authHeader, out principal))
{
HttpContext.Current.User = principal;
return true;
}
return false;
}
private static bool TryGetPrincipal(string authHeader, out IPrincipal principal)
{
var creds = ParseAuthHeader(authHeader);
if (creds != null && TryGetPrincipal(creds, out principal))
return true;
principal = null;
return false;
}
业务层 (eShopping.Business)
我使用 Data Service Context 类来访问 WCF OData 服务,而 DbSContext
是 DataServiceContext
类的实例。DbSContext
在向 WCF OData 服务发送请求以获取数据时,始终会发送加密的授权标头。我使用 RijndaelManaged 算法加密授权标头。
public static DataServiceContext DbSContext; static GlobalObjects()
{
DbSContext = new DataServiceContext(CommonVariables.DbServiceUrl);
DbSContext.SendingRequest += newEventHandler<sendingrequesteventargs>(OnSendingRequest);
}
internal static void OnSendingRequest(object sender, SendingRequestEventArgs e)
{
var creds = Encryption.EncryptString("Administrator") +
Encryption.EncryptString("SecurePassword");
var bcreds =Encoding.ASCII.GetBytes(creds);
var base64Creds = Convert.ToBase64String(bcreds);
e.RequestHeaders.Add("Authorization","Basic " + base64Creds);
}
WCF OData 服务 (eShopping.DataService)
我创建了一个 IHttp Module (BasicAuthenticationModule) 来验证来自业务层的 OData 请求,如果用户名和密码不匹配,服务将返回 **Unauthorized 404** 错误消息。
我在 web.config 文件中注册了此模块(BasicAuthenticationModule
)。
<httpModules>
<add name="BasicAuthenticationModule"
type="eShopping.DataService.Authentication.BasicAuthenticationModule"/>
</httpModules>
当 WCF OData 服务接收到请求时,应用程序会调用已注册的模块来验证请求。
public void Init(HttpApplication context)
{
context.AuthenticateRequest += new EventHandler(context_AuthenticateRequest);
}
#endregion
void context_AuthenticateRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
if(!BasicAuthenticationProvider.Authenticate(application.Context))
{
application.Context.Response.Status = "401Unauthorized";
application.Context.Response.StatusCode = 401;
application.Context.Response.AddHeader("WWW-Authenticate","Basic");
application.CompleteRequest();
}
}
业务实体层 (eShopping.Entities)
我将实体放在一个地方以保持一致性并消除重复。这将有助于在多个项目中共享相同的实体,例如在数据库层、业务层和 UI 层。
UI 层 (eShopping)
我使用 Ninjected DI 作为默认依赖注入器,并使用 Automapper 来使用视图模型映射模型。
我在 Global.asax 文件中注册了 AutoMapper。
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new eShoppingControllerFactory());
InitializeAutoMapper();
}
private void InitializeAutoMapper()
{
Mapper.CreateMap<customerview,>();
Mapper.AssertConfigurationIsValid();
}
免责声明
该项目完全基于我个人的学习、知识和研究,不基于任何其他项目。我使用了 eShopping 之类的术语,但这完全是演示术语,与任何实际工作的项目无关。我使用了 Microsoft Northwind 数据库,它是 Microsoft 公开提供的示例数据库。我没有为 eShopping 实现像购物、查看产品等功能,我的目的是仅描述 N 层架构,以及 ASP.NET MVC3.0 中最常用的开源工具,如 Ninject 和 AutoMapper。我没有在此项目中添加单元测试,所以如果您愿意,可以向此项目添加单元测试。请随时与我联系,以添加更多功能。