.net core异常中间件的使用

 更新时间:2021年06月16日 09:33:29   作者:不问前世  
本文主要简单介绍一下异常中间件的使用,学习.net core的同学可以了解下本文

正文

if (env.IsDevelopment())
{
	app.UseDeveloperExceptionPage();
}

这样写入中间件哈,那么在env环境下就会去执行UseDeveloperExceptionPage。

public static IApplicationBuilder UseDeveloperExceptionPage(this IApplicationBuilder app)
{
	if (app == null)
	{
		throw new ArgumentNullException(nameof(app));
	}

	return app.UseMiddleware<DeveloperExceptionPageMiddleware>();
}

那么我们应该去看DeveloperExceptionPageMiddleware中间件哈。

那么这里介绍它是如何能够捕获其他中间件的异常的哈。

里面的invoke:

其实它的操作是很简单的,直接在外面套了try catch。

里面的异常处理怎么处理的可以直接去看DeveloperExceptionPageMiddleware 中间件,里面的操作也比较简单处理。

测试:

[HttpGet]
public int GetService([FromServices]ISelfService selfService)
{
	throw new System.Exception("错误");
	return 1;
}

结果:

因为上面说了,这个是dev环境下,那么生产环境不能直接给用户看到错误信息。

正式环境:

app.UseExceptionHandler("/error");

将错误转移到/error 处理。具体UseExceptionHandler细节篇里面介绍,有许多可以借鉴的地方。

[ApiController]
[Route("[controller]")]
public class ErrorController : Controller
{
	public ILogger<ErrorController> _logger;
	public ErrorController(ILogger<ErrorController> logger)
	{
		this._logger = logger;
	}

	public IActionResult Index()
	{
		var exceptionHandlerPathFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();

		var ex = exceptionHandlerPathFeature?.Error;

		var knownException = ex as IKnownException;

		if (knownException == null)
		{
			_logger.LogError(ex, ex.Message);
			knownException = KnownException.Unknow;
		}
		else
		{
			knownException = KnownException.FromKnowException(knowException);
		}

		return View(knownException);
	}
}

视图:

<html>
<head>

</head>
<body>
<div>
    错误码: @Model.ErrorCode
</div>
<div>
    错误信息: @Model.Message
</div>
</body>
</html>

IKnownException:

public interface IKnownException
{
	public string Message { get; }

	public int ErrorCode { get; }

	public object[] ErrorData { get; }
}

KnownException:

public class KnownException : IKnownException
{
	public string Message
	{
		get; private set;
	}

	public int ErrorCode
	{
		get; private set;
	}

	public object[] ErrorData
	{
		get;
		private set;
	}

	public readonly static IKnownException Unknow = new KnownException { Message = "未知错误", ErrorCode = 99 };

	public static IKnownException FromKnowException(IKnownException Exception)
	{
		return new KnownException{Message = Exception.Message, ErrorCode = Exception.ErrorCode, ErrorData = Exception.ErrorData};
	}
}

测试1:

[HttpGet]
public int GetService([FromServices]ISelfService selfService)
{
	throw new System.Exception("错误");
	return 1;
}

这种属于未知异常,结果:

现在弄一个支付异常:

public class PayErrorException : Exception, IKnownException
{
	public PayErrorException(string message, int errorCode, params object[] errorData): base(message)
	{
		this.ErrorCode = errorCode;
		this.ErrorData = errorData;
	}

	public int ErrorCode { get;private set; }

	public object[] ErrorData { get;private set; }
}

测试2:

[HttpGet]
public int GetService([FromServices]ISelfService selfService)
{

	throw new PayErrorException("支付错误",405,null);
	return 1;
}

将异常处理放入到中间件分支中。

app.UseExceptionHandler(errApp =>
{
	errApp.Run(async context =>
	{
		var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
		IKnownException knownException = exceptionHandlerPathFeature.Error as IKnownException;
		if (knownException == null)
		{
			var logger = context.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
			logger.LogError(exceptionHandlerPathFeature.Error, exceptionHandlerPathFeature.Error.Message);
			knownException = KnownException.Unknown;
			context.Response.StatusCode = StatusCodes.Status500InternalServerError;
		}
		else
		{
			knownException = KnownException.FromKnownException(knownException);
			context.Response.StatusCode = StatusCodes.Status200OK;
		}
		var jsonOptions = context.RequestServices.GetService<IOptions<JsonOptions>>();
		context.Response.ContentType = "application/json; charset=utf-8";
		await context.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(knownException, jsonOptions.Value.JsonSerializerOptions));
	});
});

效果一样就不演示了。如果是已知异常错误码应该为200,一个是500异常是系统无法处理,系统错误,但是已知错误是属于系统正常处理。另一个是监控系统,认为报500错误,是会持续放出系统警告。

