Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts

Thursday, 18 April 2013

Fixing WSDL addresses in WCF 3.5 hosted on IIS 7 and using SSL

Problem

I needed to host a WCF 3.5 web service on IIS 7 (running on Windows Server 2008) using SSL. In fact the service was configured to use wsHttpBinding with TransportWithMessageCredential. The service was running on a public facing web server with a registered domain name.

The problem was usual one; having navigated to .svc file in a browser the service description page showed the WSDL URL to be using the machine name, not the domain name. When viewing the generated WSDL the service location was also using the machine name.

Solution

The web site bindings had been set up in IIS for HTTP and HTTPS. It appears that when the HTTPS binding is setup the host name is not set. You cannot set this using the Internet Information Services (IIS) Manager so you have to do it by other means.

 

image

To add the host name to the HTTPS binding do the following:

  1. Open the applicationHost file located in C:\Windows\System32\inetsrv\config.
  2. Locate the section for the website in question (you can see the web site name in the Internet Information Services (IIS) Manager).
  3. Find the https binding and change the bindingInformation by adding the domain name after “:443:”.
  4. Save the applicationHost file and restart IIS.

 

Now when you view the service .svc file in a browser and the generated WSDL the domain name will appear in place of the machine name.

Thursday, 18 April 2013,

Wednesday, 30 January 2013

Single file WSDL generation in WCF

Sometimes it is convenient or even necessary (e.g. some interoperability scenarios) to have WCF generate a single WSDL file without references to external schema. Luckily, there are some 3rd party libraries available to help out: WCFExtras and WCFExtrasPlus. These are both available from NuGet. WCFExtrasPlus is based on WCFExtras and is slightly more up-to-date. Note that there seems to be 2 versions of WCFExtras as well. At the time of writing NuGet gives you WCFExtras 2.0.

Steps

My steps here are based on an IIS hosted WCF service.

Firstly, use NuGet to reference WCFExtras in the WCF host project.

Secondly, edit your Web.config file to include the following behaviour extension:

<system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name="wsdlExtensions" type="WCFExtrasPlus.Wsdl.WsdlExtensionsConfig, WCFExtrasPlus, Version=2.3.0.2, Culture=neutral, PublicKeyToken=f8633fc5451b43fc"/>
      </behaviorExtensions>
    </extensions>
    ... snip ...
</system.serviceModel>

If the version is different you can use something like Telerik JustDecompile to get the correct information to use in the type attribute of the add element.

Next create an endpoint behaviour referencing the new extensions:

<system.serviceModel>
    ... snip ...
    <behaviors>
      <endpointBehaviors>
        <behavior name="SingleFileBehaviour">
          <wsdlExtensions singleFile="true" />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    ... snip ...
</system.serviceModel>

You now need to update your endpoint definitions to use the new behaviour, something like this:

<endpoint address="" 
binding="wsHttpBinding"
bindingNamespace="http://schemas.example.com/Example"
bindingConfiguration="wsHttpBindingConfiguration"
behaviorConfiguration="SingleFileBehaviour"
contract="Example.ServiceContracts.IExampleService" />

Fixing problems

Most execution problems seem to stem from namespacing issues. In WCFExtras there is a class called WCFExtras.Wsdl.SingleFileExporter that does the work. The first thing it does is check that the number of generated WSDL documents is not greater that 1 and this will be the case is your namespaces are wrongly defined. Here’s my checklist to avoid problems:

1. If you define service contracts in a separate interface ensure the ServiceContract attribute has a namespace.

[ServiceContract(Name = "ExampleService", "Namespace = http://schemas.example.com/Example")]

