简介

《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. Pollard_rho算法进行质因素分解

    Pollard_rho算法进行质因素分解要依赖于Miller_Rabbin算法判断大素数,没有学过的可以看一下,也可以当成模板来用 讲一下Pollard_rho算法思想: 求n的质因子的基本过程是,先 ...

  2. Windows环境下Node.js环境搭建

    1.Node.js下载与安装 https://nodejs.org/zh-cn/download/ Windows现在windows安装包(.msi),现在后手动安装,安装目录无要求,选项默认即可 2 ...

  3. 过滤器,拦截器,aop区别与使用场景

    1. 什么是过滤器 过滤器,顾名思义就是起到过滤筛选作用的一种事物,只不过相较于现实生活中的过滤器,这里的过滤器过滤的对象是客户端访问的web资源,也可以理解为一种预处理手段,对资源进行拦截后,将其中 ...

  4. 浅谈Webpack模块打包工具三

    Source Map 生产代码与开发代码完全不同,如果需要调试应用的话会非常的麻烦,错误信息无法定位,Soutce Map就会逆向得到源代码, 须在打包之后的代码文件的末尾位置例如添加//# sour ...

  5. Atlas 分表功能

    目录 分表原因 分表方式 Atlas 分表 分表思路 配置 Atlas 创建原表 创建分表 数据测试 分表原因 1.数据过多,访问缓慢 2.创建索引时重新排序,创建缓慢,并且占用大量的磁盘空间 分表方 ...

  6. codeforces 1045I Palindrome Pairs 【stl+构造】

    题目:戳这里 题意:给1e5个字符串,问有多少对字符串组合,满足最多只有一种字符有奇数个. 解题思路:每种情况用map存一下就行了.感觉这题自己的代码思路比较清晰,所以写个题解记录一下 附ac代码: ...

  7. Dapr 交通控制示例

    Dapr 已在塔架就位 将发射新一代微服务 牛年 dotnet云原生技术趋势 Dapr是如何简化微服务的开发和部署 前面几篇文章都是从大的方面给大家分享Dapr 能帮助我们解决什么问题,微软从开源到1 ...

  8. μC/OS-III---I笔记4---软件定时器

    软件定时器是在硬件定时器的基础上开发的,通过将一个硬件定时器进行分频及管理就可以的到多个软件定时器.他和时间管理共同组成了系统的时间管理大部分的内容.系统一开始的系统初始化函数OSInit函数内调用了 ...

  9. JS Object Deep Copy & 深拷贝 & 浅拷贝

    JS Object Deep Copy & 深拷贝 & 浅拷贝 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Refe ...

  10. after upgrade macOS Catalina bugs

    after upgrade macOS Catalina bugs 升级了macOS catalina后,碰到的 bugs? macOS 10.15.5 https://www.apple.com/m ...