Невозможно перехватить исключение FaultException, созданное службой WCF в клиентском приложении SilverLight.

Я вызываю метод службы WCF из своего приложения Silverlight. Служба Wcf возвращает исключение сбоя при сбое. Я могу выбросить исключение ошибки из моей службы WCF. Но оно не поступает в мое приложение Silverlight (.xaml.cs). Вместо этого я получаю исключение «Исключение связи не было обработано пользователем, удаленный сервер вернул ошибку: NotFound» в файле References.cs (автоматически созданный файл)

Я вызываю метод службы WCF в моем файле .Xaml.cs, как показано ниже.

      private void btnExecuteQuery_Click(object sender, RoutedEventArgs e)
        {
         try
           {
            objService.GetDataTableDataAsync(_DATABASENAME, strQuery);
           objService.GetDataTableDataCompleted += new    EventHandler<GetDataTableDataCompletedEventArgs>(objService_GetDataTableDataCompleted);

            }
          catch (FaultException<MyFaultException> ex)
           {
             lblErrorMessage.Content = "Please Enter a Valid SQL Query";
            }
       }

And I wrote my GetDataTableDataCompleted event as below

     void objService_GetDataTableDataCompleted(object sender, GetDataTableDataCompletedEventArgse)
        {
         //code
        }

Вот мой метод обслуживания

 public IEnumerable<Dictionary<string, object>> GetDataTableData(string dataBaseName, string query)
    {
        try
        {
            IEnumerable<Dictionary<string, object>> objDictionary;
            objDictionary = objOptimityDAL.GetDataForSelectQuery(dataBaseName, query);
            return objDictionary;
        }
        catch (Exception ex)
        {
            MyFaultException fault = new MyFaultException();
            fault.Reason = ex.Message.ToString();
            throw new FaultException<MyFaultException>(fault, new FaultReason("Incorrect SQL Query"));

        }
    }

Здесь моя служба WCf взаимодействует с уровнем доступа к данным и успешно генерирует исключение сбоя, но не получает его на мой клиентский метод. Вместо этого я получаю необработанное исключение, например «Исключение связи не было обработано пользователем, удаленный сервер вернул ошибку: NotFound» "в коде References.cs, показанном ниже

 public System.Collections.ObjectModel.ObservableCollection<System.Collections.Generic.Dictionary<string, object>> EndGetDataTableData(System.IAsyncResult result) {
            object[] _args = new object[0];
            System.Collections.ObjectModel.ObservableCollection<System.Collections.Generic.Dictionary<string, object>> _result = ((System.Collections.ObjectModel.ObservableCollection<System.Collections.Generic.Dictionary<string, object>>)(base.EndInvoke("GetDataTableData", _args, result)));
            return _result;
        }

Вот Web.config службы Wcf

    <?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>   
    <behaviors>
      <serviceBehaviors>        
        <behavior>         
          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
           <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>  
</configuration>

Ниже мой файл ServiceReferences.ClientConfig.

 <configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IService1"
          maxBufferSize="2147483647"
          maxReceivedMessageSize="2147483647"
          closeTimeout="01:00:00"
          receiveTimeout="01:00:00"
          sendTimeout="01:00:00">
          <security mode="None" />
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:3132/Service1.svc" binding="basicHttpBinding"
          bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
          name="BasicHttpBinding_IService1" />
    </client>
  </system.serviceModel>
</configuration>

Пожалуйста, предложите мне как-нибудь поймать ошибку faultException в моем SilverlightClient

Заранее спасибо


person Sudhakar Byna    schedule 16.05.2013    source источник
comment
Возможно, в конфигурации есть какая-то ошибка, поскольку вы получаете исключение связи. Позволяет ли сервис звонить клиентам? Похоже, вы получаете сообщение об ошибке при попытке вызвать службу? Возможно, разместите свои web.configs и полную трассировку стека?   -  person Jocke    schedule 16.05.2013
comment
Привет, Джок, спасибо за ответ, я отредактировал свой пост с помощью файлов конфигурации, и я могу успешно вызвать метод службы, который, в свою очередь, генерирует исключение, но здесь проблема заключается в перехвате этого брошенного исключения из службы.   -  person Sudhakar Byna    schedule 16.05.2013
comment
Вы сделали FaultContract [FaultContract(typeof(MyFaultException))]? Вы можете прочитать это для получения дополнительных сведений. .   -  person Tonio    schedule 16.05.2013