2. In the service class add a ServiceBehavior attribute also with a namespace (failure to do this will result in the service being given the http://tempuri.org namespace). The namespace must match that of the service contract.

[ServiceBehavior(Namespace = "http://schemas.example.com/Example")]

3. Check the binding namespace on the endpoint configuration in Web.config (see above).

4. Check the namespaces on any DataContract or MessageContract attributes.

5. If you are building at x86 you might want to set the project output path to be bin\ to avoid having multiple folders with different copies of the dlls. 

Wednesday, 30 January 2013

Thursday, 27 October 2011

Handling WCF faults in Silverlight

Here’s a quick reminder to self about handling SOAP faults in Silverlight applications, something that happened recently and I forgot a simple step.

Before going any further read this (it will probably answer all your questions): Creating and Handling Faults in Silverlight

Firstly, I had a WCF service that was exposing faults contracts using the [FaultContract] attribute.

[ServiceContract(Namespace = "http://some_namespace_here/ConfigurationService/2011/10/01/01", Name = "ConfigurationService")]
public interface IConfigurationService
{
    [OperationContract(Name = "GetConfiguration")]
    [FaultContract(typeof(MyFault))]
    [FaultContract(typeof(ValidationFault))]
    ConfigurationResponse GetConfiguration(ConfigurationRequest request);
}

The service was implemented along with fault types, for example:

[DataContract(Namespace = "http://some_namespace_here/WIRM/2011/10/01/01", Name = "MyFault")]
public class MyFault
{
    [DataMember(IsRequired = true, Name = "FaultDetail", Order = 0)]
    public string FaultDetail { get; set; }

    [DataMember(IsRequired = true, Name = "FaultCode", Order = 1)]
    public string FaultCode { get; set; }
}

The problem was that back in Silverlight when I was handling exceptions generated from service calls the exception didn’t have the specific detail of the fault. The trick to making this work is in the article linked to above. We chose to use the “alternative client HTTP stack” approach by adding this to App.xaml.cs:

public partial class App : Application
{
    public App()
    {
        bool registerResult = WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
        InitializeComponent();
    }
}

Thereafter it was possible to get at the actual fault exceptions and take advantage of specific exception details:

private void ClientGetConfigurationCompleted(object sender, GetGetConfigurationEventArgs e)
{
    if (e.Error == null)
    {
        // Do normal processing here...
        return;
    }
            
    if (e.Error is FaultException<ValidationFault>)
    {   
        var ex = e.Error as FaultException<ValidationFault>;
        // Do stuff with validation errors (via ex.Detail)
    }
            
    if (e.Error is FaultException<MyFault>)
    {
        var ex = e.Error as FaultException<WirmFault>;
        // Do stuff with MyFault (via ex.Detail)
    }
}

That’s it.

Monday, 23 May 2011

What is the difference between the various WCF programming models?

OK, I’m getting confused again about the differences between the various WCF-based programming models. There are so many variations on the theme - WCF Data Services, WCF RIA Services, WCF Web API, etc. – that I can no longer see the wood for the trees. Microsoft’s insistence on renaming things doesn’t help. So, here’s a quick aide-mémoire for me based on WCF, Data Services and RIA Services Alignment Questions and Answers.

Service model Description Also known as
WCF
  • SOAP-based services
  • Full flexibility for building operation-centric services
  • Supports interoperability (e.g. with Java)
  • Indigo
WCF WebHttp Services
  • Operation centric
  • Expose WCF service operations to non-SOAP endpoints
  • Best when
    • operation-centric HTTP services to be deployed at web scale
    • or building a RESTful service and want full control over the URI/format/protocol
  • WCF Rest
WCF Data Services
  • Data centric
  • Best when exposing data model through a RESTful interface
  • Includes a full implementation of the OData Protocol
  • Astoria
  • ADO.Net Data Services
WCF RIA Services
  • For building an end-to-end Silverlight applications
  • Provides a prescriptive pattern that defaults many options for the best experience in the common cases
  • .Net RIA Services
WCF Web API
  • Expose applications, data and services to the web directly over HTTP
  • Replaces the REST Starter Kit
  • Supporting SOAP is not a goal
  • New kid on the block

References

Monday, 23 May 2011

Friday, 4 February 2011

Known Types in a WCF service

Firstly, this post has been prompted by an MSDN Magazine article by renowned brain-box, Juval Lowy: Data Contract Inheritance. Having recently been forced to resort to the [KnownType] attribute on a WCF data contract, and having been slightly confused as to why (not to mention uncomfortable with having a data contract base class now coupled to its subclasses) the article has proved most illuminating.

For my own benefit here are a few choice bits from the article (my bold).

What’s the problem?

Unlike traditional object orientation or the classic CLR programming model, WCF passes all operation parameters by value, not by reference… The parameters are packaged in the WCF message and transferred to the service, where they are then deserialized to local references for the service operation to work with…

… With multitier applications, marshaling the parameters by value works better than by reference because any layer in the architecture is at liberty to provide its own interpretation to the behavior behind the data contract. Marshaling by value also enables remote calls, interoperability, queued calls and long-running workflows.

If you do pass a subclass reference to a service operation that expects a base class reference, how would WCF know to serialize into the message the derived class portion?

What does [KnownType] do?

When the client passes a data contract that uses a known type declaration, the WCF message formatter tests the type (akin to using the is operator) and sees if it’s the expected known type. If so, it serializes the parameter as the subclass rather than the base class…

The WCF formatter uses reflection to collect all the known types of the data contracts, then examines the provided parameter to see if it’s of any of the known types…

… Because the KnownType attribute may be too broad in scope, WCF also provides ServiceKnownTypeAttribute, which you can apply on a specific operation or on a specific contract.”

.Net 4 to the rescue

To alleviate the problem, in the .NET Framework 4 WCF introduced a way of resolving the known types at run time. This programmatic technique, called data contract resolvers, is the most powerful option because you can extend it to completely automate dealing with the known type issues. In essence, you’re given a chance to intercept the operation’s attempt to serialize and deserialize parameters and resolve the known types at run time both on the client and service sides.

Friday, 4 February 2011

Thursday, 27 January 2011

Breaking dependencies on specific DI containers

Warning: Before going any further you probably want to have a look at Service locator anti-pattern. The code featured in this post uses Service Locator but the pattern is regarded by some to be an anti-pattern and as such should be avoided.

I’ve been working on a WCF service that uses Unity for dependency resolution. Everything has been working but I’ve been unhappy about a tight dependency on Unity itself that I have introduced in my code. I recalled that there is a service locator library knocking around that defines an interface that IoCs can adopt.

The Common Service Locator library contains a shared interface for service location which application and framework developers can reference. The library provides an abstraction over IoC containers and service locators. Using the library allows an application to indirectly access the capabilities without relying on hard references. The hope is that using this library, third-party applications and frameworks can begin to leverage IoC/Service Location without tying themselves down to a specific implementation.” - http://commonservicelocator.codeplex.com/

The Common Service Locator library provides a simple interface for service location:

public interface IServiceLocator : IServiceProvider
{
    object GetInstance(Type serviceType);
    object GetInstance(Type serviceType, string key);
    IEnumerable<object> GetAllInstances(Type serviceType);
    TService GetInstance<TService>();
    TService GetInstance<TService>(string key);
    IEnumerable<TService> GetAllInstances<TService>();
}

It turns out that the library is supported by Unity (as well as a bunch of other IoC implementations). The Common Service Locator library site links to an adapter for Unity but peeking around I found the UnityServiceLocator class in the Microsoft.Practices.Unity assembly.

I have now been able to replace all references to IUnityContainer with IServiceLocator (i.e. breaking the tight dependency on Unity). In the case of the WCF service all I needed to do was create a ServiceHostFactory implementation that passes an instance of UnityServiceLocator around rather than an instance of UnityContainer.

public class UnityServiceLocatorServiceHostFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        var unityContainer = new UnityContainer();
        unityContainer.LoadConfiguration();
        var unityServiceLocator = new UnityServiceLocator(unityContainer);
        return new ServiceLocatorServiceHost(serviceType, unityServiceLocator, baseAddresses);
    }  
}

