简介

《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. 洛谷 P2895 [USACO08FEB]Meteor Shower S (BFS)

    题意:你刚开始位于坐标轴的\((0,0)\)点,一共有\(m\)颗流星砸向地面,每颗流星在\(t\)时砸到\((x,y)\)点,其四周上下左右也均有波及,你每秒可以向上下左右移动一个单位,问你是否可以 ...

  2. 【史上最全】Hadoop 核心 - HDFS 分布式文件系统详解(上万字建议收藏)

    1. HDFS概述 Hadoop 分布式系统框架中,首要的基础功能就是文件系统,在 Hadoop 中使用 FileSystem 这个抽象类来表示我们的文件系统,这个抽象类下面有很多子实现类,究竟使用哪 ...

  3. HTTP笔记4--HTTP 状态码

    状态码作用.组成 HTTP 状态码负责表示客户端 HTTP 请求的返回结果.标记服务器端的处理是否正常.通知出现的错误等工作.状态码的职责是当客户端向服务器端发送请求时,描述返回的请求结果. 状态码如 ...

  4. OpenStack Train版-9.安装neutron网络服务(计算节点)

    在计算节点安装neutron网络服务(computel01计算节点192.168.0.20)安装组件 yum install openstack-neutron-linuxbridge ebtable ...

  5. 3.安装可视化工具kibana

    作者 微信:tangy8080 电子邮箱:914661180@qq.com 更新时间:2019-06-19 10:10:42 星期三 欢迎您订阅和分享我的订阅号,订阅号内会不定期分享一些我自己学习过程 ...

  6. String的20个方法

    String的20个方法 面试题 1.new和不new的区别 String A="OK"; String B="OK";//会去常量池查找有没有"Ok ...

  7. codeforces 1013B 【思维+并查集建边】

    题目链接:戳这里 转自:参考博客 题意:给一个n*m的矩阵,放入q个点,这q个点之间的关系是,若已知这样三个点(x1,y1),(x2,y1),(x1,y2),可以在(x2,y2)处生成一个新的点,对于 ...

  8. spring-cloud-netflix-hystrix-turbine

    Hystrix-dashboard是一款针对Hystrix进行实时监控的工具,通过Hystrix Dashboard我们可以在直观地看到各Hystrix Command的请求响应时间, 请求成功率等数 ...

  9. redis跳表

    redis使用跳表作为有序集合的底层实现之一,下面来看下跳表的结构 一.跳表的结构

  10. React render twice bug

    React render twice bug React bug constructor render twice bug update render twice bug StrictMode htt ...