Ответы (1)


При первом создании службы вам следовало выбрать службу WCF с поддержкой Silverlight. Это создало бы для вас всю инфраструктуру.

Но вы все равно можете добавить необходимый код вручную в проект службы WCF.

SilverlightFaultBehavior.cs

/// <summary>
/// The behavior which enables FaultExceptions for Silverlight clients
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class SilverlightFaultBehaviorAttribute : Attribute, IServiceBehavior
{
    private class SilverlightFaultEndpointBehavior : IEndpointBehavior
    {
        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new SilverlightFaultMessageInspector());
        }

        public void Validate(ServiceEndpoint endpoint)
        {
        }

        private class SilverlightFaultMessageInspector : IDispatchMessageInspector
        {
            public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
            {
                return null;
            }

            public void BeforeSendReply(ref Message reply, object correlationState)
            {
                if ((reply != null) && reply.IsFault)
                {
                    HttpResponseMessageProperty property = new HttpResponseMessageProperty();
                    property.StatusCode = HttpStatusCode.OK;
                    reply.Properties[HttpResponseMessageProperty.Name] = property;
                }
            }
        }
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
        {
            endpoint.Behaviors.Add(new SilverlightFaultEndpointBehavior());
        }
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }
}

Service1.cs

[SilverlightFaultBehaviorAttribute]
public class Service1 : IService1
{
...
}

А на клиенте вы должны проверить свойство e.Error внутри функции обратного вызова. Попробовать / поймать из вашего примера не получится.

Клиент Silverlight

objService.GetDataTableDataCompleted += (s, e) => 
    {
        if(e.Error != null) {
            if (e.Error is FaultException) {
                lblErrorMessage.Content = "Please Enter a Valid SQL Query";
            }
            // do something with other errors
        }
        else {
            // success
        }
    };

objService.GetDataTableDataAsync(_DATABASEName, strQuery);
person vortexwolf    schedule 16.05.2013
comment
Я вызываю событие objService.GetDataTableDataCompleted в событии нажатия кнопки. Итак, каковы параметры (s, e) в silverlightclient вашего ответа, как я могу написать это в моем событии нажатия кнопки. не могли бы вы быть красноречивым. Я отредактировал свой пост silverlightclient (.xaml.cs), не могли бы вы пройти через это и отредактировать свой ответ silverlightClient, пожалуйста. - person Sudhakar Byna; 17.05.2013
comment
@Sudhakar Byna (s, e) - входные параметры лямбда-выражения. Вы можете прочитать о лямбда-выражениях здесь: msdn.microsoft.com/en-us/ библиотека / bb397687.aspx - person vortexwolf; 17.05.2013
comment
Спасибо. На этот раз я получаю необработанное исключение, например, исключение типа 'System.ServiceModel.FaultException`1' произошло в System.ServiceModel.dll, но не было обработано в пользовательском коде в моем методе обслуживания при выбросе исключения сбоя, например, throw new FaultException ‹ MyFaultException ›(ошибка, новый FaultReason (неверный запрос SQL)); - person Sudhakar Byna; 17.05.2013
comment
Тогда это необработанное исключение является нарушением в файле References.cs в приведенном ниже коде public System.Collections.Generic.Dictionary ‹строка, объект› [] EndGetSelectQueryData (результат System.IAsyncResult) {object [] _args = new object [0]; System.Collections.Generic.Dictionary ‹строка, объект› [] _result = ((System.Collections.Generic.Dictionary ‹строка, объект› []) (base.EndInvoke (GetSelectQueryData, _args, result))); return _result; } - person Sudhakar Byna; 17.05.2013
comment
@SudhakarByna Отладчик Visual Studio останавливается каждый раз при возникновении исключения. После этого просто нажмите F5 или кнопку «Продолжить». - person vortexwolf; 17.05.2013