1

我正在使用新的 ASP.Net 4.5 Web Api 编写 Api。我的 Api 响应与fourSquare 的 Api Response Messages
非常相似。 我的 api 应该总是响应这样的消息:

{
    Meta:
    {
        Code: "401"
        ErrorDetails: "Not Authorized!"
    }
    Response: "The Api Response Object or Text'
}

意思是我应该总是返回 Http 状态码:200 OK
任何错误指示都将位于“Meta”标签中。因此,我为所有 Json 请求实现了一个 MediaFormatter。看起来像这样:

 public class MyApiResponseFormatter : JsonMediaTypeFormatter
{
    public MyApiResponseFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
    }

    public override bool CanReadType(Type type)
    {
        return true;
    }

    public override bool CanWriteType(Type type)
    {
        return true;
    }

    public override Task WriteToStreamAsync(Type type, object value, System.IO.Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext)
    {
        HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.OK;
        return Task.Factory.StartNew(() =>
        {
            ApiResponse apiResponse = CreateApiResponse(type, value);

            using (StreamWriter requestWriter = new StreamWriter(writeStream))
            {
                requestWriter.Write(JsonConvert.SerializeObject(apiResponse, new JsonSerializerSettings
                {
                    NullValueHandling = NullValueHandling.Ignore
                }));
            }
        });
    }

    private ApiResponse CreateApiResponse(Type type, object value)
    {
        #region Handle Errors
        Type exceptionType = null;
        ErrorDetails errorDetails = null;
        HttpStatusCode statusCode = HttpStatusCode.OK;
        if (type == typeof(HttpError))
        {
            exceptionType = Type.GetType(((System.Web.Http.HttpError)value)["ExceptionType"].ToString());
            errorDetails = new ErrorDetails()
            {
                Message = ((System.Web.Http.HttpError)value)["ExceptionMessage"].ToString(),
                StackStace = ((System.Web.Http.HttpError)value)["StackTrace"].ToString()
            };

            // get the status code
            if (exceptionType == typeof(UnauthorizedAccessException))
            {
                statusCode = HttpStatusCode.Unauthorized;
            }
            else
            {
                statusCode = HttpStatusCode.BadRequest;
            };
        }
        #endregion

        ApiResponse apiResponse = new ApiResponse()
        {
            Meta = new MetaData()
            {
                Code = (int)statusCode,
                ErrorType = exceptionType,
                ErrorDetails = errorDetails
            },

            Notifications = null,
            Response = type == typeof(HttpError) ? null : value
        };
        return apiResponse;
    }

    public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, System.Net.Http.HttpContent content, IFormatterLogger formatterLogger)
    {
        return base.ReadFromStreamAsync(type, readStream, content, formatterLogger);
    }
}

一切似乎都很好,除了如果引发异常,响应上的状态代码不是 200(它是 500 - 内部服务器错误)
所以我添加了这行代码,看起来像一个 hack:
HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.OK;

在这个解决方案中感觉有些不对劲。任何有经验的关于如何实现这样的 Api 的 web api 见解将不胜感激。谢谢。

4

0 回答 0