这个广为人知的答案对我帮助很大,但我想在我的中间件中传递HttpStatusCode以在运行时管理错误状态码。
根据这个链接,我得到了一些做同样事情的思路。所以我将Andrei的答案与此合并。所以我的最终代码如下:
1. 基类
public class ErrorDetails
{
public int StatusCode { get; set; }
public string Message { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
2. 自定义异常类类型
public class HttpStatusCodeException : Exception
{
public HttpStatusCode StatusCode { get; set; }
public string ContentType { get; set; } = @"text/plain";
public HttpStatusCodeException(HttpStatusCode statusCode)
{
this.StatusCode = statusCode;
}
public HttpStatusCodeException(HttpStatusCode statusCode, string message)
: base(message)
{
this.StatusCode = statusCode;
}
public HttpStatusCodeException(HttpStatusCode statusCode, Exception inner)
: this(statusCode, inner.ToString()) { }
public HttpStatusCodeException(HttpStatusCode statusCode, JObject errorObject)
: this(statusCode, errorObject.ToString())
{
this.ContentType = @"application/json";
}
}
3. 自定义异常中间件
public class CustomExceptionMiddleware
{
private readonly RequestDelegate next;
public CustomExceptionMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context )
{
try
{
await next(context);
}
catch (HttpStatusCodeException ex)
{
await HandleExceptionAsync(context, ex);
}
catch (Exception exceptionObj)
{
await HandleExceptionAsync(context, exceptionObj);
}
}
private Task HandleExceptionAsync(HttpContext context, HttpStatusCodeException exception)
{
string result = null;
context.Response.ContentType = "application/json";
if (exception is HttpStatusCodeException)
{
result = new ErrorDetails()
{
Message = exception.Message,
StatusCode = (int)exception.StatusCode
}.ToString();
context.Response.StatusCode = (int)exception.StatusCode;
}
else
{
result = new ErrorDetails()
{
Message = "Runtime Error",
StatusCode = (int)HttpStatusCode.BadRequest
}.ToString();
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
return context.Response.WriteAsync(result);
}
private Task HandleExceptionAsync(HttpContext context, Exception exception)
{
string result = new ErrorDetails()
{
Message = exception.Message,
StatusCode = (int)HttpStatusCode.InternalServerError
}.ToString();
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
return context.Response.WriteAsync(result);
}
}
4. 扩展方法
public static void ConfigureCustomExceptionMiddleware(this IApplicationBuilder app)
{
app.UseMiddleware<CustomExceptionMiddleware>();
}
5. 在startup.cs中配置方法
app.ConfigureCustomExceptionMiddleware();
app.UseMvc();
现在我的账户控制器中登录方法为:
try
{
IRepository<UserMaster> obj
= new Repository<UserMaster>(_objHeaderCapture, Constants.Tables.UserMaster);
var result = obj.Get()
.AsQueryable()
.Where(sb => sb.EmailId.ToLower() == objData.UserName.ToLower()
&& sb.Password == objData.Password.ToEncrypt()
&& sb.Status == (int)StatusType.Active)
.FirstOrDefault();
if (result != null)
return result;
else
throw new HttpStatusCodeException(HttpStatusCode.NotFound,
"Please check username or password");
}
catch (Exception ex)
{
throw ex;
}
如上所示,如果我没有找到用户,则会抛出HttpStatusCodeException异常,在其中我传递了HttpStatusCode.NotFound状态和自定义消息。
在中间件中:
catch (HttpStatusCodeException ex)
将调用blocked,该方法将控制权传递给
private Task HandleExceptionAsync(HttpContext context, HttpStatusCodeException exception) 方法
但是,如果在此之前发生运行时错误,该怎么办?为此,我使用了try catch块,它会抛出异常,并在catch(Exception exceptionObj)块中被捕获,然后将控制权传递给
Task HandleExceptionAsync(HttpContext context, Exception exception) 方法。
为了保持一致性,我使用了一个名为ErrorDetails的类。
UseExceptionHandler
中间件吗? - Pawel