目前版本是Asp.Net Core v1.1,这个版本的感觉对Http请求中的错误处理方便不是很完善。

没有HttpException异常类,不能在任何的地方自由的抛出对应的异常状态。

一、默认的异常处理配置

1.默认配置在StartUp文件的Configure中注册错误处理

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug(); if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
}

特别说明:

1.env.IsDevelopment()  用于判断当前运行环境是否是测试环境

2.app.UseDeveloperExceptionPage(); 如果是测试环境则启用开发者异常页面

开发者异常页面

当在Web处理管道放生了一个位置异常时,开发者异常页面会显示有用的调试信息。页面包含几个选项卡显示Stack、Query、Cookie、Header异常信息。

3.app.UseExceptionHandler("/Home/Error"); 在正式运行环境中输出异常的内容信息。

4.默认的异常处理对于404没有处理,如果是404的地址则返回空内容。

5.业务逻辑404的抛出

使用状态视图

public IActionResult Test2()
{
//手动抛出404 页面
return StatusCode(, "你要访问的页面不存在");
}

或者修改相应上下文的状态码

@{
//自定义抛出404异常
this.Context.Response.StatusCode = ;
}
<h1>404状态的页面</h1>

二、错误处理扩展,使用委托

1.

//此处的404页面,只能用于处理路由中不匹配的404页面
//如果是程序逻辑中的404不予以处理
//并且对于程序中Exception 也不做处理,直接相应500,内容为空
RequestDelegate handler = async context =>
{
var resp = context.Response;
if (resp.StatusCode == )
{
await resp.WriteAsync($"当前是404页面,暂时没有获取到异常内容");
}
};
app.UseStatusCodePages(builder =>
{
builder.Run(handler);
});

2.

//使用StatusCodePagesMiddleware 指定状态对应的显示页面
Func<StatusCodeContext, Task> handler = async context =>
{
var resp = context.HttpContext.Response;
if (resp.StatusCode == )
{
//需要 using Microsoft.AspNetCore.Http;
await resp.WriteAsync($"当前是404页面,暂时没有获取到异常内容", Encoding.UTF8);
}
else if (resp.StatusCode == )
{
await resp.WriteAsync($"当前是500页面,暂时没有获取到异常内容", Encoding.UTF8);
}
};
app.UseStatusCodePages(handler);

三、错误处理扩展,使用自定义扩展类

Asp.Net Core三种呈现错误也的方式都可以扩展

1.DeveloperExceptionPageMiddleware中间件的扩展可以自定义开发者异常页面,当前略过

2.ExceptionHandlerMiddleware中间件,可以自定义扩展异常处理

示例,处理异常并制定异常的响应页面

public class ErrorHandlingMiddleware
{
private RequestDelegate _next;
private ExceptionHandlerOptions _options; public ErrorHandlingMiddleware(RequestDelegate next, IOptions<ExceptionHandlerOptions> options)
{
_next = next;
_options = options.Value;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch
{
//虽然此处指定500,但是出现异常,再次执行异常页面则响应的是200
context.Response.StatusCode = ;
context.Response.Clear();
if (_options.ExceptionHandlingPath.HasValue)
{
context.Request.Path = _options.ExceptionHandlingPath;
}
RequestDelegate handler = _options.ExceptionHandler ?? _next;
await handler(context);
}
}
}

使用扩展方法为IApplicationBuilder扩展内容

public static class ErrorHandlingExtensions
{
public static IApplicationBuilder UseErrorHandling(this IApplicationBuilder builder, ExceptionHandlerOptions options)
{
return builder.UseMiddleware<ErrorHandlingMiddleware>(Options.Create(options));
}
}

在 Configure中注册当前错误处理

//使用自定义异常处理
app.UseErrorHandling(new ExceptionHandlerOptions()
{
//注意此处的路径不能使用~符号
ExceptionHandlingPath = "/Home/Error"
});

3.StatusCodePagesMiddleware中间件可以根据正常的相应内容(没有抛出异常的情况下) 扩展状态相应页面