The UnityServiceLocatorServiceHostFactory is the only class that has a tight dependency on Unity and can be farmed off into a separate Unity assembly. All other classes, including the service host implementation, only need to deal with IServiceLocator:

public class ServiceLocatorServiceHost : ServiceHost
{
    private IServiceLocator _serviceLocator;
        
    public ServiceLocatorServiceHost(IServiceLocator serviceLocator) : base()
    {
        _serviceLocator = serviceLocator;
    }

    public ServiceLocatorServiceHost(Type serviceType, IServiceLocator serviceLocator, params Uri[] baseAddresses)
        : base(serviceType, baseAddresses)
    {
        _serviceLocator = serviceLocator;
    }

    protected override void OnOpening()
    {
        if (Description.Behaviors.Find<ServiceLocatorServiceBehaviour>() == null)
        {
            Description.Behaviors.Add(new ServiceLocatorServiceBehaviour(_serviceLocator));
        }

        base.OnOpening();
    }
}

The ServiceLocatorServiceBehavior adds a service locator instance provider to the endpoint dispatcher, something like this:

public class ServiceLocatorServiceBehavior : IServiceBehavior
{   
    private readonly IServiceLocator _serviceLocator;
	
    public ServiceLocatorServiceBehavior(IServiceLocator serviceLocator)
    {
        _serviceLocator = serviceLocator;
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        // Nothing to see here. Move along...
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
        // Nothing to see here. Move along...
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
        {
            foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
            {
                string contractName = endpointDispatcher.ContractName;
                ServiceEndpoint serviceEndpoint = serviceDescription.Endpoints.FirstOrDefault(e => e.Contract.Name == contractName);
                endpointDispatcher.DispatchRuntime.InstanceProvider = new ServiceLocatorInstanceProvider(_serviceLocator, serviceEndpoint.Contract.ContractType);
            }
        }
    }
}

