Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
313 views
in Technique[技术] by (71.8m points)

.net - How to make custom WCF error handler return JSON response with non-OK http code?

I'm implementing a RESTful web service using WCF and the WebHttpBinding. Currently I'm working on the error handling logic, implementing a custom error handler (IErrorHandler); the aim is to have it catch any uncaught exceptions thrown by operations and then return a JSON error object (including say an error code and error message - e.g. { "errorCode": 123, "errorMessage": "bla" }) back to the browser user along with an an HTTP code such as BadRequest, InteralServerError or whatever (anything other than 'OK' really). Here is the code I am using inside the ProvideFault method of my error handler:

fault = Message.CreateMessage(version, "", errorObject, new DataContractJsonSerializer(typeof(ErrorMessage)));
var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);
var rmp = new HttpResponseMessageProperty();
rmp.StatusCode = System.Net.HttpStatusCode.InternalServerError;
rmp.Headers.Add(HttpRequestHeader.ContentType, "application/json");
fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);

--> This returns with Content-Type: application/json, however the status code is 'OK' instead of 'InternalServerError'.

fault = Message.CreateMessage(version, "", errorObject, new DataContractJsonSerializer(typeof(ErrorMessage)));
var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);
var rmp = new HttpResponseMessageProperty();
rmp.StatusCode = System.Net.HttpStatusCode.InternalServerError;
//rmp.Headers.Add(HttpRequestHeader.ContentType, "application/json");
fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);

--> This returns with the correct status code, however the content-type is now XML.

fault = Message.CreateMessage(version, "", errorObject, new DataContractJsonSerializer(typeof(ErrorMessage)));
var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);

var response = WebOperationContext.Current.OutgoingResponse;
response.ContentType = "application/json";
response.StatusCode = HttpStatusCode.InternalServerError;

--> This returns with the correct status code and the correct content-type! The problem is that the http body now has the text 'Failed to load source for: http://localhost:7000/bla..' instead of the actual JSON data..

Any ideas? I'm considering using the last approach and just sticking the JSON in the HTTP StatusMessage header field instead of in the body, but this doesn't seem quite as nice?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Actually, this works for me.

Here's my ErrorMessage class:

    [DataContract]
    public class ErrorMessage
    {
        public ErrorMessage(Exception error)
        {
            Message = error.Message;
            StackTrace = error.StackTrace;
            Exception = error.GetType().Name;
        }

        [DataMember(Name="stacktrace")]
        public string StackTrace { get; set; }
        [DataMember(Name = "message")]
        public string Message { get; set; }
        [DataMember(Name = "exception-name")]
        public string Exception { get; set; }
    }

Combined with the last snippet above:

        fault = Message.CreateMessage(version, "", new ErrorMessage(error), new DataContractJsonSerializer(typeof(ErrorMessage)));
        var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
        fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);

        var response = WebOperationContext.Current.OutgoingResponse;
        response.ContentType = "application/json";
        response.StatusCode = HttpStatusCode.InternalServerError; 

This gives me proper errors as json. Thanks. :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...