还有一种局部异常,只在mvc中生效,而不是全局生效:

public class MyExceptionFilter : IExceptionFilter
{
	public void OnException(ExceptionContext context)
	{
		IKnownException knownException = context.Exception as IKnownException;
		if (knownException == null)
		{
			var logger = context.HttpContext.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
			logger.LogError(context.Exception, context.Exception.Message);
			knownException = KnownException.Unknown;
			context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
		}
		else
		{
			knownException = KnownException.FromKnownException(knownException);
			context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
		}
		context.Result = new JsonResult(knownException)
		{
			ContentType = "application/json; charset=utf-8"
		};
	}
}

在mvc 中注册:

services.AddMvc(mvcOptions =>
{
	mvcOptions.Filters.Add<MyExceptionFilter>();
}).AddJsonOptions(jsonOptions =>
{
	jsonOptions.JsonSerializerOptions.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
});

最后介绍一种,只作用于某个控制器,或者action:

public class MyExceptionFilterAttribute : ExceptionFilterAttribute
{
	public override void OnException(ExceptionContext context)
	{
		IKnownException knownException = context.Exception as IKnownException;
		if (knownException == null)
		{
			var logger = context.HttpContext.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
			logger.LogError(context.Exception, context.Exception.Message);
			knownException = KnownException.Unknown;
			context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
		}
		else
		{
			knownException = KnownException.FromKnownException(knownException);
			context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
		}
		context.Result = new JsonResult(knownException)
		{
			ContentType = "application/json; charset=utf-8"
		};
	}
}

查看一下ExceptionFilterAttribute头部:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public abstract class ExceptionFilterAttribute : Attribute, IAsyncExceptionFilter, IExceptionFilter, IOrderedFilter

上面标志了可以放于类上也可以放于方法上。所以可以放至在controller上,也可以action上,看需求了。


以上就是.net core异常中间件的使用的详细内容,更多关于.net core异常中间件的资料请关注脚本之家其它相关文章!

相关文章

  • asp.net页面SqlCacheDependency缓存实例

    asp.net页面SqlCacheDependency缓存实例

    这篇文章主要介绍了asp.net页面SqlCacheDependency缓存实例,以一个完整实例来展现asp.net中缓存技术的使用方法,需要的朋友可以参考下
    2014-08-08
  • asp.net Silverlight中的模式窗体

    asp.net Silverlight中的模式窗体

    现在Web开发技术中流行着模式窗体,这种不用跳转页面又能够满足与用户进行数据交互的手段确实不错,那我今天也谈谈Silverlight中的模式窗体吧。
    2009-11-11
  • 使用Visual Studio 2017写静态库

    使用Visual Studio 2017写静态库

    这篇文章主要为大家详细介绍了Visual Studio2017写静态库的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • .NET 6中为record类型自定义Equals方法

    .NET 6中为record类型自定义Equals方法

    这篇文章主要介绍了.NET 6中为record类型自定义Equals方法,record类型,这是一种新引用类型,而不是类或结构。record与类不同,区别在于record类型使用基于值的相等性,下文小编将介绍更多详细资料,需要的朋友可以参考一下
    2022-03-03
  • mvc file控件无刷新异步上传操作源码

    mvc file控件无刷新异步上传操作源码

    这篇文章主要为大家分享了mvc file控件无刷新异步上传操作源码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • Asp.net移除Server,X-Powered-By和X-AspNet-Version头

    Asp.net移除Server,X-Powered-By和X-AspNet-Version头

    这篇文章主要介绍了Asp.net移除Server, X-Powered-By, 和X-AspNet-Version头,移除X-AspNet-Version很简单,只需要在Web.config中增加相应配置节,感兴趣的朋友一起看看吧
    2024-02-02
  • ASP.NET 获取客户端IP方法

    ASP.NET 获取客户端IP方法

    本文主要介绍了ASP.NET获取客户端IP方法,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • 关于有些Asp.net项目发布后出现网址乱码的解决方法

    关于有些Asp.net项目发布后出现网址乱码的解决方法

    最近在部署一个网站,net2.0开发的,但是遇到一个很奇怪的问题。
    2011-07-07
  • ASP.NET MVC5网站开发显示文章列表(九)

    ASP.NET MVC5网站开发显示文章列表(九)

    显示文章列表分两块,管理员可以显示全部文章列表,一般用户只显示自己的文章列表。文章列表的显示采用easyui-datagrid,后台需要与之对应的action返回json类型数据,感兴趣的小伙伴们可以参考一下
    2015-09-09
  • ASP.NET 图片防盗链的实现原理分析

    ASP.NET 图片防盗链的实现原理分析

    防盗链的原理,从图片请求的URL地址上判断是否是我们自己网站上的域名,如果不是,恭喜,你的图片已经被盗链了!
    2010-01-01

最新评论