Returning Error Details from AJAX-Enabled WCF Service

前端 未结 5 1256
鱼传尺愫
鱼传尺愫 2020-12-09 05:13

Short Version: Is there a/what is the suggested way to return error details to the client when an exception is thrown in an AJAX-Enabled WCF Service (aside

5条回答
  •  甜味超标
    2020-12-09 05:53

    EDIT: Updated the post with a proper custom json error handler

    The quick but non-preffered way.

    
    

    In Your service behavior will give you all the details you need.

    The Nice way

    All exceptions from the application are converted to an JsonError and serialized using a DataContractJsonSerializer. The Exception.Message is used directly. FaultExceptions provide the FaultCode and other exception are threated as unknown with faultcode -1.

    FaultException are sent with HTTP status code 400 and other exceptions are HTTP code 500 - internal server error. This not nescessary as the faultcode can be used to decide if it is and unknown error. It was however convenient in my app.

    The error handler

    internal class CustomErrorHandler : IErrorHandler
    {
        public bool HandleError(Exception error)
        {
            //Tell the system that we handle all errors here.
            return true;
        }
    
        public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
        {
            if (error is FaultException)
            {
                FaultException fe = (FaultException)error;
    
                //Detail for the returned value
                int faultCode = fe.Detail;
                string cause = fe.Message;
    
                //The json serializable object
                JsonError msErrObject = new JsonError { Message = cause, FaultCode = faultCode };
    
                //The fault to be returned
                fault = Message.CreateMessage(version, "", msErrObject, new DataContractJsonSerializer(msErrObject.GetType()));
    
                // tell WCF to use JSON encoding rather than default XML
                WebBodyFormatMessageProperty wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
    
                // Add the formatter to the fault
                fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);
    
                //Modify response
                HttpResponseMessageProperty rmp = new HttpResponseMessageProperty();
    
                // return custom error code, 400.
                rmp.StatusCode = System.Net.HttpStatusCode.BadRequest;
                rmp.StatusDescription = "Bad request";
    
                //Mark the jsonerror and json content
                rmp.Headers[HttpResponseHeader.ContentType] = "application/json";
                rmp.Headers["jsonerror"] = "true";
    
                //Add to fault
                fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);
            }
            else
            {
                //Arbitraty error
                JsonError msErrObject = new JsonError { Message = error.Message, FaultCode = -1};
    
                // create a fault message containing our FaultContract object
                fault = Message.CreateMessage(version, "", msErrObject, new DataContractJsonSerializer(msErrObject.GetType()));
    
                // tell WCF to use JSON encoding rather than default XML
                var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
                fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);
    
                //Modify response
                var rmp = new HttpResponseMessageProperty();
    
                rmp.Headers[HttpResponseHeader.ContentType] = "application/json";
                rmp.Headers["jsonerror"] = "true";
    
                //Internal server error with exception mesasage as status.
                rmp.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                rmp.StatusDescription = error.Message;
    
                fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);
            }
        }
    
        #endregion
    }
    

    Webbehaviour used to install the above error handler

    internal class AddErrorHandlerBehavior : WebHttpBehavior
    {
        protected override void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            base.AddServerErrorHandlers(endpoint, endpointDispatcher);
    
            //Remove all other error handlers
            endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear();
            //Add our own
            endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(new CustomErrorHandler());
        }
    }
    

    The json error data contract

    Specifies the json error format. Add properties here to change the error format.

    [DataContractFormat]
    public class JsonError
    {
        [DataMember]
        public string Message { get; set; }
    
        [DataMember]
        public int FaultCode { get; set; }
    }
    

    Using the error handler

    Self-hosted

    ServiceHost wsHost = new ServiceHost(new Webservice1(), new Uri("http://localhost/json")); 
    
    ServiceEndpoint wsEndpoint = wsHost.AddServiceEndpoint(typeof(IWebservice1), new WebHttpBinding(), string.Empty);
    
    wsEndpoint.Behaviors.Add(new AddErrorHandlerBehavior());
    

    App.config

      
        
          
        
     
    

提交回复
热议问题