首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >WCF FaultException误差

WCF FaultException误差
EN

Stack Overflow用户
提问于 2011-04-06 16:43:29
回答 2查看 5K关注 0票数 1

我是WCF的新手,我有问题将WCF服务的异常抛给客户端。我正在使用代码示例,这些代码是我从网上复制的。(我正在使用VS2010 .NET Framework4.0)

我创建了一个ErrorHandler,其中ProvideFault断层方法如下所示:

代码语言:javascript
运行
复制
public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message msg)
    {
        FaultException<Exception> faultException = new FaultException<Exception>(error, error.Message, new FaultCode("Testing."));
        MessageFault messageFault = faultException.CreateMessageFault();
        msg = Message.CreateMessage(version, messageFault, Constants.FaultAction);
    }

故障合同如下:

代码语言:javascript
运行
复制
[FaultContract(typeof(Exception), Action=Constants.FaultAction)]

客户端测试代码如下所示:

代码语言:javascript
运行
复制
        private void button1_Click(object sender, EventArgs e)
    {
        HistorianAccessServiceClient cli = new HistorianAccessServiceClient();
        Tables.Batch bt = new Tables.Batch();
        try
        {
            bt = cli.GetBatch(3241);
        }
        catch (FaultException<Exception> ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

我注意到,如果ProvideFault方法的错误参数包含一个内部异常,那么在客户端(!?)上抛出一个System.ServiceModel.CommunicationException,内部异常是System.Net.WebException,该异常的内部异常是System.IO.IOException,该异常的内部例外是System.Net.Sockets.SocketException (错误代码10054)?!

(不幸的是,我安装了一个瑞典操作系统,这意味着调试器的消息是瑞典语。)

异常消息(google翻译)如下所示:

接收对http://localhost:7070/Historian.WebAccess/HistorianAccessService的HTTP响应时发生错误。可能是服务端点绑定不使用http协议。这也可能是由于服务器中断了http请求的上下文(可能是因为服务被终止了)。您可以在服务器日志中找到更多信息。

如果我抛出一个没有的异常--一个内部异常--该异常将由客户端处理,完全可以!

我的配置文件看起来如下(服务):

代码语言:javascript
运行
复制
 <system.serviceModel>
<bindings />
<client />
<services>
  <service name="Historian.WebAccess.HistorianAccessService">
    <host>
      <baseAddresses>
        <!--<add baseAddress="http://localhost:8732/Design_Time_Addresses/Historian.WebAccess/HistorianAccessService/"/>-->
        <add baseAddress="http://localhost:7070/Historian.WebAccess/"/>
      </baseAddresses>
    </host>
    <!-- Service Endpoints -->
    <!-- Unless fully qualified, address is relative to base address supplied above -->
    <!--<endpoint address="HistorianAccessService" binding="wsHttpBinding" contract="Historian.WebAccess.IHistorianAccessService">-->
    <endpoint address="HistorianAccessService" binding="wsHttpBinding" contract="Historian.WebAccess.IHistorianAccessService">
      <!-- 
          Upon deployment, the following identity element should be removed or replaced to reflect the 
          identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
          automatically.
      -->
      <identity>
        <dns value="localhost"/>
      </identity>
    </endpoint>
    <!-- Metadata Endpoints -->
    <!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
    <!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior>
      <!-- To avoid disclosing metadata information, 
      set the value below to false and remove the metadata endpoint above before deployment -->
      <serviceMetadata httpGetEnabled="false"/>
      <serviceThrottling maxConcurrentCalls="16" maxConcurrentInstances="2147483646" maxConcurrentSessions="10"/>

      <dataContractSerializer maxItemsInObjectGraph="2147483646"/>
      <!-- To receive exception details in faults for debugging purposes, 
      set the value below to true.  Set to false before deployment 
      to avoid disclosing exception information -->
      <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
  </serviceBehaviors>
</behaviors>

配置文件(客户端):

代码语言:javascript
运行
复制
<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="WSHttpBinding_IHistorianAccessService" closeTimeout="00:10:00"
                openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
                bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                maxBufferPoolSize="104857600" maxReceivedMessageSize="104857600"
                messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                allowCookies="false">
                <readerQuotas maxDepth="104857600" maxStringContentLength="104857600" maxArrayLength="104857600"
                    maxBytesPerRead="104857600" maxNameTableCharCount="104857600" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00"
                    enabled="false" />
                <security mode="Message">
                    <transport clientCredentialType="Windows" proxyCredentialType="None"
                        realm="" />
                    <message clientCredentialType="Windows" negotiateServiceCredential="true"
                        algorithmSuite="Default" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <client>                   
      <endpoint address="http://localhost:7070/Historian.WebAccess/HistorianAccessService"
            binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IHistorianAccessService"
            contract="HistorianAccessHost.IHistorianAccessService"
            name="WSHttpBinding_IHistorianAccessService">
            <identity>
                <dns value="localhost" />
            </identity>
        </endpoint>
    </client>

  <behaviors>
    <endpointBehaviors>
      <behavior>
        <dataContractSerializer maxItemsInObjectGraph="2147483646"/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>

有谁认识到这一现象及其解决办法吗?!

如果我能得到所有的帮助,我会很高兴的!

EN

回答 2

Stack Overflow用户

发布于 2011-04-06 16:47:04

解决方案是不尝试将.NET异常对象传回客户端。这将您限制为运行.NET的客户端。

实际上,它仅限于运行客户端,这些客户端知道可能抛出的所有异常。如果您在服务器上添加了一个新的MyNewException并将其抛回给客户端,该怎么办?客户端需要包含该异常的程序集才能将其反序列化。

票数 2
EN

Stack Overflow用户

发布于 2011-04-06 16:59:44

我觉得你太喜欢你想做的事了。如果您只是试图抛出FaultException,只需执行新的FaultException(错误)。如果您要抛出一个自定义错误类型,您必须做更多的工作,但是这些消息都不是必需的。下面是我发现的一个VB示例:

代码语言:javascript
运行
复制
 Public Function DoSomething() As Data() 
        Try
            DoSomething()
        Catch ex As Exception
          Throw New FaultException(ex.Message)
        End Try
    End Function

如果您要抛出一个自定义类型的错误(比如PermissionDenied之类的),您需要为此创建一个对象,这需要更多的工作。

你也要小心你回来的地方。向客户端发送堆栈跟踪之类的详细信息可以帮助攻击者入侵系统,而且对标准的最终用户没有多大用处。您应该将其记录在服务器上。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5569966

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档