And finally the ServiceLocatorInstanceProvider uses the service locator to resolve dependencies, something like this:

public class ServiceLocatorInstanceProvider : IInstanceProvider
{
    private readonly IServiceLocator _serviceLocator;
    private readonly Type _contractType;

    public ServiceLocatorInstanceProvider(IServiceLocator serviceLocator, Type contractType)
    {
        this._serviceLocator = serviceLocator;
        this._contractType = contractType;
    }

    public object GetInstance(InstanceContext instanceContext)
    {
        return GetInstance(instanceContext, null);
    }

    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        return _serviceLocator.GetInstance(_contractType);
    }

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
            
    }
}

Tuesday, 18 January 2011

Multiple X.509 certificates found

Problem

I was configuring a WCF service to use SSL and had created and installed a self-signed certificate. The WCF service configuration looked something like this:

<serviceBehaviors>
  <behavior name="EnquirySubmissionServiceBehavior">
    <serviceMetadata httpsGetEnabled="true" />
    <serviceDebug includeExceptionDetailInFaults="true" />
    <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="SqlRoleProvider" />
    <serviceCredentials>
      <serviceCertificate findValue="CertificateNameHere" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
    </serviceCredentials>
  </behavior>
</serviceBehaviors>

When trying to access the service metadata in a browser I received an error stating that multiple X.509 certificates had been found using the given search criteria.

Solution

The solution was to change the configuration to use an alternative method to find the certificate. In this case I used FindByThumbprint and provided the certificate thumbprint. To obtain the thumbprint do the following:

1. Start > Run > mmc
2. File > Add/Remove snap in…
3. Find and add Certificates (local machine).
4. Find the certificate and double-click on it.
5. In the pop-up dialog scroll to Thumbprint and click on it to view the value.
6. Copy the thumbprint value and remove spaces.

untitled

I then changed the WCF service configuration to look something like this:

<serviceBehaviors>
  <behavior name="EnquirySubmissionServiceBehavior">
    <serviceMetadata httpsGetEnabled="true" />
    <serviceDebug includeExceptionDetailInFaults="true" />
    <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="SqlRoleProvider" />
    <serviceCredentials>
      <serviceCertificate findValue="46677f6006fb15fe64e5f394d1d99c22f3729155" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
    </serviceCredentials>
  </behavior>
</serviceBehaviors>

Friday, 14 January 2011

IIS7 and WCF MIME types

Problem

I needed to deploy a WCF service to IIS7 running on windows server 2008. The service was accessed via a .svc file but upon calling it from a browser an error was reported stating that the .svc extension was not recognised.

Solution

The solution was to reregister the WCF Service Model with IIS by running ServiceModelReg.exe:

"%windir%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe" -r -y

The flags used were:

Flag Description
-r Re-registers this version of WCF and updates scriptmaps at the IIS metabase root and for all scriptmaps under the root. Existing scriptmaps are upgraded to this version regardless of the original versions.
-y Do not ask for confirmation before registering or re-registering components.

After reregistering the WCF Service Model the .svc extension was correctly installed. Note that IIS7 did not require a restart.

Full details of ServiceModelReg.exe and all its flags can be found here: ServiceModel Registration Tool (ServiceModelReg.exe)

Friday, 14 January 2011,

Friday, 31 December 2010

WCF service reference not creating correct proxy classes

Problem

I had a test project using NUnit to run unit tests for some components of a WCF service. In addition, I decided to include some integration tests that actually called a WCF service running in IIS on the localhost. To run the integration tests I created a service reference (which should generate the proxy classes) some types I had expected to find didn’t appear as proxies. The types that didn’t appear were declared as known types against the WCF service definition and all data contract attributes were correct. 

When I tried to use a type I had expected to find as a proxy class ReSharper was trying to help me out by referring me to the actual classes in the service projects, not from generated proxies. Even stranger, when I looked at the Reference.cs file (which should contain the proxy classes) the proxy classes were indeed missing but I could find declarations for the actual classes from the service projects.

Image1 
To find References.cs – in the Solution Explorer, View All Files and expand the service reference.

Solution

The fact that ReSharper was helping by pointing at the service projects was the clue. Because this was a test project I had included unit tests that created instances of classes from the service projects and as such had included references to those projects. When I added the service reference it looks like the actual service classes were used in preference to creating proxies.

I removed the references to the service projects, commented out code that needed those references and then re-added the service reference. The proxies were generated correctly.

The moral of the story is, don’t add references to the actual service projects as well as service references to the same code. It’s a good idea to run integration tests in a separate project so the references and service references don’t trip over each other.

