ASP.NET CORE小试牛刀:干货及完整源代码

发表于:2017-7-20 09:44

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:我叫So    来源:博客

分享:
  后端freestyle
  后端核心其实就展示层(控制器层)和应用服务层(业务逻辑层),展示层通过应用服务层定义一些业务接口来交互,他们之间的数据传输通过 dto 对象。
  对于 post 请求的数据,有一些同学为了图方便,直接用实体来接收前端数据,不建议大家这么做。我们是规定必须建一个 model 类来接收,也就是 dto。下面是添加、更新和删除的示例:
  [HttpPost]
  public ActionResult Add(AddWikiMenuItemInput input)
  {
      IWikiMenuItemAppService service = this.CreateService<IWikiMenuItemAppService>();
      WikiMenuItem entity = service.Add(input);
      return this.AddSuccessData(entity);
  }
  [HttpPost]
  public ActionResult Update(UpdateWikiMenuItemInput input)
  {
      IWikiMenuItemAppService service = this.CreateService<IWikiMenuItemAppService>();
      service.Update(input);
      return this.UpdateSuccessMsg();
  }
  [HttpPost]
  public ActionResult Delete(string id)
  {
      IWikiMenuItemAppService service = this.CreateService<IWikiMenuItemAppService>();
      service.Delete(id);
      return this.DeleteSuccessMsg();
  }
  AddWikiMenuItemInput 类:
  [MapToType(typeof(WikiMenuItem))]
  public class AddWikiMenuItemInput : ValidationModel
  {
      public string ParentId { get; set; }
      [RequiredAttribute(ErrorMessage = "名称不能为空")]
      public string Name { get; set; }
      public string DocumentId { get; set; }
      public bool IsEnabled { get; set; }
      public int? SortCode { get; set; }
  }
  数据校验我们使用 .NET 自带的 Validator,所以我们可以在 dto 的成员上打一些验证标记,同时要继承我们自定义的一个类,ValidationModel,这个类有一个 Validate 方法,我们验证数据是否合法的时候只需要调用下这个方法就好了:dto.Validate()。按照常规做法,数据校验应该在控制器的 Action 里,但目前我是将这个校验操作放在了应用服务层里。
  对于 dto,最终是要与实体建立映射关系的,所以,我们还要给 dto 打个 [MapToType(typeof(WikiMenuItem))] 标记,表示这个 dto 类映射到 WikiMenuItem 实体类。
  应用服务层添加、更新和删除数据实现:
  public class WikiMenuItemAppService : AdminAppService, IWikiMenuItemAppService
  {
      public WikiMenuItem Add(AddWikiMenuItemInput input)
      {
          input.Validate();
          WikiMenuItem entity = this.DbContext.InsertFromDto<WikiMenuItem, AddWikiMenuItemInput>(input);
          return entity;
      }
      public void Update(UpdateWikiMenuItemInput input)
      {
          input.Validate();
          this.DbContext.UpdateFromDto<WikiMenuItem, UpdateWikiMenuItemInput>(input);
      }
      public void Delete(string id)
      {
          id.NotNullOrEmpty();
          bool existsChildren = this.DbContext.Query<WikiMenuItem>(a => a.ParentId == id).Any();
          if (existsChildren)
              throw new InvalidDataException("删除失败!操作的对象包含了下级数据");
          this.DbContext.DeleteByKey<WikiMenuItem>(id);
      }
  }
  DbContext.InsertFromDto 和 DbContext.UpdateFromDto 是 ORM 扩展的方法,通用的,定义好 dto,并给 dto 标记好映射实体,调用这两个方法时传入 dto 对象就可以插入和更新。从 dto 到将数据插进数据库,有数据校验,也不用拼 sql!这都是基于 ORM 和 AutoMapper 的配合。
  日常开发中,频繁的写 try catch 代码是件很蛋疼的事,因此,我们可以定义一个全局异常处理的过滤器去记录错误信息,配合 NLog 组件,MVC中任何错误都会被记录进文件。所以,如果下载了源码你会发现,项目中几乎没有 try catch 类的代码。
  public class HttpGlobalExceptionFilter : IExceptionFilter
      {
          private readonly IHostingEnvironment _env;
          public HttpGlobalExceptionFilter(IHostingEnvironment env)
          {
              this._env = env;
          }
          public ContentResult FailedMsg(string msg = null)
          {
              Result retResult = new Result(ResultStatus.Failed, msg);
              string json = JsonHelper.Serialize(retResult);
              return new ContentResult() { Content = json };
          }
          public void OnException(ExceptionContext filterContext)
          {
              if (filterContext.ExceptionHandled)
                  return;
              //执行过程出现未处理异常
              Exception ex = filterContext.Exception;
  #if DEBUG
              if (filterContext.HttpContext.Request.IsAjaxRequest())
              {
                  string msg = null;
                  if (ex is Ace.Exceptions.InvalidDataException)
                  {
                      msg = ex.Message;
                      filterContext.Result = this.FailedMsg(msg);
                      filterContext.ExceptionHandled = true;
                      return;
                  }
              }
              this.LogException(filterContext);
              return;
  #endif
              if (filterContext.HttpContext.Request.IsAjaxRequest())
              {
                  string msg = null;
                  if (ex is Ace.Exceptions.InvalidDataException)
                  {
                      msg = ex.Message;
                  }
                  else
                  {
                      this.LogException(filterContext);
                      msg = "服务器错误";
                  }
                  filterContext.Result = this.FailedMsg(msg);
                  filterContext.ExceptionHandled = true;
                  return;
              }
              else
              {
                  //对于非 ajax 请求
                  this.LogException(filterContext);
                  return;
              }
          }
          /// <summary>
          ///  将错误记录进日志
          /// </summary>
          /// <param name="filterContext"></param>
          void LogException(ExceptionContext filterContext)
          {
              ILoggerFactory loggerFactory = filterContext.HttpContext.RequestServices.GetService(typeof(ILoggerFactory)) as ILoggerFactory;
              ILogger logger = loggerFactory.CreateLogger(filterContext.ActionDescriptor.DisplayName);
              logger.LogError("Error: {0}, {1}", ReplaceParticular(filterContext.Exception.Message), ReplaceParticular(filterContext.Exception.StackTrace));
          }
          static string ReplaceParticular(string s)
          {
              if (string.IsNullOrEmpty(s))
                  return s;
              return s.Replace("\r", "#R#").Replace("\n", "#N#").Replace("|", "#VERTICAL#");
          }
      }
  结语
  咱做开发的,避免不了千篇一律的增删查改,所以,我们要想尽办法 write less,do more!这个项目只是一个入门学习的demo,并没什么特别的技术,但里面也凝聚了不少LZ这几年开发经验的结晶,希望能对一些猿友有用。大家有什么问题或建议可以留言讨论,也欢迎各位入群畅谈.NET复兴大计(群号见左上角)。最后,感谢大家阅读至此!
  该项目使用的是vs2017开发,数据库默认使用 SQLite,配置好 SQLite 的db文件即可运行。亦支持 SqlServer 和 MySql,在项目找到相应的数据库脚本,运行脚本创建相关的表后修改配置文件(configs/appsettings.json)内数据库连接配置即可。
  源码地址:https://github.com/shuxinqin/Ace
22/2<12
精选软件测试好文,快来阅读吧~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号