简介

《Asp.Net Core3 + Vue3入坑教程》 此教程适合新手入门或者前后端分离尝试者。可以根据图文一步一步进操作编码也可以选择直接查看源码。每一篇文章都有对应的源码

目录

《Asp.Net Core3 + Vue3入坑教程》系列教程目录

Asp.Net Core后端项目

  1. 后端项目搭建与Swagger配置步骤
  2. 配置CROS策略解决跨域问题
  3. AutoMapper & Restful API & DI
  4. EF Core & Postgresql
  5. .Net Core 3升级成 .Net 5 & JWT
  6. (本文)异常处理与UserFriendlyException

Vue3 前端项目

  1. 使用vue-cli创建vue项目
  2. (暂未发表敬请期待...)使用Ant Design of Vue编写页面 & vue-router 初试
  3. (暂未发表敬请期待...)将Antd导航菜单与vue-router绑定
  4. (暂未发表敬请期待...) 保存用户登入状态vuex初试

本文简介

本文为《Asp.Net Core3 + Vue3入坑教程》系列教程的后端第六篇 - 异常处理与UserFriendlyException上文已经为Simple项目升级了SDK并且应用了JWT,本文继续为Simple项目增加异常处理与使用友好异常(UserFriendlyException)。

为什么需要使用友好异常的方式进行开发呢?

在很多情况下,我们在一个方法中往往包含着校验参数与返回结果两个动作,这时候我们的返回结果就需要考虑用对象来包裹校验结果与返回结果。 如果我们使用友好异常,默认方法能顺利通过校验并返回正确的结果,如果校验出现失败的情况则将失败原因通过友好异常的方式返回给调用者,可以让方法的返回内容不需要考虑校验的结果,代码更简洁明了!

用户友好参照了开源项目ABP项目 https://docs.abp.io/zh-Hans/abp/latest/Exception-Handling

异常处理与UserFriendlyException

第一步先增加测试代码,修改SqlCommanderRepo.cs

代码调整如下:

using Simple_Asp.Net_Core.Models;
using Simple_Asp.Net_Core.ServiceProvider;
using System;
using System.Collections.Generic;
using System.Linq; namespace Simple_Asp.Net_Core.Data
{
public class SqlCommanderRepo : ICommanderRepo
{
private readonly CommanderContext _context; public SqlCommanderRepo(CommanderContext context)
{
_context = context;
} public void CreateCommand(Command cmd)
{
if (cmd == null)
{
throw new ArgumentNullException(nameof(cmd));
} _context.Commands.Add(cmd);
} public void DeleteCommand(Command cmd)
{
if (cmd == null)
{
throw new ArgumentNullException(nameof(cmd));
}
_context.Commands.Remove(cmd);
} public IEnumerable<Command> GetAllCommands()
{
return _context.Commands.ToList();
} public Command GetCommandById(int id)
{
if (id == 0)
throw new Exception("id不能为0!"); return _context.Commands.First(p => p.Id == id);
} public bool SaveChanges()
{
return (_context.SaveChanges() >= 0);
} public void UpdateCommand(Command cmd)
{
//Nothing
}
}
}

运行项目,调用接口api/commands/{id}接口,当请求参数id设置为0时,后端会抛出异常信息。

当前的异常信息将程序内部内容都暴露出来,并且返回信息也不清晰,调用者难以处理。

接着在ServiceProvider文件夹下增加自定义异常类UserFriendlyException.cs

代码如下:

using System;

namespace Simple_Asp.Net_Core.ServiceProvider
{
public class UserFriendlyException : Exception
{
public UserFriendlyException(string message) : base(message)
{
} public UserFriendlyException(string message, Exception inner) : base(message, inner)
{
}
}
}

在ServiceProvider文件夹下增加类ExceptionHandler.cs,用来处理异常

在捕捉到程序异常的时候需要写入日志方便问题追踪

代码如下:

using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System.Text;
using System.Threading.Tasks; namespace Simple_Asp.Net_Core.ServiceProvider
{
public class ExceptionHandler
{
public static Task ErrorEvent(HttpContext context)
{
var feature = context.Features.Get<IExceptionHandlerFeature>();
var error = feature?.Error; if (error.GetType() == typeof(UserFriendlyException))
{
SetResponse(context);
var content = GetApiResponse(error.Message); return context.Response.WriteAsync(JsonConvert.SerializeObject(content), Encoding.UTF8);
}
else
{
// 写入日志
// error.Message
// error.StackTrace SetResponse(context);
var content = GetApiResponse("程序发生错误,请联系客服!");
return context.Response.WriteAsync(JsonConvert.SerializeObject(content), Encoding.UTF8);
}
} /// <summary>
/// 解决异常消息返回跨域问题
/// </summary>
private static void SetResponse(HttpContext context)
{
context.Response.Clear();
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
context.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET");
context.Response.ContentType = "application/json";
} /// <summary>
/// 响应Response
/// </summary>
private static ErrorResponse GetApiResponse(string message)
{
return new ErrorResponse() { success = false, message = message };
} private class ErrorResponse
{
public bool success { get; set; }
public bool Success { get { return success; } }
public string message { get; set; }
public string Message { get { return message; } }
}
}
}