Friday, 31 December 2010

Thursday, 18 November 2010

WCF service throwing immediate timeout

The problem

I was recently writing automated integration tests against a WCF service using NUnit when out of the blue all the tests failed and kept failing. An examination of the exceptions thrown showed that in each case a CommunicationException was being thrown because of a timeout.

What was most perplexing was that the apparent timeouts were being reported immediately but the client configuration was set to defaults:

<system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_EnquirySubmissionService" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                    allowCookies="false">
                    <!-- snip -->
                </binding>
            </wsHttpBinding>
        </bindings>
        <!-- snip -->
  </system.serviceModel>
</configuration>

The service was using WsHttpBinding and was hosted by IIS over HTTPS. The service was also secured using TransportWithMessageCredential and UserName credentials on the message (i.e. username and password).

 

The solution

Firstly I enabled tracing on the service by modifying the Web.config file to include the following:

<system.diagnostics> 
    <sources> 
        <source name="System.ServiceModel" switchValue="Information,ActivityTracing" propagateActivity="true"> 
            <listeners> 
                <add name="xml" /> 
            </listeners> 
        </source> 
        <source name="System.ServiceModel.MessageLogging"> 
            <listeners> 
                <add name="xml" /> 
            </listeners> 
        </source> 
    </sources> 
    <sharedListeners> 
        <add initializeData="C:\logs\TracingAndLogging-client.svclog" type="System.Diagnostics.XmlWriterTraceListener" name="xml" /> 
    </sharedListeners> 
    <trace autoflush="true" />
</system.diagnostics>

I then queried the service again to promote a timeout communication exception. I found the trace log contained:

System.ServiceModel.Security.MessageSecurityException: Message security verification failed. ---&amp;gt; System.ComponentModel.Win32Exception: The event log file is full
at System.Diagnostics.EventLog.InternalWriteEvent(UInt32 eventID, UInt16 category, EventLogEntryType type, String[] strings, Byte[] rawData, String currentMachineName) 
at System.Diagnostics.EventLog.WriteEvent(EventInstance instance, Byte[] data, Object[] values) 
at System.Diagnostics.EventLog.WriteEvent(String source, EventInstance instance, Object[] values) 
at System.ServiceModel.Security.SecurityAuditHelper.WriteEventToApplicationLog(EventInstance instance, Object[] parameters) 
at System.ServiceModel.Security.SecurityAuditHelper.WriteMessageAuthenticationSuccessEvent(AuditLogLocation auditLogLocation, Boolean suppressAuditFailure, Message message, Uri serviceUri, String action, String clientIdentity) 
at System.ServiceModel.Security.SecurityProtocol.OnIncomingMessageVerified(Message verifiedMessage) 
at System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessageCore(Message&amp;amp; message, TimeSpan timeout) 
at System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessage(Message&amp;amp; message, TimeSpan timeout)

So, the problem actually was that the event log was full! Having emptied the event log everything started working again.

Thursday, 18 November 2010

Saturday, 9 October 2010

Viewing SOAP message contents

