conflict beteween ValidationBehavior and ExceptionShielding in wcf

Topics: Exception Handling Application Block, Validation Application Block
Jul 29, 2010 at 8:47 AM

i used two enterbrise library block in WCF Project:

 [ServiceContract]
    [ValidationBehavior]
    [ExceptionShielding("Exception Policy")]
    public interface IService1
    {

        [OperationContract]
        [FaultContract(typeof(ServiceFault))]
        [FaultContract(typeof(ValidationFault))]
        string GetData([RangeValidator(5, RangeBoundaryType.Inclusive,6, RangeBoundaryType.Ignore,MessageTemplate="input muse be greater than 5")]int value);
        [OperationContract]
        CompositeType GetDataUsingDataContract(  CompositeType composite);

        // TODO: Add your service operations here
    }

in client side if i invoke the method  and pass a invalid value 4, i received this msg:

An error has occurred while consuming this service. Please contact your administrator for more information. Error ID: 0cbec700-641f-472b-9819-84c28d3cd0f3

but if i comment this attribute // [ExceptionShielding("Exception Policy")]

i can received the corret validation error msg:input muse be greater than 5

is it means i cannot use the validation and ExceptionShielding at the same time?
   

Jul 29, 2010 at 10:56 AM

Hi,

I can't able to reproduce your problem. It's working fine from my end. Now, I'm wondering if your ExceptionShielding is working properly. Can you confirm this by testing it alone without the validation? Thanks.

Gino Terrado
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

 

 

 

Jul 29, 2010 at 11:09 AM

yes gino,i tested the exceptionshielding, if i delete this [RangeValidator(5, RangeBoundaryType.Inclusive,6, RangeBoundaryType.Ignore,MessageTemplate="input muse be greater than 5")], the exceptionshielding works fine

Jul 29, 2010 at 11:18 AM
Edited Jul 29, 2010 at 11:19 AM

if i change this  <serviceDebug includeExceptionDetailInFaults="false" /> to  <serviceDebug includeExceptionDetailInFaults="true" />

i can receive the correct validation error message,but when u set includeExceptionDetailInFaults to true , it will disable the exceptionshielding

Jul 29, 2010 at 1:19 PM

I believe it is by design. The way I understand it based on here, setting the includeExceptionDetailInFaults="true" will return the actual exception raised from the WCF service to the client this is for debugging purposes so I assume the exceptionshielding may really won't work with this setting. Though, we may need confirmation from entlib team if this is indeed the expected behaviour. Well, anyway we both have the same result so I think we can cross out inconsistencies :-).

Hmm as for the validation how are you handling it in the client side? Is it something like this?

 catch (FaultException<ValidationFault> vex)
 {
        Console.WriteLine("Validation Message: " + vex.Detail.Details[0].Message);
 }

Gino Terrado
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Jul 29, 2010 at 2:07 PM
Edited Jul 29, 2010 at 2:17 PM

my client side code is like below:

 ServiceReference1.Service1Client s1 = new ConsoleApplication1.ServiceReference1.Service1Client();
            try
            {
                s1.GetData(4);
            }
            catch (FaultException<ValidationFault> valEx)
            {
                Console.WriteLine(valEx.Detail.Details[0].Message);
            }
            catch (FaultException<FaultContract> ex)
            {
                Console.WriteLine(ex.Detail.Message);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

and here is my web.config:

 

<system.serviceModel>
    <services>
      <service name="WcfService1.Service1" behaviorConfiguration="WcfService1.Service1Behavior">
        <!-- Service Endpoints -->
        <endpoint address="" binding="wsHttpBinding" behaviorConfiguration="Validation" contract="WcfService1.IService1">
          <!--
              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>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WcfService1.Service1Behavior">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true" />
          <!-- 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>
      <endpointBehaviors>
        <behavior name="Validation">
          <validation enabled="true" />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <extensions>
      <behaviorExtensions>
        <add name="validation"
         type="Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WCF.ValidationElement, Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WCF, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null" />

 </behaviorExtensions>
    </extensions>
 

  </system.serviceModel>

 

i think both use ValidationBehavior and ExceptionShielding is a very common scenario, don't know why make it so difficult

Jul 30, 2010 at 8:03 AM

To clear things up, you could use them both at the same time.  Where's your exceptionHandlingSettings configuration section?  You can opt to send a simple repro project so we could figure out what's wrong much easier.

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

 

Aug 2, 2010 at 3:09 AM
Edited Aug 2, 2010 at 3:19 AM

hi sarah and gino, i think i found the reason, if i changed the exception policy name from "Exception Policy" to "WCF Exception Shielding", everything works perfectly,

i step into the exceptionshieding's code source , i found that if i don't  named the policy name to "Exception Policy", it will execute   ExceptionPolicy.HandleException(error, ExceptionShielding.DefaultExceptionPolicy),

then it will throw a exception; exception msg is:

The requested exception policy 'WCF Exception Shielding' could not be found.


the relative source code is below:

 

public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            // Will create a default Message in case is null
            EnsureMessage(ref fault, version);

 

            try
            {
                // Execute the EHAB policy pipeline
                ExceptionPolicy.HandleException(error, exceptionPolicyName);
                // If we get to this line, then this exception is not
                // defined in the specified policy so treat it as unhandled if not in the default policy
                if (!exceptionPolicyName.Equals(ExceptionShielding.DefaultExceptionPolicy,
                    StringComparison.InvariantCultureIgnoreCase))
                {
                    // run first the default exception policy
                    ExceptionPolicy.HandleException(error, ExceptionShielding.DefaultExceptionPolicy);
                }
                // this is an unahndled exception so treat it as server and shield it.
                ProcessUnhandledException(error, ref fault);
            }
            catch (FaultContractWrapperException faultContractWrapperException)
            {
                // This exception was passed by the FaultContractExceptionHandler class
                // configured in the exception handler pipline.
                // Process the client exception that will be returned unshielded.
                // This is an application level exception that is already defined in the
                // corresponding FaultContract.
                HandleFault(faultContractWrapperException, ref fault);
            }
            catch (FaultException)
            {
                // this is a fault that comes from the service, so just send it back to the client.
                // this fault will be thrown from the exception pipeline if it is defined.
                return;
            }
            catch (Exception unhandledException)//if you don't named your polcy name as 'WCF Exception Shielding', the exception will catched here
            {
                // this is an unahndled exception so treat it as server and shield it.
                ProcessUnhandledException(error, unhandledException, ref fault);
            }
        }

 

my question is, is it a bug? why should i have to named my policy name as 'WCF Exception Shielding'?

Aug 2, 2010 at 3:49 AM

I was using "WCF Exception Shielding" as the name of my exception policy, that was the reason why I was unable to repro your error.  This looks like a bug, wcf exception shielding should work even if you specified a different name other than the default exception policy name as long as you specified it in the ExceptionShielding atttribute ([ExceptionShielding("Exception Policy")]). 

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Aug 11, 2010 at 9:34 AM

I created a work item for this in the Issue Tracker, refer to this link and add your vote to it :)

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com