public interface IStatusCodePagesFeature
{
bool Enabled { get; set; }
} public class StatusCodePagesFeature : IStatusCodePagesFeature
{
public bool Enabled { get; set; } = true;
}
public class StatusCodePagesMiddleware
{
private RequestDelegate _next;
private StatusCodePagesOptions _options;
public StatusCodePagesMiddleware(RequestDelegate next,
IOptions<StatusCodePagesOptions> options)
{
_next = next;
_options = options.Value;
}
public async Task Invoke(HttpContext context)
{
//可以用于阻止异常处理
StatusCodePagesFeature feature = new StatusCodePagesFeature();
context.Features.Set<IStatusCodePagesFeature>(feature); await _next(context);
HttpResponse response = context.Response;
//对于响应的状态编码,返回内容
//if ((response.StatusCode >= 400 && response.StatusCode <= 599) && !response.ContentLength.HasValue && string.IsNullOrEmpty(response.ContentType))
if (response.StatusCode >= && response.StatusCode <= && feature.Enabled)
{
//触发 默认处理
//await _options.HandleAsync(new StatusCodeContext(context, _options, _next)); //对于非异常的页面,执行Clear抛出异常
//response.Clear(); //response.Body.Seek(0, SeekOrigin.Begin); await response.WriteAsync($"当前HttpCode={response.StatusCode}");
}
} }

使用扩展方法注册中间件

public static class ErrorHandlingExtensions
{//注册3中处理方式
public static IApplicationBuilder UseStatusCodeHandling(this IApplicationBuilder builder)
{
return builder.UseMiddleware<StatusCodePagesMiddleware>();
}
public static IApplicationBuilder UseStatusCodeHandling(this IApplicationBuilder app, StatusCodePagesOptions options)
{
return app.UseMiddleware<StatusCodePagesMiddleware>(Options.Create(options));
}
public static IApplicationBuilder UseStatusCodeHandling(this IApplicationBuilder app, Func<StatusCodeContext, Task> handler)
{
return app.UseStatusCodePages(new StatusCodePagesOptions
{
HandleAsync = handler
});
}
}

在Configure中注册使用

Func<StatusCodeContext, Task> handler = async context =>
{
var resp = context.HttpContext.Response;
//在以下的相应数据时,会清空原页面的相应内容
if (resp.StatusCode == )
{
//需要 using Microsoft.AspNetCore.Http;
await resp.WriteAsync($"当前是404页面,暂时没有获取到异常内容", Encoding.UTF8);
}
else if (resp.StatusCode == )
{
await resp.WriteAsync($"当前是500页面,暂时没有获取到异常内容", Encoding.UTF8);
}
};
app.UseStatusCodeHandling(handler);

4.可以在扩展中综合使用处理,如下示例

public class ErrorHandlingMiddleware
{
private readonly RequestDelegate next;
private ExceptionHandlerOptions _options;
public ErrorHandlingMiddleware(RequestDelegate next, IOptions<ExceptionHandlerOptions> options)
{
this.next = next;
this._options = options.Value;
}
public async Task Invoke(HttpContext context)
{
try
{
await next(context);
}
catch (Exception ex)
{
var statusCode = context.Response.StatusCode;
if (ex is ArgumentException)
{
statusCode = ;
}
await HandleExceptionAsync(context, statusCode, ex.Message);
}
finally
{
var statusCode = context.Response.StatusCode;
var msg = "";
if (statusCode == )
{
msg = "未授权";
}
else if (statusCode == )
{
//msg = "未找到服务";
//如果是404 返回404页面
if (_options.ExceptionHandlingPath.HasValue)
{
context.Request.Path = _options.ExceptionHandlingPath;
}
RequestDelegate handler = _options.ExceptionHandler ?? next;
await handler(context);
}
else if (statusCode == )
{
msg = "请求错误";
}
else if (statusCode != )
{
msg = "未知错误";
}
if (!string.IsNullOrWhiteSpace(msg))
{
await HandleExceptionAsync(context, statusCode, msg);
}
}
}
private static Task HandleExceptionAsync(HttpContext context, int statusCode, string msg)
{
var data = new { code = statusCode.ToString(), is_success = false, msg = msg };
var result = JsonConvert.SerializeObject(new { data = data });
try
{
//特别说明ContentType属性在 HttpResponse初始化完成之后就不能修改了
//如果试图修改则抛出异常
//异常内容:Headers are read-only, response has already started.
//context.Response.ContentType = "application/json;charset=utf-8"; //特别说明对于准备输出的Response,执行Clear()清空抛出异常
//The response cannot be cleared, it has already started sending.
context.Response.Clear(); //判断输出流是否已经开始
//context.Response.HasStarted
}
catch (Exception ex)
{
//throw ex;
}
//清楚已经完成的相应内容 return context.Response.WriteAsync(result);
}
}

原文参考:http://www.cnblogs.com/artech/p/error-handling-in-asp-net-core-1.html

更多:

