项目架构开发:展现层(上)

上次我们创建了项目的服务层,服务层在业务逻辑简单,或项目运行初期不是很容易体现出他的价值;传送门:项目架构开发:服务层(上)

服务层专门处理非业务逻辑的一些功能,比如缓存、异常处理、组织多个应用逻辑等;这次我们搭建最上层的展现层,用到的知识面包括以下:

asp.net mvc5 + bootstrap + autofac + AutoMapper

这次我们没有用服务层,而是直接调用应用逻辑层接口方法,其实对小项目来说,这样已经足够了;服务层我们下次再讲吧

现在开始吧!

 

1、创建MVC + UnitTest

 

先搭建个框架,网上找的后台模板

 

 

 2、ViewModel

 UI的数据载体最好新建一个viewmodel,这样就不用依赖DTO或PO,因为页面上显示的数据实体一般比较大,会封装比DTO多的多的属性

LoginUserViewModel.cs

 1 using Infrastructure.Common;
 2 using System;
 3 using System.Collections.Generic;
 4 
 5 namespace Presentation.MVC.Models
 6 {
 7     public class LoginUserViewModel
 8     {
 9         public int RowNumber { get; set; }
10 
11         public Guid Id { get; set; }
12         public string LoginName { get; set; }
13         public short? IsEnabled { get; set; }
14         public DateTime? CreateTime { get; set; }
15     }
16 
17     public class LoginUserListViewModel
18     {
19         public List<LoginUserViewModel> Items { get; set; }
20     }
21 
22     public class LoginUserPageViewModel : PageViewModelBase
23     {
24         public List<LoginUserViewModel> Items { get; set; }
25     }
26 }

PageViewModelBase.cs (这个是分页时候用的,如上边标红实体)

 1 using Infrastructure.Common;
 2 
 3 namespace Presentation.MVC.Models
 4 {
 5     public class PageViewModelBase
 6     {
 7         public bool IsFirst { get; set; }
 8         public bool IsLast { get; set; }
 9 
10         public Page Page { get; set; }
11         public int Total { get; set; }
12         public int TotalPage
13         {
14             get
15             {
16                 return (Total % Page.PageSize) == 0 ? Total / Page.PageSize : (Total / Page.PageSize) + 1;
17             }
18         }
19 
20         public int PrePage
21         {
22             get
23             {
24                 if (Page.PageIndex == 1)
25                 {
26                     IsFirst = true;
27                     return 1;
28                 }
29                 else
30                 {
31                     IsFirst = false;
32                     return Page.PageIndex - 1;
33                 }
34             }
35         }
36         public int NextPage
37         {
38             get
39             {
40                 if (Page.PageIndex == TotalPage)
41                 {
42                     IsLast = true;
43                     return TotalPage;
44                 }
45                 else
46                 {
47                     IsLast = false;
48                     return Page.PageIndex + 1;
49                 }
50             }
51         }
52     }
53 }

 

 3、映射

 主要是DTO映射成ViewModel,这里我们用的是AutoMapper

AutoMapperConfiguration.cs,AutoMapper用法很简单,引用他,然后像下边代码那样写,然后再应用启动的时候加载

 1 using AutoMapper;
 2 using Business.ReverseDDD.Model;
 3 using Presentation.MVC.Models;
 4 
 5 namespace Presentation.MVC.Mappings
 6 {
 7     public class AutoMapperConfiguration
 8     {
 9         public static void Configure()
10         {
11             Mapper.CreateMap<LoginUser, LoginUserViewModel>();
12
13         }
14     }
15 }

Global.asax.cs

1 protected void Application_Start()
2         {
3             AreaRegistration.RegisterAllAreas();
4             FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
5             RouteConfig.RegisterRoutes(RouteTable.Routes);
6             BundleConfig.RegisterBundles(BundleTable.Bundles);
7 
8             AutoMapperConfiguration.Configure();
9         }

 

4、视图