调整Startup.cs,增加异常捕捉

代码如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Serialization;
using Simple_Asp.Net_Core.Data;
using Simple_Asp.Net_Core.ServiceProvider;
using System; namespace Simple_Asp.Net_Core
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddJWT(); services.AddDbContext<CommanderContext>(options =>
options.UseNpgsql("Host=localhost;Database=postgres;Username=postgres;Password=123456")); services.AddCORS();
services.AddMvc();
services.AddSwagger(); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); services.AddScoped<ICommanderRepo, SqlCommanderRepo>(); services.AddControllers().AddNewtonsoftJson(s =>
{
s.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiHelp V1");
});
}
app.UseExceptionHandler(builder => builder.Run(async context => await ExceptionHandler.ErrorEvent(context)));
app.UseCors("CorsTest");
app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute());
}
}
}

启动项目,调用api/commands/{id}接口,可以看出后端的接口发生了异常,此时的异常比较清晰。

最后我们将SqlCommanderRepo.cs里的异常改为友好异常

再次修改SqlCommanderRepo.cs

代码调整如下:

using Simple_Asp.Net_Core.Models;
using Simple_Asp.Net_Core.ServiceProvider;
using System;
using System.Collections.Generic;
using System.Linq; namespace Simple_Asp.Net_Core.Data
{
public class SqlCommanderRepo : ICommanderRepo
{
private readonly CommanderContext _context; public SqlCommanderRepo(CommanderContext context)
{
_context = context;
} public void CreateCommand(Command cmd)
{
if (cmd == null)
{
throw new ArgumentNullException(nameof(cmd));
} _context.Commands.Add(cmd);
} public void DeleteCommand(Command cmd)
{
if (cmd == null)
{
throw new ArgumentNullException(nameof(cmd));
}
_context.Commands.Remove(cmd);
} public IEnumerable<Command> GetAllCommands()
{
return _context.Commands.ToList();
} public Command GetCommandById(int id)
{
if (id == 0)
throw new Exception("id不能为0!"); return _context.Commands.First(p => p.Id == id);
} public bool SaveChanges()
{
return (_context.SaveChanges() >= 0);
} public void UpdateCommand(Command cmd)
{
//Nothing
}
}
}

最后启动项目,调用api/commands/{id}接口,这时候我们可以得到友好的提示!

总结

本文为Simple项目增加异常处理与使用友好异常(UserFriendlyException),在捕捉到程序异常的时候需要写入日志方便问题追踪!

目前Simple项目还未使用日志组件,后续会补上

异常捕捉为了能够将异常内容进行收集,并且能以统一的方式返回给客户端,保证服务器的安全、帮助我们追踪问题并且客户端的体验也能有所保证。

异常捕捉结合友好异常的方式能够为我们减少代码量,并且让代码更直观明了,推荐大家一试!

GitHub源码

注意:源码调试过程中如果出现xml文件路径错误,需要参照第一章(后端项目搭建与Swagger配置步骤)Swagger配置“配置XML 文档文件”步骤,取消勾选然后再选中 ,将XML路径设置成与你的电脑路径匹配!

https://github.com/Impartsoft/Simple_Asp.Net_Core/tree/master/Simple_Asp.Net_Core 6.Exception Handling %26 UserFriendlyException

参考资料

ABP开源项目异常处理 https://docs.abp.io/zh-Hans/abp/latest/Exception-Handling

