在Web API中返回自定义错误对象 [英] Return custom error objects in Web API

查看:199
本文介绍了在Web API中返回自定义错误对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Web API我正在使用MVC 4 Web API框架。如果有异常,我正在抛出一个新的HttpResponseException。即:

  if(!Int32.TryParse(id,out userId))
throw new HttpResponseException(Request.CreateErrorResponse (HttpStatusCode.BadRequest,Invalid id));

这个客户端的对象返回一个简单的 {message: 无效的id}



我想通过返回一个更详细的对象来进一步控制对异常的响应。像

  {
status: - 1,
substatus:3,
message:找不到用户
}

关于这样做?是序列化我的错误对象并将其设置在响应消息中的最好方式吗?



我还研究了一个codeModelStateDictionary ,并提出了这个黑客 ,但它仍然不是一个干净的输出:

  var msd = new ModelStateDictionary(); 
msd.AddModelError(status,-1);
msd.AddModelError(substatus,3);
msd.AddModelError(message,invalid stuff);
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest,msd));

编辑

看起来像一个自定义 HttpError 是我需要的。这似乎是诀窍,现在让它从我的业务层可扩展...

  var error = new HttpError(无效的东西){{status,-1},{substatus,3}}; 
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest,error));


解决方案

我认为这将会诀窍:



为业务层创建自定义异常类:

  public class MyException:异常
{
public ResponseStatus Status {get;私人集合}
public ResponseSubStatus SubStatus {get;私人集合}
public new string Message {get;私人集合

public MyException()
{}

public MyException(ResponseStatus status,ResponseSubStatus subStatus,string message)
{
状态=状态;
SubStatus = subStatus;
Message = message;
}
}

创建一个静态方法来生成一个 HttpError 来自 MyException 的实例。我在这里使用反射,所以我可以添加属性到 MyException ,并始终将它们返回w / o更新创建

  public static HttpError Create< T>(MyException异常)其中T:Exception 
{
var properties = exception.GetType()。GetProperties(BindingFlags.Instance
| BindingFlags.Public
| BindingFlags.DeclaredOnly);
var error = new HttpError();
foreach(属性中的var propertyInfo)
{
error.Add(propertyInfo.Name,propertyInfo.GetValue(exception,null));
}
返回错误;
}

我现在有一个常规异常处理程序的自定义属性。所有类型 MyException 的异常将在这里处理:

  public class ExceptionHandlingAttribute :ExceptionFilterAttribute 
{
public override void OnException(HttpActionExecutedContext context)
{
var statusCode = HttpStatusCode.InternalServerError;

if(context.Exception is MyException)
{
statusCode = HttpStatusCode.BadRequest;
throw new HttpResponseException(context.Request.CreateErrorResponse(statusCode,HttpErrorHelper.Create(context.Exception)));
}

if(context.Exception is AuthenticationException)
statusCode = HttpStatusCode.Forbidden;

throw new HttpResponseException(context.Request.CreateErrorResponse(statusCode,context.Exception.Message));
}
}

我会再玩一点,更新,因为我在这个计划中找到洞。


I have a web API I'm working on using the MVC 4 Web API framework. If there is an exception, I'm currently throwing a new HttpResponseException. ie:

if (!Int32.TryParse(id, out userId))
    throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Invalid id")); 

This returns an object to the client that is simply {"message":"Invalid id"}

I would like to gain further control over this response to exceptions by returning a more detailed object. Something like

{
 "status":-1,
 "substatus":3,
 "message":"Could not find user"
 }

How would I go about doing this? Is the best way to serialize my error object and set it in the response message?

I've also looked into the ModelStateDictionary a bit and have come up with this bit of a "hack", but it's still not a clean output:

var msd = new ModelStateDictionary();
msd.AddModelError("status", "-1");
msd.AddModelError("substatus", "3");
msd.AddModelError("message", "invalid stuff");
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, msd));

edit
looks like a custom HttpError is what I need. This seems to do the trick, now to make it extensible from my business layer...

var error = new HttpError("invalid stuff") {{"status", -1}, {"substatus", 3}};
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, error));

解决方案

I think this will do the trick:

Create a custom exception class for the business layer:

 public class MyException: Exception
 {
    public ResponseStatus Status { get; private set; }
    public ResponseSubStatus SubStatus { get; private set; }
    public new string Message { get; private set; }

    public MyException()
    {}

    public MyException(ResponseStatus status, ResponseSubStatus subStatus, string message)
    {
        Status = status;
        SubStatus = subStatus;
        Message = message;
    }
 }

Create a static method to generate a HttpError from an instance of MyException. I'm using reflection here so I can add properties to MyException and always have them returned w/o updating Create:

    public static HttpError Create<T>(MyException exception) where T:Exception
    {
        var properties = exception.GetType().GetProperties(BindingFlags.Instance 
                                                         | BindingFlags.Public 
                                                         | BindingFlags.DeclaredOnly);
        var error = new HttpError();
        foreach (var propertyInfo in properties)
        {
            error.Add(propertyInfo.Name, propertyInfo.GetValue(exception, null));
        }
        return error;
    }

I currently have a custom attribute for a general exception handler. All exceptions of type MyException will be handled here:

public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        var statusCode = HttpStatusCode.InternalServerError;

        if (context.Exception is MyException)
        {
            statusCode = HttpStatusCode.BadRequest;
            throw new HttpResponseException(context.Request.CreateErrorResponse(statusCode, HttpErrorHelper.Create(context.Exception)));
        }

        if (context.Exception is AuthenticationException)
            statusCode = HttpStatusCode.Forbidden;

        throw new HttpResponseException(context.Request.CreateErrorResponse(statusCode, context.Exception.Message));
    }
}

I'll play around with this a bit more and update as I find holes in this plan.

这篇关于在Web API中返回自定义错误对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