为了方便,CURD都在一个页面实现了

  1 @model Presentation.MVC.Models.LoginUserPageViewModel
  2 @{
  3     ViewBag.Title = "Index";
  4     Layout = "~/Views/Shared/_Bootstrap.cshtml";
  5 }
  6 
  7 <div class="container">
  8     <h2></h2>
  9     <div class="panel panel-default">
 10         <div class="panel-heading">
 11             <h4 class="panel-title">
 12                 <a data-toggle="collapse" data-parent="#accordion"
 13                    href="#collapseOne" id="actionType">
 14                     新增用户
 15                 </a>
 16             </h4>
 17         </div>
 18         <div id="collapseOne" class="panel-collapse collapse">
 19             <div class="panel-body">
 20 
 21                 @using (Html.BeginForm("Add", "LoginUser", null, FormMethod.Post, new { @id = "formLoginUser", @class = "form-horizontal", role = "form" }))
 22                 {
 23                     @Html.AntiForgeryToken()
 24 
 25                     <div class="form-group">
 26                         <label for="firstname" class="col-sm-2 control-label">登录名</label>
 27                         <div class="col-sm-10">
 28                             <input type="text" class="form-control" name="LoginName" id="LoginName"
 29                                    placeholder="请输入登录账户名" />
 30                         </div>
 31                     </div>
 32                     <div class="form-group">
 33                         <label for="lastname" class="col-sm-2 control-label">登录密码</label>
 34                         <div class="col-sm-10">
 35                             <input type="text" class="form-control" name="Password" id="Password"
 36                                    placeholder="请输入登录密码" />
 37                         </div>
 38                     </div>
 39                     <div class="form-group">
 40                         <div class="col-sm-offset-2 col-sm-10">
 41                             <div class="checkbox">
 42                                 <label>
 43                                     <input type="checkbox" name="IsEnabled" id="IsEnabled" value="1" /> 是否有效
 44                                 </label>
 45                             </div>
 46                         </div>
 47                     </div>
 48 
 49                     <div class="form-group">
 50                         <div class="col-sm-offset-2 col-sm-10">
 51                             <input type="hidden" name="Id" id="Id" />
 52                             <button type="submit" class="btn btn-default">提交</button>
 53                         </div>
 54                     </div>
 55                 }
 56 
 57             </div>
 58         </div>
 59     </div>
 60 
 61 
 62     <h4>用户列表</h4>
 63     <table id="list" class="table table-striped table-bordered table-hover table-condensed">
 64         <thead>
 65             <tr>
 66                 <th>序号</th>
 67                 <th>登录名</th>
 68                 <th>是否有效</th>
 69                 <th>创建时间</th>
 70                 <th>操作</th>
 71             </tr>
 72         </thead>
 73         <tbody>
 74             @foreach (var item in Model.Items)
 75             {
 76                 <tr>
 77                     <td>@item.RowNumber</td>
 78                     <td>@item.LoginName</td>
 79                     <td>@item.IsEnabled</td>
 80                     <td>@item.CreateTime</td>
 81                     <td>
 82                         <button type="button" class="btn btn-link btn-xs" key="@item.Id" action="edit">修改</button>
 83                         <button type="button" class="btn btn-link btn-xs" key="@item.Id" action="delete">删除</button>
 84                     </td>
 85                 </tr>
 86             }
 87         </tbody>
 88     </table>
 89 
 90     <ul class="pagination">
 91         <li><a href="/LoginUsers/@Model.PrePage">&laquo;</a></li>
 92         @for (int index = 1; index <= Model.TotalPage; index++)
 93         {
 94             if (Model.Page.PageIndex == index)
 95             {
 96                 <li class="active"><a href="/LoginUsers/@index">@index</a></li>
 97             }
 98             else
 99             {
100                 <li><a href="/LoginUsers/@index">@index</a></li>
101             }
102         }
103         <li><a href="/LoginUsers/@Model.NextPage">&raquo;</a></li>
104     </ul>
105 
106     <script type="text/javascript">
107         $(function () {
108             $(".btn-link").click(function () {
109                 var obj = $(this);
110                 var key = obj.attr("key");
111                 if (key == undefined || key == null || key == "") return;
112 
113                 var action = obj.attr("action");
114 
115                 if (action == "delete") {
116                     CreateDeleteWindow(function () {
117                         location.href = "/LoginUser/Delete/" + key;
118                     });
119                 }
120 
121                 if (action == "edit") {
122                     $.ajax({
123                         url: "/LoginUser/Edit/" + key,
124                         type: "GET",
125                         dataType: 'json',
126                         success: function (result) {
127                             $("#Id").val(result.Id);
128                             $("#LoginName").val(result.LoginName);
129                             if (result.IsEnabled == 1) $("#IsEnabled").attr("checked", "true");
130                             else $("#IsEnabled").removeAttr("checked");
131 
132                             $('#collapseOne').collapse('show');
133                             $("#formLoginUser").attr("action", "/LoginUser/Edit");
134                             $("#actionType").html("修改用户");
135                         },
136                         error: function (e) {
137                             alert(e);
138                         }
139                     });
140                 }
141             });
142 
143         });
144     </script>
145 
146 </div>