I struggle to visualise the contents of a SOAP message by looking at WSDL. This is compounded by the somewhat indirect way changing settings in WCF service configuration (either in configuration files or code attributes) affects the WSDL and ultimately the SOAP message. It is much easier to actually have a peek at the contents of the SOAP message.
The solution to my problem was provided by Kory Becker in his article Displaying SOAP XML Messages in a Simple WCF Web Service.
For convenience I’ve created a little Visual Studio project (C#) with the code already implemented here. Note that to see the output in Visual Studio for services hosted in IIS the trick is to debug the service by attaching the debugger to the ASP.Net worker process.
Saturday, 9 October 2010

Convert a service to view metadata over HTTPS

I wanted to host a WCF service in IIS over HTTPS (i.e. using SSL). I already had a service host setup in IIS with a mex endpoint configured for HTTP. So, I configured the host site to use SSL but when I browsed to the service in a web browser I got the following error:

https-error
“Could not find a base address that matches scheme http for the endpoint binding MetadataExchangeHttpBinding…”

To change the service to use HTTPS I hade to make a couple of changes.

  1. Set the metadata exchange endpoint to use the mexHttpsBinding (not the mexHttpBinding).
  2. Modify the service behaviour to enable getting metadata over HTTPS (httpsGetEnabled).
  3. Changed the service base address to use HTTPS.
<system.serviceModel>
  <services>
    <service behaviorConfiguration="ServiceBehavior" name="Service.Service">
      ...
      <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
        <host> 
          <baseAddresses>
<add baseAddress="https://www.domaingoeshere.com/" />
</baseAddresses>
</host>
</service> </services> <bindings> ... </bindings> <behaviors> <serviceBehaviors> <behavior name="ServiceBehavior"> <serviceMetadata httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> ... </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>

NB: Don't forget that existing clients will have to update their service references.

Saturday, 2 October 2010

Keyset does not exist

I was trying to run a WCF service with additional security and generated the following “Keyset does not exist” error:

Image4 

Reading the stack trace I got the following additional information:

[ArgumentException: It is likely that certificate 'CN=RPKey' may not have a
private key that is capable of key exchange or the process may not have access
rights for the private key. Please see inner exception for detail.]

This turned out be file security settings on the key file. To fix the problem you may need to grant file permissions to the appropriate key file (in this case the RPKey file). To find the location of the key file I ran the FindPrivateKey utility which shipped with the WF and WCF Samples obtained from MSDN. Build the FindPrivateKey sample an run it in a command window:

C:\...path here...\FindPrivateKey\CS\bin>findprivatekey My LocalMachine -n "CN=RPKey" –a 

This gave the location of the key file and I was able to grant permissions to the ASPNET user. You may need to grant permissions to the network service user.

Normal service restored.

Wednesday, 29 September 2010

Instancing and concurrency in WCF

It doesn’t take long for my head to explode when thinking about threading and there is no exception when it comes to WCF. Here are a few notes on some of the main points.

How a WCF service reacts when it comes to threading and concurrency issues is basically governed by 2 concepts associated with the ServiceBehaviourAttribute: how the service is instantiated (e.g. as a singleton) through the use of the InstanceContextMode enumeration, and whether the service supports single-threaded or multi-threaded access through the use of the ConcurrencyMode enumeration.

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,
    ConcurrencyMode=ConcurrencyMode.Multiple, 
    UseSynchronizationContext=false)]
public class MessagingService : IMessagingService
{
 // other code here...
}

Instancing with the InstanceContextMode enumeration

InstanceContextMode  specifies the number of service instances available for handling calls that are contained in incoming messages.It therefore controls how service instances are allocated in response to client calls. InstanceContextMode can be set to the following values:

  • Single – One service instance is allocated for all client calls.
  • PerCall – One service instance is allocated for each client call.
  • PerSession – One service instance is allocated for each client session.

The default setting for InstanceContextMode is PerSession.

Note that when InstanceContextMode is set to PerCall, the ConcurrencyMode setting is ignored because each client call is routed to a new service instance. Only one thread is running in a service instance at one time.

Also note that when InstanceContextMode is set to PerCall, a new service instance is created for each client call and the instance is destroyed when the client call completes. In this case there are no synchronisation issues because each client call gets its own service instance.

If InstanceContextMode is set to Single the service can only process one message at a time unless you set the ConcurrencyMode to Multiple.

Concurrency with the ConcurrencyMode enumeration

ConcurrencyMode controls how multiple threads are allowed into the service at one time. ConcurrencyMode can be set to one of the following values:

  • Single – One thread can enter the service at one time.
  • Reentrant – One thread can enter the service at one time but callbacks are allowed.
  • Multiple – Multiple threads can enter the service at one time.

The default setting for ConcurrencyMode is Single. Setting ConcurrencyMode to single allows you to share service instances across multiple clients.

MSDN documentation states that the default value was chosen so that developers do not have to think about synchronisation by default.

Note that when the ConcurrencyMode is set to Multiple, multiple client calls can get through but it is the developer who is responsible for synchronising access to shared data.

The following table shows when an operation can be invoked while another one is in progress:

ConcurrencyMode Value Can a new operation be invoked?
Single Never
Reentrant Only while invoking another service or a callback
Multiple Always

 

Using the SynchronizationContext

In the C# example at the top of the page there is another property of the service behaviour attribute that is being used: UseSynchronizationContext. This property is of particular use if the service is being invoked from Windows clients (Win forms or WPF) and especially if callbacks are being used.

This is quite a complex topic which is covered in detail here.

See also

MSDN documentation:

Wednesday, 29 September 2010

Saturday, 25 September 2010

So what’s this IExtensibleDataObject interface all about then?

When defining WCF data contracts (i.e. classes marked with a DataContractAttribute) problems can occur with regards to versioning; adding new members to a data contract for example. Data could be passed to a version of a service that was not expecting it. This data could then be lost at the service.

By implementing the IExtensibleDataObject interface a data contract class can preserve unknown members included in the serialised type. The DataContractSerializer will populate the ExtensionDataObject dictionary required by the interface during the deserialisation process. The dictionary is then used to provide the additional member values upon serialisation.