《Asp.Net Core3 + Vue3入坑教程》 - 6.异常处理与UserFriendlyException的更多相关文章

  1. 《Asp.Net Core3 + Vue3入坑教程》-Net Core项目搭建与Swagger配置步骤

    简介 <Asp.Net Core3 + Vue3入坑教程> 此教程仅适合新手入门或者前后端分离尝试者.可以根据图文一步一步进操作编码也可以选择直接查看源码.每一篇文章都有对应的源码 教程后 ...

  2. 《Asp.Net Core3 + Vue3入坑教程》 - Vue 1.使用vue-cli创建vue项目

    简介 <Asp.Net Core3 + Vue3入坑教程> 此教程适合新手入门或者前后端分离尝试者.可以根据图文一步一步进操作编码也可以选择直接查看源码.每一篇文章都有对应的源码 目录 & ...

  3. Vue入坑教程(二)——项目结构详情介绍

    之前已经介绍了关于Vue的脚手架vue-cli的安装,以及一些文件目录介绍.具体可以查看<vue 入坑教程(一)--搭建vue-cli脚手架> 下面简单说一下具体的文件介绍 (一) pac ...

  4. Docker 入坑教程笔记

    Docker 入坑教程笔记 视频网址B站:点这里 查询命令 man docker 简单启动和退出 docker run --name [容器名] -i -t ubuntu /bin/bash 交互启动 ...

  5. Vue2.0史上最全入坑教程(下)—— 实战案例

    书接上文 前言:经过前两节的学习,我们已经可以创建一个vue工程了.下面我们将一起来学习制作一个简单的实战案例. 说明:默认我们已经用vue-cli(vue脚手架或称前端自动化构建工具)创建好项目了 ...

  6. Vue入坑教程(一)——搭建vue-cli脚手架

    1. Vue简介 详细内容可以参考官网Vue.js 1)兼容性 Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性.但它支持所有兼容 ECMA ...

  7. Vue2.0史上最全入坑教程(上)—— 搭建Vue脚手架(vue-cli)

    ps: 想了解更多vue相关知识请点击VUE学习目录汇总 Vue作为前端三大框架之一截至到目前在github上以收获44,873颗星,足以说明其以悄然成为主流.16年10月Vue发布了2.x版本,经过 ...

  8. vue入坑教程(一)

    1.脚手架搭配webpack的安装 (1)需要检查自己的电脑有没有安装node和npm 如果没有安装可以参考官网,以及安装的步骤 官方中文网地址:http://nodejs.cn/ (2)下载webp ...

  9. vue入坑教程(三)vue父子组件之间互相调用方法以及互相传递数据

    1.父组件调用子组件的方法 父组件: <template> <div> <button v-on:click="clickParent">点击& ...

随机推荐

  1. log查看工具log2console

    log查看工具log2console介绍:https://www.cnblogs.com/TianFang/archive/2013/03/27/2985296.html Log2Console日志监 ...

  2. 被收费绘图工具 PUA 了怎么办?来看看这个老实工具吧

    本文非常适合 Electron 入门选手,墙裂推荐! 本文作者:HelloGitHub-蔡文心 大家好!这里是 HelloGitHub 推出的<讲解开源项目>系列,今天给大家带来的一款基于 ...

  3. 洛谷P1462-通往奥格瑞玛的道路-二分+最短路

    洛谷P1462-通往奥格瑞玛的道路 题目描述 在艾泽拉斯,有\(n\)个城市.编号为\(1,2,3,...,n\). 城市之间有\(m\)条双向的公路,连接着两个城市,从某个城市到另一个城市,会遭到联 ...

  4. 力扣992.K个不同整数的子数组-C语言实现

    题目 原题链接 给定一个正整数数组 A,如果 A 的某个子数组中不同整数的个数恰好为 K,则称 A 的这个连续.不一定独立的子数组为好子数组. (例如,[1,2,3,1,2] 中有 3 个不同的整数: ...

  5. Navicat 使用 SSH 通道

    使用 Navicat for MySQL 通过跳板机登录 Mysql 时(使用 SSH 通道) 报错如下: SSH : Expected key exchange group packet from ...

  6. 牛年 dotnet云原生技术趋势

    首先祝大家:新年快乐,牛年大吉,牛年发发发! 2020年的春节,新冠疫情使得全球业务停滞不前,那时候,没有人知道会发生什么,因此会议被取消,合同被搁置,项目被推迟,一切似乎都停止了.但是我们却见证了I ...

  7. linux多线程模拟银行家算法

    题外话: 这应该是最近有点难度的作业了,起码比之前的理发师,读写,哲学家问题要难. 但是做好程序的结构,自顶向下,就还是不难的. 银行家算法简介:                 代码: init() ...

  8. 强网杯 2019]随便注(堆叠注入,Prepare、execute、deallocate)

    然后就是今天学的新东西了,堆叠注入. 1';show databases; # 1';show tables; # 发现两个表1919810931114514.words 依次查询两张表的字段 1'; ...

  9. u-boot 移植 --->5、友善之臂Tiny210底板王网卡驱动移植

    网卡芯片的工作原理 DM9000AE具有以下主要性能: ①48管脚的LQFP封装,管脚少体积小: ②支持8/16位数据总线: ③适用于10Base-T和100Base-T,10/100M自适应,适应不 ...

  10. Promise thenable All In One

    Promise thenable All In One Promise thenable 是指一个函数或一个对象的里面定义了一个 then 方法 Promises/A+ https://promise ...