zoukankan      html  css  js  c++  java
  • Project Silk – Mileage Stats 项目架构初步分析(ASP.NET MVC 3) [转]

    如果你正在学习ASP.NET MVC 3HTML5jQuery和浏览器客户端交互技术,推荐你下载Mileage Stats 范例程序,可更好理解如何使用当前技术创建当前的web应用程序,尤其关注如何架构一个企业级的应用程序。关于Mileage Stats项目的初步介绍,请参考《Project Silk 基于ASP.NET MVC 3 的示例应用程序Mileage Stats》。



    EntLib.com Team 尝试从架构的角度对MileageStats项目进行分析和解读,并计划运用到实际的电子商务系统中,欢迎大家参与交流和分享。



    MileageStats RI 运行的主要界面:






    MileageStats RI 项目的当前架构图,主要有Web
    表示层、业务逻辑层和数据访问层,如下图所示。







    简要看看MileageStats 包含的一些主要项目:







    创建数据模型(Data
    Model


    MileageStats.Model 项目包含数据模型(Data
    Model
    )。结构化和强类型的类描述了业务数据的数据类型、关系和约束。



    实现Repository
    Pattern


    Repository模式中,Repository是一组接口,实现了数据访问相关的方法。接口没有暴露任何特定数据存储相关的类型。


    MileageStats.Data 项目包含了Repository接口,MileageStats.Data.SqlCe 项目包含了接口的实现。如下是IReminderRepository 接口的示例代码:


    // contained in IReminderRepository.cs


    public interface IReminderRepository


    {


    void Create(int vehicleId, Reminder reminder);


    Reminder GetReminder(int reminderId);


    void Update(Reminder reminder);


    void Delete(int reminderId);


     


    IEnumerable<Reminder>
    GetRemindersForVehicle(int vehicleId);


    IEnumerable<Reminder> GetOverdueReminders(int
    vehicleId,


    DateTime forDate, int forOdometer);


     


    IEnumerable<Reminder>
    GetUpcomingReminders(int vehicleId,


    DateTime forStartDate, DateTime forEndDate,


    int odometer, int warningOdometer);


     


    IEnumerable<Reminder>
    GetFulfilledRemindersForVehicle(int vehicleId);


    }



    分解应用程序代码到ASP.NET
    MVC
    模式


    设计良好的MVC应用程序保持ControllerAction方法比较小,View比较简单。大部分的核心应用程序逻辑存放在Model中。在MVC应用程序创建时,保持DRYDon’t Repeat Yourself)原则比后期试图清理代码更容易。



    因为大部分应用程序逻辑在Model层中,因此很多MVC 应用程序包含不同类型的Model


    l View models(视图模型) - 仅用于视图的数据绑定,这些Models包含于MVC 应用程序中,一般与ViewsPartial Views保持相同的构成结构。


    l Application, domain, or service
    models(业务模型) - 基于实际业务需要建立的数据模型,可添加属性标注,或扩展支持应用功能,如数据验证、身份验证。因为这些Models易于往返于客户端浏览器,因此它们经常包含于View Models,并直接在HTML 表单进行数据绑定。


    l Data models(数据模型) - 用于数据服务和存储,不会暴露在应用程序之外,经常封装在服务层。



    如下是MileageStats RI Solution中包含的3Model项目
    下图中选中的项目,分别在Web层、业务逻辑层和数据层:






    对于比较复杂或长期维护的应用程序,应该分离业务模型和数据模型。如果业务模型和数据模型的层级和接口差异很大,则创建完全分离的类。如业务模型和数据模型有匹配的层级和兼容的接口,则建议业务模型类继承数据模型类。如业务模型和数据模型有匹配的层级,但接口不兼容(如数据模型类接口不适合于业务模型类),则在业务模型类中通过聚集关系,包含数据模型类实例。





    在编写Controller Action方法时,应将一些复杂的方法包装为modelservice层的辅助方法或类中。优先采用action过滤器属性,如HttpPostAttribute,避免在每一个action方法中检测HttpContext,编写逻辑判断。此外,使用action过滤器进行横切关切点(Cross-cutting concern),如认证(AuthorizeAttribute)、错误处理(HandleErrorAttribute)等等。处理GET请求的方法应仅包含一些方法调用,而不必包含太多业务判断逻辑;处理POST 请求的方法应验证传入的数据,在数据合法的情况下,执行更新操作,并根据更新结果,返回对应视图。MileageStats
    RI 应用程序的如下范例显示2个版本的Add方法(分别为GETPOST版本):


            // GET: /Fillups/Add/1


            public ActionResult Add(int vehicleId)


            {


                var vehicles = this.businessServices.GetVehicles(this.User.MileageStatsIdentity().UserId);


                Vehicle vehicle = vehicles.First(v =>
    v.VehicleId == vehicleId);


     


                var newFillupEntry = new FillupEntry()


                {


                    Odometer =
    vehicle.Odometer.HasValue ? vehicle.Odometer.Value : 0


                };


                var fillups = this.GetVehicleFillupsDescending(vehicleId);


     


                var model = new
    FillupViewModel()


                {


                    VehicleList
    = new VehicleListViewModel(vehicles, vehicle) {
    IsCollapsed = true },


                    Fillups =
    new SelectedItemList<FillupEntry>(fillups,
    newFillupEntry),


                    FillupEntry
    = newFillupEntry


                };


     


                this.ViewBag.IsFirstFillup = (fillups.Count ==
    0);


     


                return this.View(model);


            }


     


            //


            // POST: /Fillups/Add/5


            [HttpPost]


            [ValidateInput(false)]


            [ValidateAntiForgeryToken]


            public ActionResult Add(int vehicleId, FillupEntry model)


            {


                if (this.ModelState.IsValid)


                {


                    this.AddModelErrors(this.businessServices.CanAddFillup(this.CurrentUserId, vehicleId, model),


                                       
    "AddFillup");


     


                    if (this.ModelState.IsValid)


                   
    {


                        this.businessServices.AddFillupToVehicle(this.CurrentUserId, vehicleId, model);


                        this.TempData["LastActionMessage"] = Resources.VehicleController_AddFillupSuccessMessage;


                        return this.RedirectToAction("List", "Fillup", new {
    vehicleId = vehicleId });


                   
    }


                }


     


                var vehicles = this.businessServices.GetVehicles(this.CurrentUserId);


                Vehicle vehicle = vehicles.First(v =>
    v.VehicleId == vehicleId);


                var fillups = this.GetVehicleFillupsDescending(vehicleId);


     


                var viewModel = new
    FillupViewModel()


                {


                    VehicleList
    = new VehicleListViewModel(vehicles, vehicle) {
    IsCollapsed = true },


                    Fillups =
    new SelectedItemList<FillupEntry>(fillups, model),


                    FillupEntry
    = model


                };


     


                this.ViewBag.IsFirstFillup = (fillups.Count ==
    0);


     


                return this.View(viewModel);


            }




    依赖注入 - Dependency
    Injection


    解耦应用程序的组件(Decoupling the application
    components)。关于Unity 2.0 依赖注入容器在ASP.NET MVC 3 项目的具体使用细节,可参考文章 - ASP.NET MVC 项目使用Unity 2.0实现依赖注入



    创建Business Service


    为了项目的可维护和支持不同类型的客户端,大型和复杂的应用程序经常需要额外的架构层
    – Business Service Layer,将业务逻辑从数据访问层分离出来。



    本文参考和编译了如下文章部分内容:


    Project Silk 1.0 – Server-side Architecture


    Project Silk - http://silk.codeplex.com/

  • 相关阅读:
    js 判断图片是否加载完成(使用 onload 事件)
    使用 css 的 keyframe 实现 loading 动画
    meta标签常用属性
    Chrome开发者工具 debug 调试
    ajaxForm上传文件到本地服务器(封装)
    优化jQuery选择器
    “要有足够的耐心,一点一滴地改变世界”
    Event事件的三个阶段
    css控制页面文字不能被选中user-select:none;
    webstrom打开多个项目,webstrom常用快捷键
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2047322.html
Copyright © 2011-2022 走看看