This is useful:

  • When clients send additional unknown data to a service that should be returned intact
  • When a later version client sends data to an earlier version service and you want to preserve the unknown data for version tolerance

Ignoring IExtensibleDataObject at the service level

Even if data contract classes implement IExtensibleDataObject you can tell a service to ignore it by applying a service behaviour.

<behaviour name="serviceBehavior">
    <dataContractSerializer ignoreExtensionDataObject="true" />
</behaviour>

Additional information

The MSDN documentation states:

*The IExtensibleDataObject interface provides a single property that sets or returns a structure used to store data that is external to a data contract. The extra data is stored in an instance of the ExtensionDataObject class and accessed through the ExtensionData property. In a roundtrip operation where data is received, processed, and sent back, the extra data is sent back to the original sender intact. This is useful to store data received from future versions of the contract. If you do not implement the interface, any extra data is ignored and discarded during a roundtrip operation.” *

* IExtensibleDataObject Interface

Saturday, 25 September 2010

Thursday, 23 September 2010

What are WCF behaviours?

WCF concepts such as endpoints, bindings, operations etc. have all seemed straight forward to me but for some reason behaviours have not. For example why, if I expose a metadata endpoint do I also have to explicitly implement a metadata behaviour? This post is an aide memoire about behaviours.

What are behaviours?

“Behaviors are types that modify or extend Service or Client functionality. For example, the metadata behavior that ServiceMetadataBehavior implemented controls whether the Service publishes metadata. Similarly, the security behavior controls impersonation and authorization, while the transactions behavior controls enlisting in and auto-completing transactions.

Behaviors also participate in the process of building the channel and can modify that channel based on user-specified settings and/or other aspects of the Service or Channel.

A Service Behavior is a type that implements IServiceBehavior and applies to Services. Similarly, a Channel Behavior is a type that implements IChannelBehavior and applies to Client Channels.” *

Michele Leroux Bustamonte, in her book Learning WCF describes behaviours in the following terms:

“While endpoints describe where to reach the service, which operations are available at the specified address, and what protocols are required – behaviors affect the service model locally at the client or service. What this means is that behaviours are not exposed as part of metadata, and they are not shared between clients and services. Instead, the locally affect how the service model processes messages.” **

There are 4 types of behaviour: service, endpoint, operation and contract. Endpoint behaviours can be associated with service endpoints or client endpoints.

A WCF behaviour can be added to the runtime using one of the following methods:

  • Programmatically
  • Using attributes
  • Through configuration

Service behaviours:

  • Implement System.ServiceModel.Description.IServiceBehavior
  • Applies to the service itself or to specific endpoints, contracts, and operations
  • Can be added by attribute, configuration or programmatically

Endpoint behaviours:

  • Implement System.ServiceModel.Description.IEndpointBehavior
  • Affects the operation of a particular endpoint
  • Can be added by configuration or programmatically

Contract and operation behaviours are used to apply extensions to contracts and operations. Contract behaviours:

  • Implement System.ServiceModel.Description.IContractBehavior
  • Applies to a particular contract
  • Can be added by attribute or programmatically

Operation behaviours:

  • Implement System.ServiceModel.Description.IOperationBehavior
  • Affects a particular operation
  • Can be added by attribute or programmatically

Endpoint, contract, and operation behaviours can be applied to both services and clients, but service behaviours can only be applied to services.

See also Extending WCF with Custom Behaviors.

* Windows Communication Foundation Architecture Overview
** Learning WCF

Thursday, 23 September 2010

Missing “Edit WCF Configuration” menu option

Sometimes when you have created a new WCF service the “Edit WCF Configuration” context menu option is not available when you right-click on the config file (e.g. app.config). I have reproduced the problem below by creating a new class library and adding a WCF service to it. Right-clicking on the app.config file does not show the “Edit WCF Configuration” option.

Image1

To restore the missing option go to Tools > WCF Service Configuration Editor. This opens the editor but does not open the appropriate configuration file.

Image2

Close the editor immediately. Right-clicking on the configuration file will now show the previously missing “Edit WCF Configuration” option.

Image3

Monday, 12 July 2010

WCF Service Reference returns array and not List<T>

If you create a Service Reference to a WCF service that has operations that return generic collections you might be surprised to find the collection is exposed on the client as an array. This is the default behaviour for a WCF Service Reference but it is configurable.

To change the collection type for operations:

  1. In Visual Studio 2010 right-click on the appropriate service reference.
  2. Choose Configure Service Reference… from the pop-up menu.
  3. Choose an appropriate Collection Type on the dialog box (see image below).
  4. Click OK.

