博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AspNetCore-MVC实战系列(三)之个人中心
阅读量:6632 次
发布时间:2019-06-25

本文共 12983 字,大约阅读时间需要 43 分钟。

AspNetCore - MVC实战系列目录

. 

. git源码:

. 

. 

开篇唠嗑

这实战第三章,也就是本章的时候为了响应博友们的要求,已经把的代码开源到了了,也为了NetCore的美好明天贡献自己微薄的一份力,尽管已经开源了源码,我还是会坚持写完netcore实战系列的博文,希望大家多多支持;还有就是今天为了缓解51假期综合征能进入学习正规,早上习惯性的打开博客园,让我吃惊了,看着今天编辑推荐的博文还以为博客园出现什么故障了,如此不堪的文章尽然被编辑推荐,我在想怎么了是审核人员的不负责么,要说不负责为什么我写了这么久的博文,一篇都没被编辑推荐过呢呵呵,这里还是希望博客园能对内容的审核更严谨,而不是马马虎虎,毕竟我们很多人还是支持园区的;

个人中心模块设计

对于一个暂时只有上传,点赞,阅览的雏形网站来说,个人中心没有太多能够展示的,因此我这里把用户常用操作的记录也展示出来了,和个简单的统计模块,所以就有了以下的个人中心模块:

由上图能够看到内容不多,但是从技术角度上来说也涉及到了几个知识点和注意事项;

代码知识点分享

获取客户端ip和服务端ip+port

首先我们就从用户记录日志开始讲起,对刚刚使用netcore的朋友,对怎么获取操作人的ip有点疑惑,这里我就分享下我的经验,避免您们再做各种测试或者查资料了,这里我为了代码使用方便,直接通过静态扩展方法对Controller扩展了获取ip的方法:

1   public static string GetUserIp(this Controller controller)2   {3       return controller.HttpContext.Connection.RemoteIpAddress.ToString();4   }

没错客户端的ip信息存储于 HttpContext.Connection 中,上面是获取ip再来分享怎么获取网站的host和port吧,只需要使用 Request.Host 的代码:

1 var appUrl = $"http://{Request.Host.Host}:{Request.Host.Port}"

验证用户是否登录

对于个人中心来说往往需要验证用户是否登录,也就是是否存在咋们说通session,同样为了方便我重写了一个父Controller,凡是需要登录验证的Controller都继承于她:

1  public class BaseController : Controller 2     { 3         public MoUserInfo _MyUserInfo; 4  5         public override void OnActionExecuting(ActionExecutingContext context) 6         { 7             _MyUserInfo = context.HttpContext.Session.Get
(context.HttpContext.Session.SessionKey()); //获取登录session 8 if (_MyUserInfo == null) 9 {10 context.Result = new RedirectToActionResult(nameof(MemberController.Login), "Member", new { ReturnUrl = context.HttpContext.Request.Path });11 }12 13 ViewData["MyUserInfo"] = _MyUserInfo;14 15 base.OnActionExecuting(context);16 }17 }

上面的这种方式通常也是大家对于登录验证用的最多的方式之一了,这里暂时没有用到过滤器等其他的验证方式;

自定义分页TagHelper

对于个人中心的登陆日志爱心积分增加记录来说,一页是展示不完的,往往需要分页来展示,为此我采用了重写TagHelper的方式,来自定义一个分页控件;首先我定义一个这样的分页属性实体:

1 ///  2     /// 分页option属性 3     ///  4     public class MoPagerOption 5     { 6         ///  7         /// 当前页  必传 8         ///  9         public int CurrentPage { get; set; }10         /// 11         /// 总条数  必传12         /// 13         public int Total { get; set; }14 15         /// 16         /// 分页记录数(每页条数 默认每页15条)17         /// 18         public int PageSize { get; set; }19 20         /// 21         /// 路由地址(格式如:/Controller/Action) 默认自动获取22         /// 23         public string RouteUrl { get; set; }24 25         /// 26         /// 样式 默认 bootstrap样式 127         /// 28         public int StyleNum { get; set; }29 30         /// 31         /// 地址与分页数拼接符32         /// 33         public string JoinOperateCode { get; set; }34     }

然后自定个PagerTagHelper类来继承TagHelper,并且重写她的 public override void Process(TagHelperContext context, TagHelperOutput output) 函数,为了简洁我已经在代码注意的地方加上了注释:

1 ///  2     /// 分页标签 3     ///  4     public class PagerTagHelper : TagHelper 5     { 6  7         public MoPagerOption PagerOption { get; set; } 8  9 10         public override void Process(TagHelperContext context, TagHelperOutput output)11         {12 13             output.TagName = "div";14 15             //PagerOption.JoinOperateCode = string.IsNullOrWhiteSpace(PagerOption.JoinOperateCode) ? "/" : PagerOption.JoinOperateCode;16             if (PagerOption.PageSize <= 0) { PagerOption.PageSize = 15; }17             if (PagerOption.CurrentPage <= 0) { PagerOption.CurrentPage = 1; }18             if (PagerOption.Total <= 0) { return; }19 20             //总页数21             var totalPage = PagerOption.Total / PagerOption.PageSize + (PagerOption.Total % PagerOption.PageSize > 0 ? 1 : 0);22             if (totalPage <= 0) { return; }23             else if (totalPage <= PagerOption.CurrentPage)24             {25 26                 PagerOption.CurrentPage = totalPage;27             }28 29 30             //当前路由地址31             if (string.IsNullOrEmpty(PagerOption.RouteUrl))32             {33 34                 //PagerOption.RouteUrl = helper.ViewContext.HttpContext.Request.RawUrl;35                 if (!string.IsNullOrEmpty(PagerOption.RouteUrl))36                 {37 38                     var lastIndex = PagerOption.RouteUrl.LastIndexOf("/");39                     PagerOption.RouteUrl = PagerOption.RouteUrl.Substring(0, lastIndex);40                 }41             }42 43             //构造分页样式44             var sbPage = new StringBuilder(string.Empty);45             switch (PagerOption.StyleNum)46             {47                 case 2:48                     {49 50                         break;51                     }52                 default:53                     {54                         #region 默认样式55 56                         PagerOption.RouteUrl = PagerOption.RouteUrl.TrimEnd('/');57                         sbPage.Append("
");85 #endregion86 }87 break;88 }89 90 output.Content.SetHtmlContent(sbPage.ToString());91 }92 93 }

到此后台封装的方法就完成了,此刻我们还需要再Views/_ViewImports.cshtml文件中增加如下内容,才能正常的只用我们自定义的标签:

1 @using LovePicture.Web2 @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers3 @addTagHelper LovePicture.Web.Extends.PagerTagHelper, LovePicture.Web  //这里是增加的内容

到此我们分页的配置就完成了,下面就开始介绍怎么来使用封装的分页标签了;先看Action中这样来写:

1 public IActionResult UserLogs(string id) 2         { 3             if (string.IsNullOrWhiteSpace(id)) { return BadRequest(); } 4  5             #region  构造参数 6             var paramArr = id.Split('-'); 7             if (paramArr.Length != 2) { return BadRequest(); } 8             var page = Convert.ToInt32(paramArr[1]); 9             var codeId = Convert.ToInt32(paramArr[0]);10             if (codeId != (int)EnumHelper.EmLogCode.登录 && codeId != (int)EnumHelper.EmLogCode.积分)11             {12                 return BadRequest();13             }14             page = page <= 0 ? 1 : page;15 16             //初始化分页类17             var pageOption = new MoPagerOption18             {19                 CurrentPage = page,20                 PageSize = 15,21                 Total = 0,22                 RouteUrl = $"/usercenter/userlogs/{codeId}",23                 StyleNum = 1,24 25                 JoinOperateCode = "-"26             };27             #endregion28 29             var userLogs = _db.ToUserLog.30                  Where(b => b.UserId == _MyUserInfo.Id && b.CodeId == codeId).AsEnumerable();31             pageOption.Total = userLogs.Count();32             userLogs = userLogs.OrderByDescending(b => b.Id).33                  Skip((pageOption.CurrentPage - 1) * pageOption.PageSize).34                  Take(pageOption.PageSize).35                  ToList();36             //通过ViewData方式分页属性数据传递到试图中37             ViewBag.PagerOption = pageOption;38 39             var userLog = new ToUserLog40             {41                 CodeId = codeId,42                 Des = $"{Enum.GetName(typeof(EnumHelper.EmLogCode), codeId)}记录"43             };44             ViewData["userLog"] = userLog;45 46             return View(userLogs);47         }

最后需要再试图中绑定模型,和使用标签pager:

1 @using LovePicture.Com 2 @using LovePicture.Model.Models 3 @using LovePicture.Model.MoClass 4 @using LovePicture.Web.Extends 5 @model IEnumerable
6 @{ 7 var userLog = ViewData["userLog"] as ToUserLog; 8 ViewData["Title"] = userLog.Des; 9 var userInfo = ViewData["MyUserInfo"] as MoUserInfo;10 userInfo.Status = 1;11 }12
13 @await Html.PartialAsync("UserCenterGroup", userInfo)14
15

个人中心

16

17
18
19
20
21
22
23
24
25
26 @foreach (var item in Model)27 {28
29
32
33 }34
35
@userLog.Des
30 @item.Des31
36
37
38
39
40
41
42

为什么通过ajax获取数据来绑定数据,而不用Action返回实体模型来绑定试图呢

由于什么统计数据,上传记录,登录记录,爱心记录等数据来源方式基本都是统一的来自数据库(暂未只用缓存),所以没有什么特别需要讲的地方,反而关注分析了为什么用ajax获取后再绑定数据到页面的方式;对于ajax的方式请求来说,通常都是前端异步的代名词,一个个人中心来说需要展示很多的信息,尤其是还有统计等信息,如果通过Action-View方式直接绑定Model来加载数据,那无疑是让用户体验变差了,因为这种方式需要等待后台把数据加载完后才能展示页面给客户,经过我对爱留图个人中心如果采用这种方式展示数据的统计,需要花10s(本地)因此在没有使用缓存的基础上,我果断的使用了前端异步展示的方式(ajax);当然对于在mvc模式中使用ajax的方式来绑定数据感觉有些异类,的确是这样,因为netcore的mvc目的就是让咋们快速构建系统的,不过有些时候还是需要更具具体的情况来选择具体的方式;来看看个人中心的统计信息对应的代码吧:

1 #region 统计信息 2  3         [HttpPost] 4         public JsonResult UserStatis() 5         { 6             var data = new MoLoveData(); 7             var list = new List
(); 8 9 //留图数(公有)10 var userContent = _db.ToContent.Where(b => b.UserId == _MyUserInfo.Id).AsEnumerable();11 var total1 = userContent.Count(b => b.Status == (int)EnumHelper.EmContentStatus.公有);12 list.Add(new13 {14 name = "留图数(公有)",15 total = $"{ total1}(张)"16 });17 //留图数(私有)18 var total2 = userContent.Count(b => b.Status == (int)EnumHelper.EmContentStatus.私有);19 list.Add(new20 {21 name = "留图数(私有)",22 total = $"{ total2}(张)"23 });24 //点赞数25 var total3 = userContent.Where(b => b.Status != (int)EnumHelper.EmContentStatus.删除).Sum(b => b.ZanNum);26 list.Add(new27 {28 name = "点赞数",29 total = $"{ total3}(个)"30 });31 //浏览数32 var total4 = userContent.Where(b => b.Status != (int)EnumHelper.EmContentStatus.删除).Sum(b => b.ReadNum);33 list.Add(new34 {35 name = "浏览数",36 total = $"{ total4}(次)"37 });38 //爱心积分39 var total5 = _MyUserInfo.LevelNum;40 list.Add(new41 {42 name = "爱心积分",43 total = $"{ total5}(分)"44 });45 data.Data = list;46 data.IsOk = true;47 return Json(data);48 }49 50 #endregion

通过 return Json(data); 方法json对象给请求方;然后前端需要通过ajax来请求:

1 getUserStatis: function (tabId) { 2             if (tabId.length <= 0) { return; } 3             $.post("/usercenter/UserStatis", { x: 520 }, function (data) { 4                 if (data) { 5  6                     if (!data.isOk) { $("#" + tabId + " tbody").html('获取失败,稍后重试'); return; } 7                     var trArr = []; 8                     $.each(data.data, function (i, item) { 9                         //console.log(item);10                         trArr.push('' + item.name + '' + item.total + '');11                     });12                     if (trArr.length > 0) {13                         $("#" + tabId + " tbody").html(trArr.join(''));14                     } else {15                         $("#" + tabId + " tbody").html('暂无');16                     }17                 }18             });19         }

为了更好的用户体验,我在ajax还没有请求加载数据前,默认在数据展示区域增加一个加载的图片背景:

1  
2
3
4
统计信息
5
6
7
8
9
10
11
12
13
14
15
18
19
20
统计名称 数值
16
17
21
22
23

对应的loading类样式:

1 .loading {2     width: 100%;3     height: 32px;4     background: url('../images/load.gif') no-repeat center top;5 }

最后上传一个效果图吧,表示表示:

转载地址:http://qbbvo.baihongyu.com/

你可能感兴趣的文章
如何在centos下使python开发语法高亮显示
查看>>
Windows Phone 7 问答(答案部分)
查看>>
macvlan 网络隔离和连通 - 每天5分钟玩转 Docker 容器技术(57)
查看>>
努力打拼
查看>>
Android第十期 - 百度地图
查看>>
linux下删除特殊字符中文乱码文件方法
查看>>
KVM虚拟机静态迁移
查看>>
IT管理新举措
查看>>
Python封装及解构
查看>>
frame-relay map IP
查看>>
CentOS 6.5 Varnish缓存服务详解及应用实现 推
查看>>
Oracle Study之--Oracle TimeZone升级
查看>>
PIM规则总结
查看>>
Amoeba实现mysql主从读写分离2
查看>>
Swift中正则使用正则的几种方式
查看>>
SQL Server 2000 : gethostbyname: Error 11004
查看>>
log4j下载地址及日志文件输入位置配置
查看>>
Tomcat下Servlet配置精解
查看>>
吞吐量与网络流量对应关系剖析
查看>>
新功能:OSS访问日志实时分析
查看>>