Restful API 的设计规范(转)

.Net Core配置文件读取整理

EF Core 1.0 和 SQLServer 2008 分页的问题

Asp.Net Core异常处理整理的更多相关文章

  1. ASP.NET Core 异常处理与日志记录

    1. ASP.NET Core 异常处理与日志记录 1.1. 异常处理 1.1.1. 异常产生的原因及处理 1.1.2. ASP.NET Core中启动开发人员异常页面 1.2. 日志记录 1.2.1 ...

  2. Asp.Net Core 视图整理(一)

    一.部分视图的使用 注:1.目前在Asp.Net Core2.0中对于部分视图的支持主要使用 Html.Partial()/Html.PartialAsync(); Html.RenderPartia ...

  3. Asp.Net Core异常处理

    本文将介绍在ASP.Net Core中处理异常的几种方法 1使用开发人员异常页面(The developer exception page) 2配置HTTP错误代码页 Configuring stat ...

  4. 深入探究ASP.NET Core异常处理中间件

    前言     全局异常处理是我们编程过程中不可或缺的重要环节.有了全局异常处理机制给我们带来了很多便捷,首先我们不用满屏幕处理程序可能出现的异常,其次我们可以对异常进行统一的处理,比如收集异常信息或者 ...

  5. Asp.Net Core简单整理

    1.Asp.NetCore 中文入门文档 http://www.cnblogs.com/dotNETCoreSG/p/aspnetcore-index.html

  6. ASP.NET Core ---异常处理

    一.局部异常处理: 在Action里面catch 二.全局异常处理: 1.默认的异常处理配置: 默认配置在StartUp文件的Configure中注册错误处理,显示开发者错误页面: public vo ...

  7. Asp.net core 框架整理

    https://github.com/thangchung/awesome-dotnet-core#cms

  8. Asp.Net Core 404处理

    在使用Asp.Net Core Mvc时 404处理整理如下 一.自带404状态处理 1.控制器视图子弹404视图 NotFoundResult,NotFoundObjectResult // // ...

  9. Asp.Net Core 文件上传处理

    本文主要介绍后台接收处理 1.在使用控制器接收 : [HttpPost] : public IActionResult UploadFiles(IList<IFormFile> files ...

随机推荐

  1. 如何用Python写一个贪吃蛇AI

    前言 这两天在网上看到一张让人涨姿势的图片,图片中展示的是贪吃蛇游戏, 估计大部分人都玩过.但如果仅仅是贪吃蛇游戏,那么它就没有什么让人涨姿势的地方了. 问题的关键在于,图片中的贪吃蛇真的很贪吃XD, ...

  2. OCM_第十天课程:Section5—》数据仓库

    注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...

  3. Jmeter接口测试实例图文示例

    以getObjectByCode接口为例,用jmeter2.13来进行接口测试. 测试前准备: 测试工具及版本:jmeter 2.13 r1665067(须包含__MD5函数) 示例接口:8.1根据单 ...

  4. java.lang.Math

    四舍五人 System.out.println(Math.round(1.8f));//输出位2 static(静态)方法random() //: object/Shifting.java packa ...

  5. bzoj营业额统计

    这个也是板子题吧,很水,求前驱后继即可 /* 插入,求前驱和后继 */ #include<iostream> #include<cstring> #include<cst ...

  6. PyCharm 新建文件时默认添加作者时间等

    将内容添加到Python Script 右侧的文本框中: 路径: File → Setting → Editor → File and Code Templates → Python Script # ...

  7. 《剑指offer》-斐波那契数列

    大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项. n<=39 这么直接的问fibonacci,显然是迭代计算.递归的问题在于重复计算,而迭代则避免了这一点:递归是自 ...

  8. zjoi 2017 树状数组

    题解: 感觉相比仙人掌简单了很多啊.. 首先会发现那个其实就是后缀和 然后其实就是判断一下两个位置的元素想不想等 然后l=1是要特判的 之后一个易错的地方就是去维护每个数是0/1的概率 因为这样概率是 ...

  9. python全栈开发day24-__new__、__del__、item系列、异常处理

    一.昨日内容回顾 1.反射 用字符串类型的名字,操作命名空间的变量. 反射使用场景:明显的简化代码,能拿到的变量名本来就是一个字符串类型的时候, 用户输入的,文件读入的,网上传输的 2.__call_ ...

  10. ZOJ - 3471

    壮压水一水,刚开始脑残了非要开两维dp... #include<cstdio> #include<cstring> #include<algorithm> #def ...