Image1

Monday, 12 July 2010

Wednesday, 7 July 2010

What is the Windows Process Activation Service (WAS)?

Here are some brief notes on the Windows Process Activation Service.

“Windows Process Activation Service (WAS) is the new process activation mechanism for the Windows Server 2008 that is also available on Windows Vista. It retains the familiar IIS 6.0 process model (application pools and message-based process activation) and hosting features (such as rapid failure protection, health monitoring, and recycling), but it removes the dependency on HTTP from the activation architecture. IIS 7.0 uses WAS to accomplish message-based activation over HTTP. Additional WCF components also plug into WAS to provide message-based activation over the other protocols that WCF supports, such as TCP, MSMQ, and named pipes. This allows applications that use communication protocols to use the IIS features such as process recycling, rapid fail protection, and the common configuration system that were only available to HTTP-based applications.” * (my bold)

“The Windows Process Activation Service (WAS) manages the activation and lifetime of the worker processes that contain applications that host Windows Communication Foundation (WCF) services. The WAS process model generalizes the IIS 6.0 process model for the HTTP server by removing the dependency on HTTP. This allows WCF services to use both HTTP and non-HTTP protocols, such as Net.TCP, in a hosting environment that supports message-based activation and offers the ability to host a large number of applications on a given machine.” ** (my bold)

WAS allows applications to be hosted in a more robust and manageable way:

  • Applications start and stop dynamically in response to incoming work items that arrive using HTTP and non-HTTP network protocols.
  • Process recycling to maintain the health of running applications.
  • Centralized application configuration and management.
  • Applications can take advantage of the IIS process model without a full IIS installation.
  • A single WAS server instance can be home to many different applications.
  • Applications are organised into groups called sites.
    • For the purposes of addressing and management.
    • Applications are also grouped together into application pools.
      • An application pool can house many different applications from many different sites.
      • Each application pool corresponds to an instance of a worker process (w3wp.exe).
  • Within a site, applications are arranged in a hierarchical manner
    • Reflects the structure of the URIs

 

* http://msdn.microsoft.com/en-us/library/ms730158.aspx
** http://msdn.microsoft.com/en-us/library/ms734677.aspx

Wednesday, 7 July 2010

Saturday, 3 July 2010

X.509 error when running simple WCF services

I was running through some tutorials and hit a problem when adding new endpoints to a WCF service. The Visual Studio service runner showed the following error:
System.InvalidOperationException: Cannot load the X.509 certificate identity specified in the configuration.
   at System.ServiceModel.Description.ConfigLoader.LoadIdentity(IdentityElement element)
   at System.ServiceModel.Description.ConfigLoader.LoadServiceDescription(ServiceHostBase host, ServiceDescription description, ServiceElement serviceElement, Action`1 addBaseAddress)
   at System.ServiceModel.ServiceHostBase.LoadConfigurationSectionInternal(ConfigLoader configLoader, ServiceDescription description, ServiceElement serviceSection)
   at System.ServiceModel.ServiceHostBase.LoadConfigurationSectionInternal(ConfigLoader configLoader, ServiceDescription description, String configurationName)
   at System.ServiceModel.ServiceHostBase.ApplyConfiguration()
   at System.ServiceModel.ServiceHostBase.InitializeDescription(UriSchemeKeyedCollection baseAddresses)
   at System.ServiceModel.ServiceHost.InitializeDescription(Type serviceType, UriSchemeKeyedCollection baseAddresses)
   at System.ServiceModel.ServiceHost..ctor(Type serviceType, Uri[] baseAddresses)
   at Microsoft.Tools.SvcHost.ServiceHostHelper.CreateServiceHost(Type type, ServiceKind kind)
   at Microsoft.Tools.SvcHost.ServiceHostHelper.OpenService(ServiceInfo info)
The problem lay in the App.config <identity> block of some of the newly added endpoints. Originally they looked something like this:
<identity>
    <certificatereference x509findtype="FindBySubjectDistinguishedName" storelocation="LocalMachine" storename="My" />
</identity>
Adding a <dns> element fixed the issue:
<identity>
    <dns value="localhost" />
    <certificatereference x509findtype="FindBySubjectDistinguishedName" storelocation="LocalMachine" storename="My" />
</identity>
The <dns> element is described as:
“Specifies the DNS of an X.509 certificate used to authenticate a service. This element contains an attribute value that is a string, and contains the actual identity.”
See the MSDN documentation:
Saturday, 3 July 2010