其实也没什么特别的就是用了Bootstrap美化页面样式,对Bootstrap不懂的请点击这里

 

5、控制器

LoginUserController.cs

 1 using AutoMapper;
 2 using Business.DTO.Request;
 3 using Business.ReverseDDD.IApplication;
 4 using Infrastructure.Common;
 5 using LingExtensions;
 6 using Presentation.MVC.Models;
 7 using System;
 8 using System.Collections.Generic;
 9 using System.Web.Mvc;
10 
11 namespace Presentation.MVC.Controllers
12 {
13     public class LoginUserController : Controller
14     {
15         private ILoginUserApplication loginUserApplication;
16 
17         public LoginUserController(ILoginUserApplication loginUserApplication)
18         {
19             this.loginUserApplication = loginUserApplication;
20         }
21 
22         [Route("LoginUsers/{PageIndex=1}")]
23         public ActionResult Index(string PageIndex)
24         {
25             Page page = new Page();
26             page.PageIndex = PageIndex.ToInt(1);
27 
28             var model = new LoginUserPageViewModel();
29             var soure = this.loginUserApplication.GetPage(page, w => w.OrderByDescending(t => t.CreateTime));
30 
31             model.Items = Mapper.Map<List<LoginUserViewModel>>(soure.Item2);
32             model.Total = soure.Item1;
33             model.Page = page;
34 
35             return View(model);
36         }
37 
38         [HttpPost]
39         [ValidateAntiForgeryToken] 
40         public ActionResult Add(LoginUserCURequest entity)
41         {
42             this.loginUserApplication.Add(new LoginUserCURequest()
43             {
44                 Id = Guid.NewGuid(),
45                 LoginName = entity.LoginName,
46                 Password = entity.Password,
47                 IsEnabled = entity.IsEnabled
48             });
49 
50             return RedirectToAction("Index");
51         }
52 
53         [HttpGet]
54         public ActionResult Delete(string id)
55         {
56             this.loginUserApplication.Delete(Guid.Parse(id));
57 
58             return RedirectToAction("Index");
59         }
60 
61         [HttpGet]
62         public ActionResult Edit(Guid id)
63         {
64             var soure = this.loginUserApplication.Get(id);
65 
66             return Json(soure, JsonRequestBehavior.AllowGet);
67         }
68 
69         [HttpPost]
70         [ValidateAntiForgeryToken]
71         public ActionResult Edit(LoginUserCURequest entity)
72         {
73             this.loginUserApplication.Update(new LoginUserCURequest()
74             {
75                 Id = entity.Id,
76                 LoginName = entity.LoginName,
77                 Password = entity.Password,
78                 IsEnabled = entity.IsEnabled
79             });
80 
81             return RedirectToAction("Index");
82         }
83     }
84 }

 

都是演示CURD的功能,大家不要在意这些细节。。

看标红的地方,意思是将soure.Item2(是Tuple<int, IEnumerable<LoginUser>>类型)转换成List<LoginUserViewModel>

这就是AutoMapper的用法

 

还有是这里没有依赖具体应用逻辑组件的,只依赖了业务逻辑接口using Business.ReverseDDD.IApplication;

这个是为了解耦,而且对分层并行开发很有用,项目前端后端开发都不用依赖谁开发完才能往下继续;

 

控制器我们用的是依赖注入Autofac组件:

 

 6、UnitTest

LoginUserControllerTest.cs, 记得也要Mapping哦

 

测试通过了

 

7、UI,我们来看看界面功能

 7.1 新增用户

 

用户新增成功,列表正常显示数据

 

7.2 修改数据

修改成功

7.3 分页正常

 

至此,展现层完成了

 

8、完整项目架构如下

 

