Endpoint Identity not maintained after import

Topics: Usage Scenarios, Technical Questions
Jun 24, 2008 at 3:53 PM
I have the following WCF endpoint hosted in a Windows service.

                <endpoint address="net.tcp://appdev:10090/title/service"
                          binding="netTcpBinding"
                          bindingConfiguration="TcpSecurity"
                          contract="DefaultNet.IProcess.Title.ITitlePC"
                          behaviorConfiguration="TitleServiceEndpointBehavior">
                    <identity>
                        <dns value="DEV_SERVICES"/>
                    </identity>
                </endpoint
>

I am specifying the identity because my certificate name does not match the host name.  This works fine when generating a proxy and calling the service directly.  However, when I import this service into MSE, the identity setting is not persisted.  This results in the following error:

Communication Error in BeginRequest: Identity check failed for outgoing message. The expected DNS identity of the remote endpoint was 'appdev' but the remote endpoint provided DNS claim 'DEV_SERVICES'. If this is a legitimate remote endpoint, you can fix the problem by explicitly specifying DNS identity 'DEV_SERVICES' as the Identity property of EndpointAddress when creating channel proxy.

How can I configure MSE to use the identity setting?
Developer
Jun 25, 2008 at 9:23 PM
Edited Jun 25, 2008 at 9:26 PM
Essentially, we need to override the default channel creation the MSE performs.  This take a little effort, but is a great example of when & why you may want to override the default logic.  The ChannelMoniker associated with each operation version defines how the WCF channel stack is constructed to invoke the service implementation.  There is a good explanation of this process in the HttpForm Binding lab so I won't explain it too much here.

The key steps are:
1) Derive a class from the default ChannelModel (located in Microsoft.MSE.Runtime.Module.dll)
2) Create a custom ChannelFactory that creates the channel with the EndpointIdentity properly assigned.
3) Update the ChannelMoniker for each operation version that will need this functionality.

Here are some code snippets to make this easier:

New channel moniker that includes a property for the DnsName to use when creating the DnsEndpointIdentity

<

 

ChannelModelExt
Address="http://localhost:9300/CalculatorWCF/Calculator/Basic"
Action="http://mse.testservices.com/wcf/calculator/ICalculator/AddIntegers"
DnsName="localhost"
xmlns="clr-namespace:Microsoft.MSE.ExtendedChannelModel;assembly=Microsoft.MSE.ExtendedChannelModel"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</
ChannelModelExt>

 

 

 

 

 

New ChannelFactory implementation
 

 

 

 

public class ExtendedChannelFactory<TChannel> : ChannelFactory<TChannel>
{
    IExtendedChannelModelSettings _settings;
    public ExtendedChannelFactory(Binding binding, IExtendedChannelModelSettings settings)
        :
base(binding)
    {
        _settings = settings;
    }

 

    public override TChannel CreateChannel(EndpointAddress address, Uri via)
    {
        EndpointIdentity epIdentity = EndpointIdentity.CreateDnsIdentity(_settings.DnsName); 
        EndpointAddress newAddress = new EndpointAddress(address.Uri, epIdentity, address.Headers);
        return base.CreateChannel(newAddress, via);
    }
}

 

 

 

 

New ChannelModelExt implementation:

 

public class ChannelModelExt :ChannelModel, IExtendedChannelModelSettings
{
private Binding m_innerBinding;
public string DnsName { get; set; }

 

#region Binding Methods
public override BindingElementCollection CreateBindingElements()
{
    
return m_innerBinding.CreateBindingElements();
}

 

 

 

public override string Scheme
{
    
get { return m_innerBinding.Scheme; }
}

 

 

 

public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingParameterCollection parameters)
{
    m_innerBinding = GetInnerBinding(parameters);
    
ExtendedChannelFactory<TChannel> factory = new ExtendedChannelFactory<TChannel>(m_innerBinding, this);
    
return factory;
}

 

 

 

#endregion

 

 

 

 

 

private Binding GetInnerBinding(BindingParameterCollection parameters)
{
    
Binding containedBinding = null;
    
if (null != parameters && parameters.Count > 0)
    {
        
for (int i = 0; i < parameters.Count; i++)
        {
            containedBinding = parameters[i]
as Binding;
            
if (null != containedBinding)
            
break;
        }
    }
    
return containedBinding;
}

 

 }

 

 

public interface IExtendedChannelModelSettings
{
string Address { get; set; }
string Action { get; set; }
string DnsName { get; set; }
}

 

 

 

 




kdstock wrote:
I have the following WCF endpoint hosted in a Windows service.

                <endpoint address="net.tcp://appdev:10090/title/service"
                          binding="netTcpBinding"
                          bindingConfiguration="TcpSecurity"
                          contract="DefaultNet.IProcess.Title.ITitlePC"
                          behaviorConfiguration="TitleServiceEndpointBehavior">
                    <identity>
                        <dns value="DEV_SERVICES"/>
                    </identity>
                </endpoint
>

I am specifying the identity because my certificate name does not match the host name.  This works fine when generating a proxy and calling the service directly.  However, when I import this service into MSE, the identity setting is not persisted.  This results in the following error:

Communication Error in BeginRequest: Identity check failed for outgoing message. The expected DNS identity of the remote endpoint was 'appdev' but the remote endpoint provided DNS claim 'DEV_SERVICES'. If this is a legitimate remote endpoint, you can fix the problem by explicitly specifying DNS identity 'DEV_SERVICES' as the Identity property of EndpointAddress when creating channel proxy.

How can I configure MSE to use the identity setting?