Archive

Archive for January, 2011

Retrieving the client certificate from an X509Identity in WCF

January 28, 2011 2 comments

Please note: This article is merely a demonstration, I absolutely do not recommend relying on internal classes of the .Net framework in real applications.

WCF can be configured for two mayor modes of security:

  • Transport security
  • Message security
  • (And you actually also have the in between TransportWithMessageCredential, but lets forget this for simplicity …)

In both of these modes WCF can be configured to use X509 certificates as client and service credentials. At the service side, WCF maps these credentials to an IIdentity instance that can be retrieved using the ServiceSecurityContext.

IIdentity identity = ServiceSecurityContext.Current.PrimaryIdentity;

The implementation type of this identity is the internal class  System.IdentityModel.Claims.X509Identity. If we look at this type using reflector we can see the following:

Inspect X509Identity using Reflector

The X509Identity contains the X509 client certificate inside a private variable “certificate”. Using reflection, we can easily retrieve this certificate:

private X509Certificate2 ClientCertificate
{
    get
    {
        try
        {
            IIdentity identity = ServiceSecurityContext.Current.PrimaryIdentity;

            // X509Identity is an internal class, so we cannot directly access it
            Type x509IdentityType = identity.GetType();

            // The certificate is stored inside a private field of this class
            FieldInfo certificateField = x509IdentityType.GetField("certificate", BindingFlags.Instance | BindingFlags.NonPublic);

            return (X509Certificate2)certificateField.GetValue(identity);
        }
        catch (Exception)
        {
            return null;
        }
    }
}

Using this property we can now retrieve the client certificate. This was not that difficult to do? Glimlach

Categories: Advanced, C#, WCF

A few tips when you want to develop a WCF service with streamed transfer mode

January 25, 2011 1 comment

This weekend I tried to develop a WCF service that uses the streamed transfer mode. Configuring this is very easy; you only have the change the “transferMode” property of the binding to Streamed (or StreamedResponse or StreamedRequest)

<system.serviceModel>
  <services>
    <service name="StreamingService.Upload">
      <endpoint address=""
                binding="basicHttpBinding"
                bindingConfiguration="streamingBinding"
                contract="StreamingService.IUpload"/>
    </service>
  </services>

  <bindings>
    <basicHttpBinding>
      <binding name="streamingBinding"
                transferMode="Streamed"/>
    </basicHttpBinding>
  </bindings>
</system.serviceModel>

Simple and straightforward, but while doing this I discovered a few attention points:

  • If want to use a http binding, you can only use the basicHttpBinding as the wsHttpBinding does not support the “transferMode” property.
  • If you want to test this. You cannot run this using the integrated web server of Visual Studio 2010. I continuously received bad request error messages “ProtocolException: The remote server returned an unexpected response: (400) Bad Request.”. It was only after I switched to IIS that my service worked.
  • The “transferMode” property is not part of the metadata for http bindings, so in case you do “Add Service Reference” in Visual Studio, you have to manually edit the app.config of web.config of your client application.

Not a big blog article this time, but I hope that you find it helpful. 🙂

Categories: C#, WCF

Using the WCF service moniker with the WSDL of a service

January 8, 2011 8 comments

Introduction

In a previous article I wrote about the WCF service moniker. This COM component allows legacy applications to communicate with their new .Net based siblings. In the previous article, I explained two of the three ways to use the WCF service moniker. In this article, I will explain you the third way: using a locally cached WSDL description of the web service. Using the locally cached WSDL has advantages; you don’t need to create a class library for your WCF service and it does not need to expose meta data. Not exposing meta data is in enterprise environments often required to increase the security of the service.

The demo WCF service

First we are going to create the same simple demo service as in my previous WCF moniker article. So start Visual Studio and create a new “WCF Service Application”.

image

Inside the project we create the following service contract:

[ServiceContract]
public interface IHelloName
{
 	[OperationContract]
	string Hello(string name);
}

We implement the service as follows:

public class HelloName : IHelloName
{
	public string Hello(string name)
	{
		return "Hello " + name;
	}
}

The configuration for our service is the following (enter this in your web.config):