转载于:https://www.cnblogs.com/lanxiaoke/p/6540431.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 基于 AJAX 的多架构开发项目,需要考虑以下几个方面: 1.前端技术 前端技术包括 HTML、CSS、JavaScript 等,其中 JavaScript 是 AJAX 技术的核心。可以使用 jQuery、Vue.js、React 等前端框架来简化开发。 2.后端技术 后端技术可以选择 PHP、Java、Python 等语言,使用框架例如 SpringMVC、Django、Flask 等来实现数据的处理和存储。 3.AJAX 技术 AJAX 技术可以通过 XMLHttpRequest 对象来实现。通过 AJAX 可以异步地请求后端数据,并将数据插入到前端页面中,从而实现无刷新的页面交互效果。 4.多架构架构包括表现、业务逻辑和数据访问。表现负责前端页面的展示和交互,业务逻辑负责业务逻辑的处理,数据访问负责数据的存储和访问。 在多架构中,前端页面通过 AJAX 技术向业务逻辑发起请求,业务逻辑处理请求并访问数据访问,最终将处理结果返回给前端页面。 综上所述,基于 AJAX 的多架构开发项目需要掌握前端技术、后端技术、AJAX 技术和多架构的相关知识。 ### 回答2: 基于Ajax的多架构开发项目是一种基于Web的应用程序开发模式。它将应用程序的不同次分离开来,包括展示、业务逻辑和数据访问,并通过Ajax(Asynchronous JavaScript and XML)技术实现前后端之间的数据交互和异步通信。 该多架构开发项目具有以下特点: 1. 分离前后端:通过Ajax技术前端页面与后端服务器之间的数据交互可以实现无需刷新页面的异步通信,提高用户体验。前端使用JavaScript异步请求数据并将结果动态更新到页面上,后端则负责处理请求并返回所需数据。 2. 提高响应速度:由于Ajax的异步特性,前端可以同时发送多个请求,从而减少页面加载时间和数据传输时间。用户能够迅速地获取数据,同时可以在等待数据的同时进行其他操作。 3. 可重用性和可维护性:将应用程序的不同次分离开来,使得各个次的代码更清晰、更易于维护。开发人员可以专注于各自次的开发,降低代码耦合度,提高代码重用性。 4. 安全性增强:通过Ajax技术,可以减少对敏感数据的暴露,因为只有在用户请求数据时才会传输相关数据,提高了应用程序的安全性。 5. 提供更好的用户体验:通过无需刷新页面的数据更新,用户能够更快地获取所需信息,并能够在页面上进行实时交互,提高了用户的满意度和使用体验。 总之,基于Ajax的多架构开发项目能够提供更好的用户体验、提高响应速度、增强应用程序的安全性,并且具有良好的代码结构和可维护性,是一种值得推荐的开发模式。 ### 回答3: 基于Ajax的多架构开发项目是一种用于构建Web应用程序的技术方案。它将应用程序的不同部分划分为多个次,每个次负责不同的功能和任务,通过Ajax技术进行交互和通信。 这种架构一般由以下几组成: 1. 表示:负责将用户界面展示给用户,并接收用户的交互请求。通常使用HTML、CSS和JavaScript编写,可以实现动态内容的呈现和用户界面的交互。 2. 业务逻辑:负责处理用户请求并进行业务处理。它包含了应用程序的核心逻辑,处理用户的操作和请求,并与数据访问进行交互。这一通常使用服务器端的脚本语言(如PHP、Python或Java)来实现。 3. 数据访问:负责与数据库进行数据的读取、写入和更新操作。通过与数据库进行交互,将数据传递给业务逻辑进行处理,并将处理结果返回给表示。在这一,可以使用SQL语言编写数据库操作语句。 4. 数据库:负责存储应用程序的数据。可以使用关系型数据库(如MySQL、Oracle)或非关系型数据库(如MongoDB)来存储数据。 通过Ajax技术,这些不同次的组件可以实现快速、无刷新的数据交互。在用户与应用程序进行交互时,表示可以通过Ajax技术发送异步请求到业务逻辑,业务逻辑再与数据访问进行交互,最后将结果返回给表示用于页面的更新。 基于Ajax的多架构开发项目具有以下优势: 1. 增强用户体验:通过Ajax技术,实现了快速响应和无刷新的数据更新,提高了用户与应用程序的交互体验。 2. 解耦合性:通过将应用程序的不同部分划分为多个次,实现了各组件之间的解耦合,方便维护和扩展。 3. 可重用性:每个次只负责特定的功能和任务,可以实现组件的重用,提高开发效率。 4. 安全性:通过合理的权限控制和加密机制,保障了数据的安全性。 综上所述,基于Ajax的多架构开发项目可以提升Web应用程序的性能、可维护性和用户体验,并提供了一种灵活可扩展的架构设计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值