【问题标题】:Low level WCF exceptions as FaultException低级 WCF 异常为 FaultException
【发布时间】:2014-03-11 22:32:21
【问题描述】:

当我使用无效的操作请求调用我的 WCF 服务时,我遇到了一个异常。我需要将此异常作为 FaultException 发送。

我尝试了以下场景:-

  • 我使用了IErrorHandler,但ProvideFault 函数在此服务调用中没有命中(在其他情况下它工作正常)。

  • 我也使用消息检查器来处理异常。但AfterReceiveRequestBeforeSendReply 在此调用期间也没有命中。

    如何将所有类型的异常作为 FaultException 发送

服务请求

请求: POST /0710 HTTP/1.1

标题: 连接:关闭 内容长度:11 内容类型:application/soap+xml;字符集=utf-8; action="无效:S.O.A.P.:Action..." 主机:userpc:9001

正文:

发生异常(来自跟踪日志)

异常类型

System.ServiceModel.CommunicationException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

留言

无法识别的消息版本。

堆栈跟踪

System.ServiceModel.Channels.ReceivedMessage.ReadStartEnvelope(XmlDictionaryReader reader)
System.ServiceModel.Channels.BufferedMessage..ctor(IBufferedMessageData messageData, RecycledMessageState recycledMessageState, Boolean[] understoodHeaders, Boolean understoodHeadersModified)
System.ServiceModel.Channels.BufferedMessage..ctor(IBufferedMessageData messageData, RecycledMessageState recycledMessageState)
System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.ReadMessage(ArraySegment`1 buffer, BufferManager bufferManager, String contentType)
System.ServiceModel.Channels.HttpInput.DecodeBufferedMessage(ArraySegment`1 buffer, Stream inputStream)
System.ServiceModel.Channels.HttpInput.ParseMessageAsyncResult.ContinueReading(Int32 bytesRead)
System.ServiceModel.Channels.HttpInput.ParseMessageAsyncResult.DecodeBufferedMessageAsync()
System.ServiceModel.Channels.HttpInput.ParseMessageAsyncResult.BeginParse()
System.ServiceModel.Channels.HttpInput.ParseMessageAsyncResult..ctor(HttpRequestMessage httpRequestMessage, HttpInput httpInput, AsyncCallback callback, Object state)
System.ServiceModel.Channels.HttpInput.BeginParseIncomingMessage(HttpRequestMessage httpRequestMessage, AsyncCallback callback, Object state)
System.ServiceModel.Channels.HttpInput.BeginParseIncomingMessage(AsyncCallback callback, Object state)
System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginParseIncomingMessage(AsyncCallback asynCallback, Object state)
System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult..ctor(ReplyChannelAcceptor acceptor, Action dequeuedCallback, HttpPipeline pipeline, AsyncCallback callback, Object state)
System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action dequeuedCallback, AsyncCallback callback, Object state)
System.ServiceModel.Channels.HttpRequestContext.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action acceptorCallback, AsyncCallback callback, Object state)
System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync()
System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1..ctor(HttpRequestContext requestContext, Action acceptorCallback, HttpChannelListener`1 listener, AsyncCallback callback, Object state)
System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext context, Action acceptorCallback, AsyncCallback callback, Object state)
System.ServiceModel.Channels.SharedHttpTransportManager.EnqueueContext(IAsyncResult listenerContextResult)
System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult listenerContextResult)
System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result)
System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
System.Net.LazyAsyncResult.Complete(IntPtr userToken)
System.Net.ListenerAsyncResult.IOCompleted(ListenerAsyncResult asyncResult, UInt32 errorCode, UInt32 numBytes)
System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

您可以通过使用以下代码调用任何 WCF 服务来创建类似的情况

public static string HttpPost(string URI)
        {
            try
            {
                var r = (HttpWebRequest) WebRequest.Create(URI);
                r.Method = "POST";
                r.ContentType = @"application/soap+xml; charset=utf-8; action=""Invalid:S.O.A.P.:Action...""";                           
                var ws = new StreamWriter(r.GetRequestStream());
                ws.Write("<EmptyXml/>");
                ws.Close();
                var resp = (HttpWebResponse) r.GetResponse();
                var sr = new StreamReader(resp.GetResponseStream());
                return sr.ReadToEnd();
            }
            catch (FaultException ex)
            {
                //I need to catch low level exception as Fault exception
            }
            catch (CommunicationException ex)
            {

            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception : " + ex.Message);
            }
            return null;
        }

【问题讨论】:

  • 您在哪里托管您的服务? WAS、IIS、WinService、WPF/Winforms?如果是 WPF/Winforms,您可能忘记在服务行为或回调行为中使用 (UseSynchronizationContext=False)。
  • 我正在使用 WCF 服务库,它是从 WPF 应用程序启动的。我已经在使用该属性。我在服务中使用的属性是 [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single , ConfigurationName = "xxxxx", InstanceContextMode = InstanceContextMode.Single, Name = "xxxxx", Namespace = "xxxx.xx.xx", UseSynchronizationContext = false)]
  • 你在某处使用回调吗?
  • 我没有在这个服务中使用回调
  • 你能提供更多关于你正在尝试的代码吗?

标签: c# wcf


【解决方案1】:

由于您使用的是 HttpWebRequest,因此您永远不会通过 webrequest 收到错误异常。

要获取您的 faultexception,您必须从 webexception 响应中读取它。

=>

try
        {
            var r = (HttpWebRequest)WebRequest.Create("/S");
            r.Method = "POST";
            r.ContentType = @"text/json; charset=utf-8; action=""Invalid:S.O.A.P.:Action...""";
            var js = new JavaScriptSerializer();
            string postData = js.Serialize(new {something = "Hello World"});
            r.ContentLength = postData.Length;
            var ws = new StreamWriter(r.GetRequestStream());
            ws.Write(postData);
            ws.Close();
            var resp = (HttpWebResponse)r.GetResponse();

            var respStream = resp.GetResponseStream();
            if (respStream == null) return;
            var sr = new StreamReader(respStream);
            string s = sr.ReadToEnd();
        }
            catch (WebException ex)
            {
                using (var stream = ex.Response.GetResponseStream())
                {
                    if (stream == null) return;
                    using (var reader = new StreamReader(stream))
                    {
//At this point i'm just writing it to the console. However her you have your FaultException xml encoded.
                        Console.WriteLine(reader.ReadToEnd());
                    }
                }
            }

【讨论】:

  • 当你运行我的示例代码时,你会得到一个通信异常(检查服务跟踪日志)。我需要将其作为 FaultException 发送。我只开发 WCF 服务部分。客户端由第三方供应商开发。我们的服务应通过客户端开发人员提供的一组测试用例。其中一个测试用例提供我的问题。我们不能改变他们的测试场景。
  • 如前所述,您在 catch 块中遇到了错误异常,从那里开始您必须调查它的原因是什么以及它发生在哪里,这样您就可以抓住它服务端并生成您自己的故障异常。
  • 仅供参考:我真正的问题是如何处理无效的操作请求并将其作为来自 WCF 服务的 FaultException 发送。我不担心如何处理来自客户端的异常。我提供了该示例代码在服务器端创建类似的错误。
  • 据我所知,WCF 中的消息过滤器会为您处理无效消息。如果他们没有到达你的服务器实现,他们就不会让你的服务器崩溃。因此,据我所知,它已被处理。在客户端,他们还可以处理返回(如 catch 块中所示),所以我不确定您还想要什么?
猜你喜欢
  • 2011-08-29
  • 1970-01-01
  • 2011-08-08
  • 2013-01-13
  • 2013-06-08
  • 1970-01-01
  • 1970-01-01
  • 2013-06-26
相关资源
最近更新 更多