1

I'm trying to throw a custom exception from a WCF Service to a Client application. I will try to describe as much code as I can think can be related to this.

Exception:

using System.Runtime.Serialization;

namespace App.Exceptions
{
    /// <summary>
    /// General App exception
    /// </summary>
    [DataContract]
    public class AppException : System.Exception
    {
        private string strMessage = "An unknown exception occurred";

        /// <summary>
        /// Creates a new instance of a App Exception
        /// </summary>
        public AppException()
        { }

        /// <summary>
        /// Creates a new instance of a App Exception
        /// </summary>
        /// <param name="Message">Message to send as exception</param>
        public AppException(string Message)
        { strMessage = Message; }

        public override string Message
        { get { return strMessage; } }
    }
}

Service code:

(...)
using App.Exceptions;

namespace App.Services
{
    public class Service1 : IService1
    {
        public Service1 () 
        { }

        public void TestFunction() 
        {
            throw new AppException();
        }
    }
}

ServiceInterface:

(...)

namespace App.Services.Interfaces
{
    [ServiceContract]
    public interface IService1
    {   
        [OperationContract]
        void TestFunction();
    }
}

Client:

(...)
using App.Exceptions;
(...)

try 
{
    service.TestFunction();
}
catch (AppException ex) 
{

}

Everything works very well, function is called on the service and exception is thrown. References are exactly the same either on Client and Server. I've cheched and AppException is being referenced on the same namepsace so it should be ok.

I've tried on service app.config to set <serviceDebug includeExceptionDetailInFaults="True" /> and also setting it to False just to see if I get a different Exception and in fact it is different so I'm not really understanding why the break point set on the catch for the AppException is never hit.

EDIT:

Service config:

  <service name="App.Services.Service1">
    <endpoint address="" binding="basicHttpBinding" contract="App.Services.Interfaces.IService1">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8733/Design_Time_Addresses/App.Services/Service1/" />
      </baseAddresses>
    </host>
  </service>

Client config:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IService1" />
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost:8733/Design_Time_Addresses/App.Services/Service1/"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1"
            contract="Services.IService1" name="BasicHttpBinding_IService1" />
    </client>
</system.serviceModel>
rgomez
  • 185
  • 1
  • 2
  • 17
  • Possible duplicate of [WCF Web Service Custom Exception Error to Client](https://stackoverflow.com/questions/1369882/wcf-web-service-custom-exception-error-to-client) – Marisa Sep 29 '17 at 15:36
  • I've tried that also. AppException Catch is never hit. – rgomez Sep 29 '17 at 15:41
  • did you use catch (AppException ex) or catch (FaultException ex)? The former won't work, the second should. – Marisa Sep 29 '17 at 15:49
  • I've just retried to do it and after doing exactly as on the other question you mentioned I got an issue updating the service reference Error 400 Metadata cointains a reference that cannot be resolved. Also I noticed when debug was on the throw of the fault exception it was showing "System.ServiceModel.FaultException`1" Is that the expected behavior? I don't think so. – rgomez Sep 29 '17 at 16:08
  • @rgomez why not just catch with Exception ex and check? – Hameed Syed Sep 29 '17 at 16:18
  • You mean check what? – rgomez Sep 29 '17 at 16:20

1 Answers1

0

You cannot throw any unhandled exceptions or .net or any exceptions like that from the server to the client(if client want to know the excpetions) because of security and interoperability reasons ,these exceptions by default are not propagated to clients from the wcf service.

Instead of propagating the exceptions,the WCF serializes them into SOAP fault and sends SOAP fault to the client.So you need to include this custom exception in SOAP fault.

First Let the servicecontract know the which operation can throw which SOAP faults.

namespace App.Services.Interfaces
{
    [ServiceContract]
    public interface IService1
    {   
        [FaultContract(typeOf(AppException))]
        [OperationContract]
        void TestFunction();
    }
}


using System.ServiceModel;
public class Service1 : IService1
    {
        public Service1 () 
        { }

        public void TestFunction() 
        {
            try
            {
             service.TestFunction();
            }
            catch(Exception ex)
             {
               AppException app=new AppException();
               app.strMessage =ex.Message;
               throw new FaultExcpetion<AppException>(app);
             }
        }
    }

Additionally ,you can have fault details and well as fault error.Catch the above exception at the client side.

//client side

     try
                {
                  //call wcf service contract.
                }
                catch (FaultException<ServiceReference.AppException> ex)
                {

                   label.Text=ex.Detail.strMessage ;
                }

One more way is to use custom WCF IErrorHandler implementation.Refer this https://stackoverflow.com/a/8764782/6086968 for centralized way of handling exceptions.

Edit1:The app.config need to be configured properly for metadata.

    <service name="App.Services.Service1" behaviorConfiguration="mexendpoint">
        <endpoint address="" binding="basicHttpBinding" contract="App.Services.Interfaces.IService1">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8733/Design_Time_Addresses/App.Services/Service1/" />
          </baseAddresses>
        </host>
      </service>
<behaviors>
  <serviceBehaviors>  
    <behavior name="mexendpoint">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
    </behavior>
     </serviceBehaviors>
</behaviors>
</system.serviceModel>
Hameed Syed
  • 3,939
  • 2
  • 21
  • 31
  • As soon as I add the `[FaultContract(typeof(AppException))]` to the service interface and build that project I cannot update service reference on client project. I've tried adding the service project as reference for the client and same error -> Error 400 Metadata cointains a reference that cannot be resolved – rgomez Sep 30 '17 at 14:45
  • Were ou able to build the server side code?Can you post your app.config xml where you are defining binding for wcf service?Also post the complete error message. – Hameed Syed Sep 30 '17 at 15:46
  • The error is. `Metadata contains a reference that cannot be resolved: 'address for service'. Content Type application/soap+xml; charset=utf-8 was not supported by service. The client and service bindings may be mismatched. The remote server returned an error (415) Cannot process the message because the content type 'application/soap+xml, charset=utf-8' was not the expected type 'text/xml; chartset-utf8'`.. I will update the question including configurations. – rgomez Sep 30 '17 at 16:06
  • I've tried that. The service do build but the update Service reference now returns a refused connection. `There was no endpoint listening on address '
    ' that could accept the message. This is often caused by an incorrect address or SOAP action (..)`
    – rgomez Sep 30 '17 at 16:41
  • so before these exception changes,were you able to update the add service reference successfully?Add Service1 implementation code also. – Hameed Syed Sep 30 '17 at 16:49
  • All I need to do to make everything work is comment the `[FaultContract(typeof(AppException))]` on the service interface and it works right away. Only no Catch of the fault exception is hit. – rgomez Sep 30 '17 at 16:50