<system.serviceModel>
  <services>
    <service behaviorConfiguration="serviceBehavior"
              name="HelloNameService.HelloName">
      <endpoint binding="basicHttpBinding"
                contract="HelloNameService.IHelloName" />

      <endpoint address="mex"
                binding="mexHttpBinding"
                contract="IMetadataExchange" />
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="serviceBehavior">
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="false" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

We are now done with our WCF service, so you can press F5 to start the WCF service.

service page in internet explorer

Retrieving the WSDL

Before using the WCF service moniker, lets first look at the WSDL exposed by the WCF service. In order to do this, open your browser and enter the url “http://localhost:49170/HelloName.svc?wsdl”.

Please note that this URL will be probably be different on your system.

WSDL import

The first thing to notice is that the WSDL document is importing other documents. Because we want to call our web service by using a single file saved on disk, this behavior is not feasible. Luckily we were not the first .Net developers that wanted to have a “flat” WSDL. Other programming languages with less advanced web service stacks were having problems with this aspect of the WSDL generated by WCF, so Tomas Restrepo and Cristian Weyers came up with an alternative ServiceHostFactory that modifies the WCF stack to expose a flat WSDL. You can find this extension called “Flat WSDL” at http://www.thinktecture.com/media/9297/flatwsdl.zip

Download it and add the class library “Thinktecture.ServiceModel.Extensions.Description.dll” as a reference to our WCF service project. We can now modify the svc file of our service to change the ServiceHostFactory that IIS or WAS will be using. To do this provide the value “Thinktecture.ServiceModel.Extensions.Description.FlatWsdlServiceHostFactory” for the “Factory” property.

change of the factory voor een svc file detailed

If you now relaunch the WCF service and open the WSDL again, you will see that is has been “flattened”; it does not import any documents anymore. Save the WSDL to a file on your hard disk (I chose the path “c:\temp\IHelloName.wsdl”).

WSDL in internet explorer flattened

Creating the client application

For this demo, we are going to create a client application in VBA and Excel, but you can use the WCF service moniker from within every programming technology that supports COM.

Enter the following code in the VBA editor of Excel:

Sub ServiceMonikerCallWSDL()
    Dim service As Object
    Dim monString As String

    Const ForReading = 1
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFile = objFSO.OpenTextFile("c:\temp\IHelloName.wsdl", ForReading, False, TristateTrue)
    wsdlContract = objFile.ReadAll
    objFile.Close

    On Error GoTo Exception:

    monString = "service4:address='http://localhost:49170/HelloName.svc'" & _
                ", wsdl='" & wsdlContract & "'" & _
                ", binding=BasicHttpBinding_IHelloName, bindingNamespace=http://tempuri.org/" & _
                ", contract=IHelloName, contractNamespace=http://tempuri.org/"

    Set service = GetObject(monString)

    MsgBox (service.Hello("Excel WSDL"))

    Exit Sub

Exception:
    MsgBox Err.Description
End Sub

Remark: don’t forget to change the address of the service and the path of the WSDL file to the correct ones for your computer.

Before executing this code, we will first disable the publishing of metadata to prove that we can call the WCF service without using its exposed meta data. We can also remove the custom ServiceHostFactory in the svc file.

disable meta data detailed

If we now restart the WCF service and execute the VBA code in Excel we get the following response:

Hello excel from wsdl

Conclusion

As shown in this article, the WCF service moniker can relatively simple be used in combination with the WSDL of the service. This has the advantage that we can disable meta data publishing for services running in production and still be able to call it with the WCF service moniker. If you want to use this mode, don’t forget to ‘flatten’ the WSDL.

Categories: C#, WCF

Extension method fun 2

January 2, 2011 1 comment

Sometimes it is required to shuffle the elements of a collection. I have seen little algorithm monsters that did this, yet it can be done in c# and .Net in a very clean way using a Linq query. The key to understand my Linq query, is knowing that the orderby expression does not necessarily has to order the elements of your query.

public static class EnumerableExtensions
{
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> enumerable)
    {
         return from i in enumerable
                orderby Guid.NewGuid()
                select i;
     }
}

A small test application:

static void Main(string[] args)
{
    List<string> inputData = new List<string>() { "pieter", "bill", "steve" };
    IEnumerable<string> shuffledData = inputData.Shuffle();

    foreach (string item in shuffledData)
        Console.WriteLine(item);
}
Categories: C#, Linq