添加自定义Exception类
using System;
using System.Net;
namespace Application.Errors
{
public class RestException:Exception
{
public RestException(HttpStatusCode code,object errors=null)
{
Code = code;
Errors = errors;
}
public HttpStatusCode Code { get; }
public object Errors { get; }
}
}
添加中间件
中间件接受一个委托,并且传递下一个委托给下一个中间件
创建中间件处理异常
using System;
using System.Net;
using System.Threading.Tasks;
using Application.Errors;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace API.Middleware
{
public class ErrorHandlingMiddleware
{
private readonly ILogger<ErrorHandlingMiddleware> _logger;
private readonly RequestDelegate _next;
public ErrorHandlingMiddleware(RequestDelegate next,ILogger<ErrorHandlingMiddleware> logger)
{
_logger = logger;
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch(Exception ex)
{
await HandleExceptionAsync(context, ex, _logger);
}
}
private async Task HandleExceptionAsync(HttpContext context, Exception ex, ILogger<ErrorHandlingMiddleware> logger)
{
object errors = null;
switch(ex)
{
case RestException re:
logger.LogError(ex, "Rest Error");
errors = re.Errors;
context.Response.StatusCode = (int)re.Code;
break;
case Exception e:
logger.LogError(ex, "Server Error");
errors = string.IsNullOrWhiteSpace(e.Message) ? "Error" : e.Message;
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
break;
}
context.Response.ContentType = "application/json";
if(errors!=null)
{
var result = JsonConvert.SerializeObject(new
{
errors
});
await context.Response.WriteAsync(result);
}
}
}
}
在Startup类中使用中间件
app.UseMiddleware<ErrorHandlingMiddleware>();
请求响应管道中的每一个委托都在前一个委托后执行,所以应当尽量早的调用异常处理的委托
在Delete动作中抛出RestException
if (activity == null)
throw new RestException(HttpStatusCode.NotFound, new { Activity = "Not Found" });
使用postMan测试
可以得到404的返回结果和返回的json对象
客户端异常处理
使用ReactRouter
作路由导航
在 /layout/ 中添加NotFound.tsx组件作为404页面
import React from 'react';
import { Segment, Button, Header, Icon } from 'semantic-ui-react';
import { Link } from 'react-router-dom';
const NotFound = () => {
return (
<Segment placeholder>
<Header icon>
<Icon name='search' />
Oops - we've looked everywhere but couldn't find this.
</Header>
<Segment.Inline>
<Button as={Link} to='/activities' primary>
Return to Activities page
</Button>
</Segment.Inline>
</Segment>
);
};
export default NotFound;
使用axios来捕获服务端的异常
axios.interceptors.response.use(undefined, error=> {
const { status, data, config } = error.response;
if (status === 404) {
history.push('/notfound')
}
});
```>
这里的**history** 通过 Router组件进行注入
export const history = createBrowserHistory();
ReactDOM.render(
<Router history={history}>
<ScrollToTop>
<App />
</ScrollToTop>
</Router>
, document.getElementById('root'));
接下来添加处理其他类型异常的逻辑
添加react-toastify
npm install react-toastify
[使用文档](https://www.npmjs.com/package/react-toastify#usage)
在index页面添加CSS,在App页面中添加ToastContainer
<ToastContainer position='bottom-right' />
添加其他错误的处理逻辑
if (error.message === "Network Error" && !error.response) {
toast.error("NetWork Error");
}
const { status,data,config } = error.response;
if (status === 404) {
history.push('/notfound')
}
if (status === 400 && config.method === 'get' && data.errors.hasOwnProperty('id')) {
history.push('/notfound')
}
if (status === 500) {
toast.error('Server error,check your terminal!')
}