当前位置:  开发笔记 > 编程语言 > 正文

当HTTP状态代码为401 Unauthorized时,IErrorHandler返回错误的消息体

如何解决《当HTTP状态代码为401Unauthorized时,IErrorHandler返回错误的消息体》经验,为你挑选了0个好方法。

我已经实现了IErrorHandler来处理在我的restful WCF服务的构造函数中抛出的授权异常.捕获常规异常时,我的自定义类型按预期返回,但ContentType标头不正确.

HTTP/1.1 500 Internal Server Error
Content-Type: application/xml;
...

{"ErrorMessage":"Error!"}

但是,当错误处理程序尝试返回401 Unauthorized http状态代码时,消息正文将被覆盖为默认类型,但ContentType标头应该是它应该的样本.

HTTP/1.1 401 Unauthorized
Content-Type: application/json; 
...

{"Message":"Authentication failed.","StackTrace":null,"ExceptionType":"System.InvalidOperationException"}

显然这里有些不对劲,但我不确定是什么.

如何实现IErrorHandler,使其在json中使用正确的标头返回我的自定义类型?

BaseDataResponseContract对象:

[Serializable]
[DataContract( Name = "BaseDataResponseContract" )]
public class BaseDataResponseContract
{
    [DataMember]
    public string ErrorMessage { get; set; }

} // end

这是我想要返回的对象.我的应用程序中的所有其他对象都继承自此对象.当抛出异常时,我们真正关心的是http状态代码和错误消息.

IErrorHandler实现(为简洁起见,未显示日志记录):

namespace WebServices.BehaviorsAndInspectors
{
    public class ErrorHandler : IErrorHandler
    {
        public bool HandleError(Exception error)
        {
            return true;

        } // end

        public void ProvideFault(Exception ex, MessageVersion version, ref Message fault)
        {
            // Create a new instance of the object I would like to return with a default message
            var baseDataResponseContract = new BaseDataResponseContract { ErrorMessage = "Error!" };

            // Get the outgoing response portion of the current context 
            var response = WebOperationContext.Current.OutgoingResponse;

            // Set the http status code 
            response.StatusCode = HttpStatusCode.InternalServerError;

            // If the exception is a specific type change the default settings
            if (ex.GetType() == typeof(UserNotFoundException))
            {
                 baseDataResponseContract.ErrorMessage = "Invalid Username!";
                 response.StatusCode = HttpStatusCode.Unauthorized;
            }    

            // Create the fault message that is returned (note the ref parameter)
            fault = Message.CreateMessage(version, "", baseDataResponseContract, new DataContractJsonSerializer(typeof(BaseDataResponseContract)));

            // Tell WCF to use JSON encoding rather than default XML
            var webBodyFormatMessageProperty = new WebBodyFormatMessageProperty(WebContentFormat.Json);
            fault.Properties.Add(WebBodyFormatMessageProperty.Name, webBodyFormatMessageProperty);

            // Add ContentType header that specifies we are using json 
            var httpResponseMessageProperty = new HttpResponseMessageProperty();
            httpResponseMessageProperty.Headers[HttpResponseHeader.ContentType] = "application/json";
            fault.Properties.Add(HttpResponseMessageProperty.Name, httpResponseMessageProperty);

        } // end

    } // end class

} // end namespace

IServiceBehavior实施:

namespace WebServices.BehaviorsAndInspectors
{
    public class ErrorHandlerExtensionBehavior : BehaviorExtensionElement, IServiceBehavior
    {
        public override Type BehaviorType
        {
            get { return GetType(); }
        }

        protected override object CreateBehavior()
        {
            return this;
        }

        private IErrorHandler GetInstance()
        {
            return new ErrorHandler();
        }

        void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters) { } // end

        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            var errorHandlerInstance = GetInstance();

            foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(errorHandlerInstance);
            }
        }

        void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } // end

    } // end class

} // end namespace

Web.Config中:



          
      
        
      
    

          
              
        
              
          
    

              
              
        
          
          
          
             
          
    

    ....

最后,我在使用WebFaultException时看到了类似的行为.我的想法是,这是一些深埋的.Net恶作剧的结果.我选择实现IErrorHandler,以便我可以捕获任何其他可能无法处理的异常.

参考:

https://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ierrorhandler(v=vs.100).aspx

http://www.brainthud.com/cards/5218/25441/which-four-behavior-interfaces-exist-for-interacting-with-a-service-or-client-description-what-methods-do-they-落实和

其他例子:

IErrorHandler似乎没有处理我在WCF中的错误..任何想法?

如何使用非OK http代码使自定义WCF错误处理程序返回JSON响应?

如何为HttpClient请求设置Content-Type标头?

推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有