WCF FaultException error - PullRequest
       1

WCF FaultException error

1 голос
/ 06 апреля 2011

Я новичок в WCF, и у меня возникают проблемы с выдачей исключений из моей службы WCF клиенту.Я использую примеры кода, которые я скопировал из Интернета.(Я использую VS2010 .NET Framework 4.0)

Я создал ErrorHandler, где ProvideFault-метод выглядит следующим образом:

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);
    }

Контракт ошибки выглядит следующим образом:

[FaultContract(typeof(Exception), Action=Constants.FaultAction)]

Тестовый код на стороне клиента выглядит следующим образом:

        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 на http://localhost:7070/Historian.WebAccess/HistorianAccessService. Возможно, привязка конечной точки службы не использует протокол http.Это также может быть связано с тем, что сервер прервал запрос http (возможно, из-за того, что служба прервана).Вы можете найти больше информации в журналах сервера.

Если я сгенерирую исключение без внутреннего исключения, то исключение обрабатывается клиентом совершенно нормально!?!?!

Мои файлы конфигурации выглядят так (Служба):

 <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>

Файл конфигурации (Клиент):

<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>

Кто-нибудь там распознает это?феномен и его решение?!

Буду признателен за всю помощь, которую смогу получить!

Ответы [ 2 ]

2 голосов
/ 06 апреля 2011

Решение состоит в том, чтобы не пытаться передавать объекты исключений .NET обратно клиенту. Это ограничивает вас клиентами под управлением .NET.

Фактически, он ограничивает вас запущенными клиентами, которые знают обо всех исключениях, которые вы можете выдавать. Что если вы добавите новый MyNewException на сервер и вернете его клиенту? Клиенту необходимо иметь сборку, содержащую это исключение, чтобы его вообще можно было десериализовать.

0 голосов
/ 06 апреля 2011

Я думаю, вы слишком увлечены тем, что пытаетесь сделать. Если вы просто пытаетесь вызвать FaultException, просто создайте новое FaultException (ошибка). Вам нужно проделать немного больше работы, если вы генерируете пользовательский тип ошибки, но ничего из этого сообщения не требуется. Вот пример VB, который я нашел:

 Public Function DoSomething() As Data() 
        Try
            DoSomething()
        Catch ex As Exception
          Throw New FaultException(ex.Message)
        End Try
    End Function

Если вы генерируете нестандартный тип ошибки (например, PermissionDenied или тому подобное), вам нужно создать объект для этого, что немного больше работы.

Вы также хотите быть осторожными с тем, что вы возвращаете сюда. Отправка клиенту множества деталей, таких как следы стека, может помочь злоумышленнику попытаться проникнуть в систему, и он не слишком полезен для вашего обычного конечного пользователя. Вы должны зарегистрировать это на сервере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...