AspNetCore - MVC实战系列目录
. 爱留图网站诞生
. git源码:https://github.com/shenniubuxing3/LovePicture.Web
. AspNetCore - MVC实战系列(一)之Sqlserver表映射实体模型
. AspNetCore-MVC实战系列(二)之通过绑定邮箱找回密码
开篇唠嗑
今天唠唠家常吧,最近一段时间媳妇闹着上班,由于这里算郊区吧所以希望我能在公司找个合适的职位,考虑到需要上下班接送孩子上学,所以工作的时间只能在早9晚5左右,不然人的精力有限会很疲倦的,因此通过各种渠道,最总她被安排到了xxx产品部门,从基本的开始学习,简单介绍下她以前的工作主要是服装店销售衣服的,可以这样说使用电脑的时间或者办公软件的时间很少,在家用电脑也就是看看电影,听歌等,平常没有涉及到各种办公软件,在这层前提下,这几天在公司学习什么业务,后台系统,办公通讯工具的使用竟然有打退堂鼓的意思,各种说自己不适合;想想以前在家里教她什么微信,支付宝转账等软件的使用,很明显就能感觉出来毛躁,爱面子。。。等;这有点像那种刚毕业又找到从来没了解过的专业工作并且时常抱怨的朋友一样,说什么这不适合,哪不适合,带的人怎么的不好,怎么的看不顺眼;这种类型的朋友和我媳妇儿一样一般会选择辞职吧,这里个人以工作6年的经验说下个人见解:在职场上遇到困难就放弃并且干什么都是怕苦怕累,现在年轻还好有家里支柱,当您成为家里主要经济来源的时候,您还有退路么,您还干轻易放弃么;故此昨天晚上狠狠的说了媳妇一顿,哈哈真是涨了地位;
vs2017怎么压缩js和css文件
同样为了文章的干货性质,这里分享下自己再开发Netcore的Mvc时候利用vs2017怎么压缩js和css文件的方法,由于也netframwork的mvc不一样(她是写在代码中的)所以需要手动配置并输入命令,压缩主要分两步;首先需要在web项目工程文件中添加如下配置信息:
1 项目中添加
2 <ItemGroup>
3 <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.0-msbuild3-final" />
4 <DotNetCliToolReference Include="BundlerMinifier.Core" Version="2.2.281" />
5 </ItemGroup>
然后查看下bundleconfig.json文件中的配置,一般默认的内容有:
1 [
2 {
3 "outputFileName": "wwwroot/css/site.min.css",
4 // An array of relative input file paths. Globbing patterns supported
5 "inputFiles": [
6 "wwwroot/css/site.css"
7 ]
8 }, 9 { 10 "outputFileName": "wwwroot/js/site.min.js", 11 "inputFiles": [ 12 "wwwroot/js/site.js" 13 ], 14 // Optionally specify minification options 15 "minify": { 16 "enabled": true, 17 "renameLocals": true 18 }, 19 // Optionally generate .map file 20 "sourceMap": false 21 } 22 ]
我就以默认配置的js文件和css文件为例,运行命令: dotnet bundle 能够看到如下效果:
此时打开您项目的wwwroot文件里面的css或者js文件,能够看到压缩成一行的代码:
账户设置 - 修改头像
对于几乎每个系统来说,账户设置普遍包括有修改个人信息,头像,密码这3部分的操作,本篇的主要分享内容也是围绕这3部分来讲解和分享代码;首先来看看爱留图开源代码的修改头像模块吧,对于修改头像功能往往都是单独的,所以我们可以通过如下界面跳转到仅仅只有上传头像的界面:
修改头像主要功能是上传头像,如果上传的图片过大就限制上传或者系统生成一个小头像的图片,这样避免用户查看头像时候由于图片过大,加载速度变慢了;来看看主要处理上传的Action方法吧:
1 [HttpPost] 2 public async Task<IActionResult> UpHeadPhoto([Bind("Id")]MoUserInfo moUserInfo) 3 { 4 5 var file = Request.Form.Files.Where(b => 6 b.Name == "myHeadPhoto" && 7 b.ContentType.Contains("image")). 8 SingleOrDefault(); 9 if (file == null) { this.MsgBox("请选择上传的头像图片!"); return View(_MyUserInfo); } 10 11 var maxSize = 1024 * 1024 * 4; 12 if (file.Length > maxSize) 13 { 14 this.MsgBox("头像图片不能大于4M!"); return View(_MyUserInfo); 15 } 16 17 var fileExtend = file.FileName.Substring(file.FileName.LastIndexOf('.')); 18 var fileNewName = $"{DateTime.Now.ToString("yyyyMMddHHmmssfff")}{fileExtend}"; 19 var path = Path.Combine(_selfSetting.UpHeadPhotoPath, fileNewName); 20 using (var stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite)) 21 { 22 await file.CopyToAsync(stream); 23 } 24 25 //更新数据 26 var viewPath = $"{_selfSetting.ViewHeadPhotoPath}/{fileNewName}"; 27 28 var user = _db.ToUserInfo.Where(b => b.Id == _MyUserInfo.Id).SingleOrDefault(); 29 if (user == null) { this.MsgBox("上传失败,请稍后重试!"); return View(_MyUserInfo); } 30 user.HeadPhoto = viewPath; 31 user.LevelNum += (int)EmLevelNum.修改头像; 32 var result = await _db.SaveChangesAsync(); 33 if (result > 0) 34 { 35 _MyUserInfo.HeadPhoto = viewPath; 36 _MyUserInfo.LevelNum = user.LevelNum; 37 HttpContext.Session.Set<MoUserInfo>(HttpContext.Session.SessionKey(), _MyUserInfo); 38 this.MsgBox("上传成功!"); 39 40 _db.ToUserLog.Add(new ToUserLog 41 { 42 CodeId = (int)EmLogCode.积分, 43 CreateTime = DateTime.Now, 44 Des = $"【修改头像】 +{(int)EmLevelNum.修改头像}", 45 UserId = _MyUserInfo.Id 46 }); 47 await _db.SaveChangesAsync(); 48 49 } 50 else { this.MsgBox("上传失败,请稍后重试!"); } 51 return View(_MyUserInfo); 52 }
在写博文的时候才发现,这代码原来有部分多余的写法,仔细的朋友应该看出来了 [Bind("Id")]MoUserInfo moUserInfo 我在action中根本没有用到呢,不知道当初写的时候是怎么想的哈哈,因为这里我直接通过 Request.Form.Files 来获取上传的头像图片文件信息,注意了由于Files是获取多个文件信息,但是我们上传头像的时候只会有一张图片存在才是合理的,所以我通过上传的元素file对应的name='myHeadPhoto'来让files匹配出对应的文件信息,所以有了这样的筛选操作:
1 Request.Form.Files.Where(b =>b.Name == "myHeadPhoto" && b.ContentType.Contains("image")).SingleOrDefault()
对于存放图片文件的路径我是通过读取配置在appsettings.json文件中的节点配置的,正如我AspNetCore - MVC实战系列(一)之Sqlserver表映射实体模型写到的怎么通过Options获取appsettings.json文件配置信息是一样的操作,如果你可以直接取那里看吧;然后通过 await file.CopyToAsync(stream); 来拷贝复制文件流到生成的图片文件里面,以此完成上传功能;至于其他的添加积分,上传记录日志等这些都是业务需要的操作,这里不在详解;
账户设置 - 修改基本信息
基本信息的修改没有什么特别的地方,提一下注意点对于一个登陆用户来说,修改了基本信息,如果你session存储有这些信息也同样在更新数据表数据的时候也需要更新session存储的信息,这样才能保证修改后,用户看到的是修改的内容;
1 [HttpPost] 2 public async Task<IActionResult> ModifyUser(MoUserInfo moUserInfo) 3 { 4 if (moUserInfo.Id <= 0) 5 { 6 this.MsgBox("修改失败,请稍后重试。"); 7 return View(_MyUserInfo); 8 } 9 else if (string.IsNullOrWhiteSpace(moUserInfo.NickName)) 10 { 11 this.MsgBox("昵称不能为空!"); 12 return View(_MyUserInfo); 13 } 14 15 _MyUserInfo.NickName = moUserInfo.NickName; 16 _MyUserInfo.Tel = moUserInfo.Tel; 17 _MyUserInfo.Sex = moUserInfo.Sex; 18 _MyUserInfo.Birthday = moUserInfo.Birthday; 19 20 _MyUserInfo.Blog = moUserInfo.Blog; 21 _MyUserInfo.Introduce = moUserInfo.Introduce; 22 23 var user = _db.ToUserInfo.Where(b => b.Id == _MyUserInfo.Id).SingleOrDefault(); 24 if (user == null) { this.MsgBox("修改失败,请稍后重试"); return View(_MyUserInfo); } 25 26 user.NickName = _MyUserInfo.NickName; 27 user.Tel = _MyUserInfo.Tel; 28 user.Sex = _MyUserInfo.Sex; 29 user.Birthday = _MyUserInfo.Birthday; 30 31 user.Blog = _MyUserInfo.Blog; 32 user.Introduce = _MyUserInfo.Introduce; 33 34 var result = await _db.SaveChangesAsync(); 35 if (result > 0) 36 { 37 HttpContext.Session.Set<MoUserInfo>(HttpContext.Session.SessionKey(), _MyUserInfo); 38 this.MsgBox("修改成功!"); 39 } 40 else { this.MsgBox("修改失败,请稍后重试!"); } 41 42 return View(_MyUserInfo); 43 }
为了避免分享的内容枯燥性,这里分享一些通用方法,如用户绑定了手机号或邮箱,处于安全考虑这些是不能直接在web网页展示出来的需要类似于:8312***333.com的*号来屏蔽,这里提供个扩展方法:
1 /// <summary> 2 /// 格式化安全信息 3 /// </summary> 4 /// <param name="val"></param> 5 /// <param name="startLen"></param> 6 /// <param name="endLen"></param> 7 /// <returns></returns> 8 public static string FomartPhone(this string val, int startLen = 3, int endLen = 3) 9 { 10 if (string.IsNullOrWhiteSpace(val)) { return ""; } 11 12 var len = val.Trim().Length; 13 var start = string.Empty; 14 var end = string.Empty; 15 if (len > startLen) { start = val.Substring(0, startLen); } else { start = val; } 16 if (len - endLen > startLen) { end = val.Substring(len - endLen, endLen); } 17 return string.Format("{0}***{1}", start, end); 18 }
很简单的吧,不过这种也是很常用并且是需要的一个方法,用起来仅仅只需要这样: Model.Email.FomartPhone(startLen:4,endLen:4) ;再来个计算注册时间距离现在多少天多少月多少年的方法:
1 /// <summary> 2 /// 获取据当前时间的时间间隔:如1年1月1日 3 /// </summary> 4 /// <param name="date"></param> 5 /// <param name="yearNum"></param> 6 /// <param name="monthNum"></param> 7 /// <returns></returns> 8 public static string FormatDateToNow(this DateTime date, int yearNum = 365, int monthNum = 31) 9 { 10 var subTime = DateTime.Now.Subtract(date); 11 12 var dayNum = subTime.Days; 13 14 var year = dayNum / yearNum; 15 var month = dayNum % yearNum / monthNum; 16 var day = dayNum % yearNum % monthNum; 17 18 var str = year > 0 ? $"{year}年" : ""; 19 str += month > 0 ? $"{month}月" : ""; 20 str += day > 0 ? $"{day}天" : "1天"; 21 22 return str; 23 }
由于也是扩展的DateTime的方法,所以可以直接这样用 @Model.CreateTime.FormatDateToNow() ,然后看起来的效果是这样:
账户设置 - 修改密码
修改密码这东西往往需要很多验证,主要为了防盗;应对这些防盗的方法有绑定邮箱,绑定手机号码,在AspNetCore-MVC实战系列(二)之通过绑定邮箱找回密码已经讲解了如果通过绑定邮箱找回密码的流程,有需要的朋友可以参考下,主要通过发送重置密码链接,修改密码;由于偷懒账户设置的修改密码,我就没有做这么多的流程验证了,仅仅只需要填写密码和重复密码即可:
1 public IActionResult ModifyPwd() 2 { 3 return View(new MoRegisterUser { UserName = _MyUserInfo.UserName }); 4 } 5 6 [HttpPost] 7 public async Task<IActionResult> ModifyPwd([Bind("UserName,UserPwd,ComfirmPwd")]MoRegisterUser moRegisterUser) 8 { 9 if (ModelState.IsValid) 10 { 11 var user = _db.ToUserInfo.Where(b => b.Id == _MyUserInfo.Id).SingleOrDefault(); 12 if (user == null) { this.MsgBox("修改失败,请稍后重试"); return View(moRegisterUser); } 13 user.UserPwd = PublicClass._Md5(moRegisterUser.UserPwd.Trim()); 14 var result = await _db.SaveChangesAsync(); 15 if (result > 0) 16 {18 this.MsgBox("修改成功!"); 19 } 20 else { this.MsgBox("修改失败,请稍后重试!"); } 21 } 22 return View(moRegisterUser); 23 }
结尾告白
到这里AspNetCore-MVC实战系列基本就讲解的差不多了,内容主要以业务场景居多,基本都是很常见的功能,代码也已经开源分享了,刚接触netcore并且有兴趣的朋友可以参考;老实说对于这种感觉没有什么特别之处的功能讲解很费劲的,不过在本次开发过程中遇到的一些问题还是值得了解下的,这些都分享在每张讲解的内容里面了,需要注意看下才能发现总结的经验;最近在做公司系统,该系统会大量的发送邮件,因此简单构思了个邮件系统,如果可以将再下一篇和大家分享;谢谢大家的支持。