Dan Rigsby - Coding Up Style

.Net, C#, & Wcf Development

Archive for May, 2008

REST Services and Metadata Endpoints in WCF

Posted by Dan Rigsby on 29th May 2008

As mentioned in a previous article, there is no defined a way to get metadata about REST based services using webHttpBinding.  Since REST doesn’t use SOAP, there is no WSDL that defines the service and no built in way to generate metadata about it.  REST operations return back POX or JSON or something else. 

You can still create a mexHttpBinding endpoint which can be used to represent the structure of the data that the REST service understands.  You just cant really use this metadata to build a proxy client based on the REST interface. You don’t need any addition endpoints to expose the WSDL, having just a webHttpBinding endpoint is enough.  You just need to enable httpGet on the serviceMetadata (see here for more detailed information on this):

<serviceBehaviors>
    <behavior name="contactServiceBehavior">
        <serviceMetadata httpGetEnabled="true"/>
    </behavior>
</serviceBehaviors>

One common tactic to give the REST service some kind of documentation, is to have a "Documentation" or "Help" method on your service that returns a an HTML page as a Stream which describes how to work with the REST service (as seen in pictureservices).  This isn’t really metadata that can be consumed to generate a proxy class, but it is informative to other developers and consumers of your REST service.

Example

Lets look at an example of the "Documentation" method on a REST service.  This example is based on a simple contact service that holds a collection of contacts.  Some of the methods are AddContact, GetContact, UpdateContact, etc. The complete interface for the service is:

using System.Collections.Generic;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Syndication;
using System.ServiceModel.Web;

namespace Rigsby.RestDocumentation
{
    [ServiceContract]
    public interface IContactService
    {
        [OperationContract]
        [WebGet(UriTemplate = "help")]
        Stream GetDocumentation();

        [OperationContract]
        [WebGet(UriTemplate = "contacts")]
        List<Contact> GetAllContacts();

        [OperationContract]
        [WebGet(UriTemplate = "contacts/feed?format={format}",
            BodyStyle = WebMessageBodyStyle.Bare)]
        [ServiceKnownType(typeof(Atom10FeedFormatter))]
        [ServiceKnownType(typeof(Rss20FeedFormatter))]
        SyndicationFeedFormatter GetContactsFeed(string format);

        [OperationContract]
        [WebGet(UriTemplate = "contact/{contactId}")]
        Contact GetContact(string contactId);

        [OperationContract]
        [WebGet(UriTemplate = "contact/name/{name}")]
        List<Contact> GetContactByName(string name);

        [OperationContract]
        [WebGet(UriTemplate="contact/name/startswith/{startsWith}")]
        List<Contact> GetContactsWhereNameStartsWith(string startsWith);

        [OperationContract]
        [WebGet(UriTemplate = "contact/name/endsWith/{endsWith}")]
        List<Contact> GetContactsWhereNameEndsWith(string endsWith);

        [OperationContract]
        [WebGet(UriTemplate = "contact/name/contains/{contains}")]
        List<Contact> GetContactsWhereNameContains(string contains);

        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "contact/{name}")]
        void AddContact(string name);

        [OperationContract(Name = "AddFullContact")]
        [WebInvoke(Method = "POST", UriTemplate = "contact")]
        void AddContact(Contact contact);

        [OperationContract]
        [WebInvoke(Method="DELETE", UriTemplate = "contact/{contactId}")]
        int DeleteContact(string contactId);

        [OperationContract]
        [WebInvoke(Method = "PUT", UriTemplate = "contact/{contactId}")]
        void UpdateContact(string contactId, Contact contact);
    }
}

The operation to look at is "GetDocumentation".  This method returns a stream which will be the HTML of the documentation for the service.  The UriTemplate we are using is just "help", so the full path would just be something like "http://localhost:8080/ContactService/help".

[OperationContract]
[WebGet(UriTemplate = "help")]
Stream GetDocumentation();
 
The implementation of this is pretty straight forward.  We basically just create a new StreamWriter, write the contents of our HTML to it, set content type of the outgoing response to "text/html", and return the stream:
 
public Stream GetDocumentation()
{
    MemoryStream stream = new MemoryStream();

    StreamWriter writer = new StreamWriter(stream, Encoding.UTF8);
    writer.Write(Properties.Resources.Documentation);
    writer.Flush();
    stream.Position = 0;

    WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";

    return stream;
}
 
When a user navigates to "http://localhost:8080/ContactService/help", the following HTML page is displayed which documents how to use the REST interface:

restdoc

The HTML for this was manually hacked together, but you could write some process that looks at some custom attributes on the service to build this help file:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
<head>
    <title>Contact Service - Documentation</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <style type="text/css">
        body {margin: 0px;padding: 0px;font-family: Calibri, Tahoma, Arial;}
        .banner {padding: 5px 5px 5px 15px;background-color: Gray;color: White;}
        .content {margin: 15px;}
    </style>
</head>
<body>
    <div class="banner">
        <h1>Contact Service</h1>
    </div>
    <div class="content">
        <h2>Available Feeds</h2>
        <ul>
            <li><b>GET /contacts/feed?format={format}</b> &mdash; Returns a feed of all contacts as "rss" or "atom"</li>
        </ul>
        <h2>Available Endpoints</h2>
        <ul>
            <li><b>GET /help</b> &mdash; Displays the service documentation</li>
            <li><b>GET /contacts</b> &mdash; Returns all contacts</li>
            <li><b>GET /contact/{contactId}</b> &mdash; Returns a contact by contactId</li>
            <li><b>GET /contact/name/{name}</b> &mdash; Returns all contacts with the specified name</li>
            <li><b>GET /contact/name/startswith/{startswith}</b> &mdash; Returns all contacts whose name starts with the specified string</li>
            <li><b>GET /contact/name/endsWith/{endsWith}</b> &mdash; Returns all contacts whose name ends with the specified string</li>
            <li><b>GET /contact/name/contains/{contains}</b> &mdash; Returns all contacts whose name contains the specified string</li>

            <li><b>POST /contact/{name}</b> &mdash; Adds a new contact with the specified name (ignores POST data)</li>
            <li><b>POST /contact</b> &mdash; Adds a new contact with the POST data</li>
            <li><b>DELETE /contact/{contactId}</b> &mdash; Deletes a contact by contactId</li>
            <li><b>PUT /contact/{contactId}</b> &mdash; Updates a contact by contactId</li>
        </ul>
    </div>
</body>
</html>

You can download a complete sample of the code discussed in this article here: http://www.danrigsby.com/Files/Rigsby.RestDocumentation.zip

kick it on DotNetKicks.com

Posted in REST, Wcf | 9 Comments »

JavaScriptSerializer Undeprecated in .NET 3.5 SP1

Posted by Dan Rigsby on 28th May 2008

According to Scott Guthrie (see comments in this post) it appears that the JavaScriptSerializer will be undeprecated in .NET 3.5 SP1.  In was deprecated in .Net 3.5 and the DataContractJsonSerializer replaced it.  Each of these serializers serializes to Json and each have their pluses and minuses:

  • JavaScriptSerializer supports anonymous types.
  • JavaScriptSerializer works with plain strings so it can be easier to use.
  • DataContractJsonSerializer can serialize DateTimes into UTC format.   Very important over the web!

I guess the big question I have is, do we really need both? Isn’t there a way to combine these into one serializer?

What about the act of undeprecating a class?  Do you think this is a good thing?

See these links for more information about the DataContractJsonSerializer:

Posted in .Net | 2 Comments »

WCF Metadata

Posted by Dan Rigsby on 27th May 2008

The WCF team has gone to great lengths to ensure that it doesn’t tie itself down to a single service architecture or naming. This can be best demonstrated by how WCF refers to its metadata. Most users will think of this metadata as WSDL. And in WCF today, it is WSDL. However, what will WSDL be in 5 years? What happens when something better comes along? Or what if we want some metadata for REST which doesn’t use SOAP? Instead, it is just called Metadata.

So what is the this metadata?  Metadata is basically to describe how to interact with the service’s endpoints.  This includes metadata about:

  1. The operations a service can perform
  2. The structure of the data types that the operations work with or return
  3. Definitions of all the endpoints implemented by the service and the various options needed for each such as security

By default service metadata is turned off.  This has been a problem for some people because you have to manually configure the service to publish the metadata.  This is by design because metadata can expose parts of your service you don’t want to expose.  Many services out in the wild do not want to publish metadata at all.  Personally, I am a bit torn about this.  Part of me understands why they implemented it this way, but the more common use is to expose metadata always.  It seems that the default should be metadata on, with the option to turn metadata off for the more rare occasions.  However, the WCF team really wanted it to be "secure by default", which means it needed to be turned off.  This can throw off classic WebService developers because in ASMX you needed to opt-out of exposing metadata, while WCF requires opt-in of exposing metadata.

The metadata can be used to generate proxy classes with svcutil.exe, "Add Service Reference" in Visual Studio, wcftestclient.exe, or any other program that can interpret the metadata and build proxies.  This data can also by used to pull out specific information about a service such as its’ endpoints, or simply just for reference information about the service.

Exposing Metadata

To expose metadata you need to turn on the serviceMetaData property in the service behavior that the service is implementing.  This can be done declaratively through the xml config files, or programmatically directly in your code:

Declaratively

The minimum you need is to add the serviceMetaData node to the serviceBehavior being used by the service:

<serviceBehaviors>
  <behavior name = "MetadataBehavior">
    <serviceMetadata />
  </behavior>
</serviceBehaviors>
 
In a full configuration file this may look like something like this:
 
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name = "MetadataBehavior">
         <serviceMetadata httpGetEnabled = "true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name = "MyService"
               behaviorConfiguration = "MetadataBehavior">
        <host>
          <baseAddresses>
            <add baseAddress =
                 "http://localhost:8080/MyService"
                 "net.tcp://localhost:9000/MyService"/>
          </baseAddresses>
        </host>
        <endpoint address = ""
                  binding = "wsHttpBinding"
                  contract = "IMyService"/>
        <endpoint address = ""
                  binding = "netTcpBinding"
                  contract = "IMyService"/>
        <endpoint address = "net.tcp://localhost:9000/MyService/mex"
                  binding = "mexTcpBinding"
                  contract = "IMetadataExchange"/>
      </service>
    </services>
  </system.serviceModel>
</configuration>

Programmatically

Adding this in code is similar.  You need to add a ServiceMetadataBehavior object to the behaviors of the serviceHost:

ServiceHost host = new ServiceHost(
    typeof(MyService),
    new Uri("http://localhost:8080/MyService"),
    new Uri("net.tcp://localhost:9000/MyService"));

host.AddServiceEndpoint(
    typeof(IMyService),
    new WSHttpBinding(),
    "");
host.AddServiceEndpoint(
    typeof(IMyService),
    new NetTcpBinding(),
    "");
Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
host.AddServiceEndpoint(
    typeof(IMetadataExchange),
    mexBinding,
    "net.tcp://localhost:9000/MyService/mex");

ServiceMetadataBehavior metadataBehavior =
    new ServiceMetadataBehavior();
metadataBehavior.HttpGetEnabled = true;
host.Description.Behaviors.Add(metadataBehavior);

 

Enabling the serviceMetaData property is enough to expose metadata through all binding types except http and https.  For these you have to specify "HttpGetEnabled=true" or "HttpsGetEnabled=true" depending on if you are using http or https.  You must expose at least one endpoint for http or https and declare a base address or you will get a runtime exception with HttpGetEnabled or HttpsGetEnabled enabled.

Http and Https can expose metadata simply by appending "?wsdl" to the end of the base address.  For any binding type, you need to specify a metadata binding endpoint to retrieve the metadata from.  This is done by creating an endpoint that uses the IMetadataExchange interface, a corresponding "mex" binding for the transport (more on this later), and the address where the metadata published.  You can also use an IMetadataExchange address for http and https as well, but normally the "?wsdl" site is enough.

There are a few properties of ServiceMetadata:

  • ExternalMetadataLocation: A Uri that contains the location of a WSDL file, which is returned to the user in response to WSDL and MEX requests instead of the auto-generated WSDL. When this attribute is not set, the default WSDL is returned. The default is an empty string.
  • HttpGetEnabled: A Boolean value that specifies whether to publish service metadata for retrieval using an HTTP/Get request. The default is false. If the httpGetUrl attribute is not specified, the address at which the metadata is published is the service address plus a "?wsdl". For example, if the service address is "http://localhost:8080/MyService", the HTTP/Get metadata address is "http://localhost:8080/MyService?wsdl". If this property is false, or the address of the service is not based on HTTP or HTTPS, “?wsdl” is ignored.
  • HttpGetUrl: A Uri that specifies the address at which the metadata is published for retrieval using an HTTP/Get request.
  • HttpsGetEnabled: A Boolean value that specifies whether to publish service metadata for retrieval using an HTTPS/Get request. The default is false. If the httpsGetUrl attribute is not specified, the address at which the metadata is published is the service address plus a "?wsdl". For example, if the service address is https://localhost:8080/MyService, the HTTP/Get metadata address is "https://localhost:8080/MyService?wsdl". If this property is false, or the address of the service is not based on HTTP or HTTPS, “?wsdl” is ignored.
  • HttpsGetUrl: A Uri that specifies the address at which the metadata is published for retrieval using an HTTPS/Get request.

Metadata Exchange Endpoint

A metadata exchange endpoint is an endpoint that returns back the metadata about the service. You can have as many metadata exchange endpoints as you want. You could have one for each service endpoint, one that all endpoints share, or 100s that just return the same data.  Usually one metadata endpoint is sufficient, but it is common to see one for each service endpoint as well.

Like all endpoints it is comprised of the ABCs: Address, Binding, and Contract:

Address

The address is just the Uri that the endpoint can be can found.  In a metdata exchange endpoint this is commonly done by appending "mex" to the base address such as "net.tcp://localhost/MyService/mex", but you can use whatever address you choose.

Binding

There are only 4 bindings that are defined to be used as a metadata endpoint:

  1. mexHttpBinding: Specifies the settings for a binding used for the WS-MetadataExchange (WS-MEX) message exchange over HTTP.
  2. mexHttpsBinding: Specifies the settings for a binding used for the WS-MetadataExchange (WS-MEX) message exchange over HTTPS.
  3. mexNamedPipesBinding: Specifies the settings for a binding used for the WS-MetadataExchange (WS-MEX) message exchange over named pipe.
  4. mexTcpBinding: Specifies the settings for a binding used for the WS-MetadataExchange (WS-MEX) message exchange over TCP

You can use any of these in the configuration file to define metadata endpoints, such as:

<endpoint address = "net.tcp://localhost:9000/MyService/mex"
    binding = "mexTcpBinding"
    contract = "IMetadataExchange"/>

In code however, these bindings must be created through the static MetadataExchangeBindings class.  It has the following 4 methods:

You can use any of these methods in your code go generate the bindings for the corresponding transport, such as:

Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
host.AddServiceEndpoint(
    typeof(IMetadataExchange),
    mexBinding,
    "net.tcp://localhost:9000/MyService/mex");

Contract

A contract is just an interface that the endpoint must follow. So, what is this IMetadataExchange interface?  It only has 3 methods:

  • BeginGet: Starts an asynchronous retrieval of metadata.
  • EndGet: Concludes the retrieval of metadata.
  • Get: Returns the service metadata

Since BeginGet and EndGet are just an asynchronous version of Get, what does Get do?  Well, as you may have guessed, it just returns the metadata for the service.

REST and webHttpBinding

So what about REST based services using webHttpBinding?  No where is there defined a way to get metadata about it.  Well, since it is REST, there is no WSDL that defines the service and no built in way to generate metadata about it.  One common tactic is to have a "Documentation" method on your service that returns a stream of data that is an HTML page which describes how to work with the REST service.  This isn’t really metadata that can be consumed to generate a proxy class, but it is informative to other developers and consumers of your REST services.

kick it on DotNetKicks.com

Posted in Wcf | 4 Comments »

Remove Icon from WPF Window

Posted by Dan Rigsby on 26th May 2008

In general, a window should always have an icon because it helps give context to the window.  However, there are occasions when you may want a window with icon such as a custom tool window or some other dialog. In Windows Forms if you want a window without an icon, you could just simply set:
 
this.ShowIcon = false;
 
In WPF, there is no simple way to just remove the icon.  If you try to just set the Icon to null, it will display the default windows icon.  The only way to disable the icon is to use some interop code to remove the icon directly through the windows API:
 
using System;
using System.Windows;
using System.Windows.Interop;
using System.Runtime.InteropServices;

public partial class WindowWithoutIcon : Window
{
    [DllImport("user32.dll")]
    static extern int GetWindowLong(IntPtr hwnd, int index);

    [DllImport("user32.dll")]
    static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);

    [DllImport("user32.dll")]
    static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);

    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);

    const int GWL_EXSTYLE = -20;
    const int WS_EX_DLGMODALFRAME = 0×0001;
    const int SWP_NOSIZE = 0×0001;
    const int SWP_NOMOVE = 0×0002;
    const int SWP_NOZORDER = 0×0004;
    const int SWP_FRAMECHANGED = 0×0020;
    const uint WM_SETICON = 0×0080;

    public MainWindow()
    {
        InitializeComponent();
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);

        // Get this window’s handle
        IntPtr hwnd = new WindowInteropHelper(this).Handle;

        // Change the extended window style to not show a window icon
        int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
        SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);

        // Update the window’s non-client area to reflect the changes
        SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
    }
}
 
 

Posted in Common Libraries, WPF | 1 Comment »

Get the Service Endpoint address a Client is accessing in WCF

Posted by Dan Rigsby on 25th May 2008

In a previous post I talked about how to get the address of a client accessing a WCF service.  I got a few questions after this asking how you would get the endpoint address of the service that the client is accessing?  A single service could have multiple endpoints, and when a client comes into the service you may branch the logic slightly depending on how they are accessing the data.  For instance, you might have a separate endpoint that is exposed outside of your network for external customers, and may want to restrict the amount of data they can access through a method. Or maybe if the client is using “Http” you might want to return back less data than if the client is using “Tcp”.

Getting the service endpoint address is actually much easier then getting the address of the client.  You just need to look at the LocalAddress on the Channel of the current Operation Context in the method:

OperationContext.Current.Channel.LocalAddress

Here is an example of a method that branches its results based on the schema (http, tcp, etc) of the endpoint that a client is accessing:

public List<Customer> GetCustomers()
{
    var customers = new List<Customer>();

    if (OperationContext.Current.Channel.LocalAddress.Uri.Scheme == “http”)
    {
        // TODO: Get partial customer objects
    }
    else
    {
        // TODO: Get full customer objects
    }

    return customers;
}

Posted in Wcf | 2 Comments »

Extending WCF InstanceContext to store custom state

Posted by Dan Rigsby on 24th May 2008

InstanceContext in Wcf Series:
Part 1: Understanding InstanceContext
Part 2: Extending InstanceContext to store custom state

This is Part 2 in a series on InstanceContexts.  You might want to read Part 1: Understanding InstanceContext in WCF before continuing on with this post.

Like most things in WCF, there are a few ways to extend an InstanceContext:

  1. IExtension<InstanceContext>: This interface is used to create objects that can be attached to the InstanceContext through the Extensions property.  These objects can store additional state information or behaviors.  This works off the standard extensible object pattern is used in WCF to either extend existing run-time classes with new functionality or to add new state features to an object.
  2. IInstanceContextProvider: Implement to participate in the creation or choosing of a InstanceContext, especially to enable shared sessions.
  3. IInstanceContextInitializer: Defines the methods necessary to inspect or modify the creation of InstanceContext objects when required. This is typically added to attach an IExtension<InstanceContext> to the InstanceContext object as a mechanism for passing data throughout an application.

Lets look at an example that implements some of these extension mechanisms to store additional state information with the InstanceContext.  For this sample, I want some extension that allows me to store the DateTime that an instance of the service was created and what is the creation index count of this instance.  The goal is to just be able to add an Attribute to the service and have it automatically store these values in the InstanceContext. To do this I need an IExtension that defines the values I want to store, an IInstanceContextProvider that adds the IExtension to the service instance when it is created, and an Attribute that implements IContractBehavior that we can use on the service.

1. IExtension<InstanceContext>

The IExtension interface is part of the extensible object pattern is used in WCF to either extend existing run-time classes with new functionality or to add new state features to an object. Since InstanceContext derives from IExtensibleObject, we can add these extension controls to it in order to provide more state information with the InstanceContext.  This interface defines 2 methods:

  1. void Attach(T owner): Enables an extension object to find out when it has been aggregated. Called when the extension is added to the IExtensibleObject<T>Extensions property.
  2. void Detach(T owner): Enables an object to find out when it is no longer aggregated. Called when an extension is removed from the IExtensibleObject<T>Extensions property.

In this example we are only using the extension to hold data and do not care what happens when it is attached or detached from the owner.  So we only need to define the two properties we want to track:

[DataContract]
public class InstanceCreationExtension :
    IExtension<InstanceContext>
{
    private int m_InstanceCreationIndex;
    private DateTime m_InstanceCreated;

    [DataMember]
    public int InstanceCreationIndex
    {
        get { return m_InstanceCreationIndex; }
    }

    [DataMember]
    public DateTime InstanceCreated
    {
        get { return m_InstanceCreated; }
    }

    public InstanceCreationExtension(
        int instanceCreationIndex,
        DateTime instanceCreated)
    {
        m_InstanceCreationIndex = instanceCreationIndex;
        m_InstanceCreated = instanceCreated;
    }

    public override string ToString()
    {
        return String.Format(“Creation Index {0}, Created: ‘{1}’”,
            m_InstanceCreationIndex,
            m_InstanceCreated);
    }

    public void Attach(
        InstanceContext owner)
    {
    }

    public void Detach(
        InstanceContext owner)
    {
    }
}

2. IInstanceContextInitializer

The IInstanceContextInitializer interfacedDefines the methods necessary to inspect or modify the creation of InstanceContext objects.  When an InstanceContext is created, this interface can be used to perform additional operations on it through the Initialize method.  In our example, we want to add a our custom IExtension object to the Extensions collection when the InstanceContext is created:

public class InstanceCreationInitializer :
    IInstanceContextInitializer
{
    private static int m_InstanceCreationIndex = 0;

    public void Initialize(
        InstanceContext instanceContext,
        Message message)
    {
        // Increment instance creation index (thread safe)
        System.Threading.Interlocked.Increment(
            ref m_InstanceCreationIndex);

        // Add extension which contains the new instance creation index
        instanceContext.Extensions.Add(
            new InstanceCreationExtension(
                m_InstanceCreationIndex,
                DateTime.Now));
    }
}

3. IContractBehavior Attribute

Now that we have defined an object to store our data and a way to populate it, we have to wire up our custom IInstanceContextInitializer so that it can do its job.  There are a few ways to do this, but perhaps the easiest way is to create a custom attribute that can be added to the service which wires it up.  To do this, we just need to extend the IContractBehavior interface. This interface defines the methods that can be used to extend run-time behavior for a contract in either a service or client application.  For this example, we only need to modify the dispatch behavior that is used or the service.  In this method we are going to added our custom IInstanceContextInilializer to the InstanceContextInitializers collection on the DispatchRuntime.  This basically means that when this attribute is applied to a service, then every time an instance is created, it will call the custom IInstanceContextInilializer that we have defined.

public class InstanceCreationAttribute :
    Attribute, IContractBehavior
{
    public void AddBindingParameters(
        ContractDescription contractDescription,
        ServiceEndpoint endpoint,
        BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(
        ContractDescription contractDescription,
        ServiceEndpoint endpoint,
        ClientRuntime clientRuntime)
    {
    }

    public void ApplyDispatchBehavior(
        ContractDescription contractDescription,
        ServiceEndpoint endpoint,
        DispatchRuntime dispatchRuntime)
    {
        dispatchRuntime.InstanceContextInitializers.Add(
            new InstanceCreationInitializer());
    }

    public void Validate(
        ContractDescription contractDescription,
        ServiceEndpoint endpoint)
    {
    }
}

Contract

We now have all of the customizations we need defined.  Now we can see how it is applied to a service.  For this example, we can define a contract with a single method that returns a string which will show us the service instance creation count and the DateTime in which the service was created:

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    string GetInstanceDescription();
}

Service

The service is pretty straight forward.  The implementation of the GetInstanceDescription method just pulls our custom IExtension from the Extensions collection of the current InstanceContext that the operation is running on.  Notice that we have set the InstanceContextMode to PerCall.  This means that every time we call a method a new instance of a service will be created.  So this method should return a unique string every time.  (You can change this to PerSession and Single to see different results.)

The real magic that gets our example working is the [InstanceCreation] attribute we defined on the service.  This is the custom IContractBehavior attribute that will inject our custom IInstanceContextInitializer and add our custom IExtension object to the InstanceContext.

[ServiceBehavior(
    InstanceContextMode=InstanceContextMode.PerCall)]
[InstanceCreation]
public class MyService : IMyService
{
    public string GetInstanceDescription()
    {
        InstanceContext ic = OperationContext.Current.InstanceContext;

        InstanceCreationExtension extension =
            ic.Extensions.Find<InstanceCreationExtension>();

        return extension.ToString();
    }
}

Example Client

In this sample client we are going to just call the method on the service and display a MessageBox with data from the InstanceContext on the service.  Since we have the service InstanceContextMode set as PerCall, this message will be different each time you click the button on the form.

public partial class ClientForm : Form
{
    IMyService m_Client;

    public ClientForm()
    {
        InitializeComponent();

        ChannelFactory<IMyService> channeFactory =
            new ChannelFactory<IMyService>(“NetTcpBinding_IMyService”);
        m_Client = channeFactory.CreateChannel();
    }

    private void m_AddNameButton_Click(object sender, EventArgs e)
    {
        MessageBox.Show(m_Client.GetInstanceDescription());
    }
}

 

You can use this sample to add any type of information you want to each instance of a service.  This is most useful if you are using PerCall or PerSession InstanceContextMode.  You could have done some of these operations in the service constructor, but this type of extension allows you to bury this logic into a reusable component and access data that may not normally have access to.

You can download a complete sample of the code discussed in this article here: http://www.danrigsby.com/Files/Rigsby.Rigsby.WcfServiceContexts.zip

 

kick it on DotNetKicks.com

Posted in Wcf | 5 Comments »

Understanding InstanceContext in WCF

Posted by Dan Rigsby on 23rd May 2008

InstanceContext in Wcf Series:
Part 1: Understanding InstanceContext
Part 2: Extending InstanceContext to store custom state

InstanceContext in WCF seems to be somewhat misunderstood.  I have seen a number of questions on MSDN Forums asking what this is or how it is used.  Conceptually it just represents the running instance of the service. Often times it is helpful to think of InstanceContext along with OperationContext. This is the transverse of OperationContext which is the instance of the client accessing the service.  From the service you can access the OperationContext of the client by simply looking at System.ServiceModel.OperationContext.Current.  This object has reference to the InstanceContext of the service it is accessing.  The InstanceContext derives from CommunicationObject

Methods to Note

  1. IncrementManualFlowControlLimit: Increases the number of messages that can be processed by the service instance by a specified about.  This method returns the new limit on the number of messages, after the number to increase by has been added.
  2. GetServiceInstance: Returns the instance of the service, or creates a new instance of the service if the service doesn’t exits or has been released.
  3. ReleaseServiceInstance:  Releases the service instance.

When ReleaseServiceInstance is called the runtime will disassociate the instance from the InstanceContext and call dispose (is IDisposable is implemented) on the instance. A new instance of the service will be created when a new message arrives of if GetServiceInstance is called. (see here Mahjayar’s Weblog for more details)

Properties to note

  1. State: (Derived from CommunicationObject.) Gets a value that indicates the current state of the communication object.
    1. Created: Indicates that the communication object has been instantiated and is configurable, but not yet open or ready for use
    2. Opening: Indicates that the communication object is being transitioned from the Created state to the Opened state.
    3. Opened: Indicates that the communication object is now open and ready to be used.
    4. Closing: Indicates that the communication object is transitioning to the Closed state.
    5. Closed: Indicates that the communication object has been closed and is no longer usable.
    6. Faulted: Indicates that the communication object has encountered an error or fault from which it cannot recover and from which it is no longer usable.
  2. Extensions: Gets the collection of extensions associated with the service instance.  These extensions would be classes derived from IExtension<InstanceContext>
  3. ManualFlowControlLimit: Gets or sets a limit on the number of messages that can be processed by the instance context.
  4. SynchronizationContext: Gets or sets the context used for thread synchronization with the current instance context.
  5. IncomingChannels: Gets the sessionful channels that are incoming to the service instance.
  6. OutgoingChannels: Gets the sessionful channels that are outgoing from the service instance.

InstanceContextMode

In the ServiceBehaviorAttribute you can set the InstanceContextMode of the service.  This property defines how new service objects are created.  There are three options here:

  1. PerSession: A new InstanceContext object is created for each session.  This means a new instance of the service itself is created for every unique client connection. If the channel does not create a session this value behaves as if it were PerCall.
  2. PerCall: A new InstanceContext object is created prior to and recycled subsequent to each call.   So a new instance of the service is created for every call even if the calls are coming from the same client.
  3. Single: Only one InstanceContext object is used for all incoming calls and is not recycled subsequent to the calls. If a service object does not exist, one is created.

The default option is PerSession, but if you aren’t using a binding that allows sessions, then the behavior will be like that of PerCall. (See here for a list of bindings that support or don’t support sessions).

Here is an example of setting context mode on a server:

[ServiceBehavior(
    InstanceContextMode = InstanceContextMode.Single)]
public class MyService : IMyService
{
    …
}

Technically whenever the user calls InstanceContext.ReleaseServiceInstance() the runtime will disassociate the instance from the InstanceContext and call dispose (If the instance inherits from IDisposable) on the instance. A new instance will be created when a new message arrives for that endpoint or the user explicitly calls InstanceContext.GetServiceInstance().

Accessing the Instance of a service a client is running on

You might want to access the InstanceContext that a client is running against.  These instances can be different since a new instance could be created PerSession or PerCall.  To access this InstanceContext, you can look at it directly in the current OperationContext:

InstanceContext ic = OperationContext.Current.InstanceContext;

Obtain a unique Id for an InstanceContext

Since each InstanceContext is unique, you can call GetHashCode() on the InstanceContext to get a unique identifier for the InstanceContext.  If you are using PerSession this may be important to ensure that the session is the same:

int serviceInstanceId =
    OperationContext.Current.InstanceContext.GetHashCode();

When might you create your own instance of InstanceContext?

The most common use for this is when using Duplexing.  In a Duplex system, the service can callback to the client via a CallbackContract.  This CallbackContract is much like a service on the client side that is listening for calls from the service on the channel that the client has opened.  This “client callback service” can only be accessed via the same channel it used on the service and therefore only that service has access to it.  In order to create the connection to the duplexed service you must specify an InstanceContext like so:

// “this” represents an object that implements the callback contract IMyDuplexServiceCallback
InstanceContext ic = new InstanceContext(this);
var m_ChannelFactory = new DuplexChannelFactory<IMyDuplexService>(ic);

Basically what we have done here is created a standard connection to the server, and gave it an object (InstanceContext) that represents the “client callback service”.

On the service you can access the “client callback service” via the GetCallbackChannel method like so:

IMyServiceCallback callback =
    OperationContext.Current.GetCallbackChannel<IMyServiceCallback>()

Extending InstanceContext

Like most things in WCF, there are a few ways to extend an InstanceContext:

  1. IExtension<InstanceContext>: This interface is used to create objects that can be attached to the InstanceContext through the Extensions property.  These objects can store additional state information or behaviors.  This works off the standard extensible object pattern is used in WCF to either extend existing run-time classes with new functionality or to add new state features to an object.
  2. IInstanceContextProvider: Implement to participate in the creation or choosing of a InstanceContext, especially to enable shared sessions.
  3. IInstanceContextInitializer: Defines the methods necessary to inspect or modify the creation of InstanceContext objects when required. This is typically added to attach an IExtension<InstanceContext> to the InstanceContext object as a mechanism for passing data throughout an application.

Look for a second part of this post that will explain extending the InstanceContext in more detail.

kick it on DotNetKicks.com

Posted in Wcf | 2 Comments »

XNA Game Studio 3.0 CTP, no 64-Bit support (yet)

Posted by Dan Rigsby on 22nd May 2008

As a Zune owner I have been quite excited to get my hands on XNA Game Studio 3.0 CTP.  I am excited about not only being about to develop games, but also applications for my Zune (see this post about XNA for the Zune).  So, I eagerly downloaded the setup, ran the install, and all was well, until I went into the “XNA Game Studio Device Center” to add my Zune device:

xna

After clicking “Next” I was greeted with the following error:

System.IO.FileNotFoundException: Unable to find the specified file.
   at Microsoft.Xna.GameStudio.DeviceManagement.UnsafeNativeMethods.AcquireZuneTransport()
   at Microsoft.Xna.GameStudio.DeviceManagement.ZuneDeviceInfo.GetAllConnectedDevices()
   at Microsoft.Xna.GameStudio.DeviceManagement.UI.ZuneNamePage.SetCurrentPage()
   at Microsoft.Xna.GameStudio.DeviceManagement.UI.AddDeviceWizard.Proceed()
   at Microsoft.Xna.GameStudio.DeviceManagement.UI.ZuneWarningPage.SetCurrentPage()
   at System.Windows.Forms.Control.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

After a bit of digging around, I discovered that this exception is caused because there is no support for 64-bit operating systems in XNA Game Studio 3.0 yet.  Unfortunately, all of my PCs right now are 64-bit Vista to take advantage of >3.5 gig of ram and to test applications in 64-bit mode.  So, I will have to attempt to run this in a Virtual PC and hope I have better luck.

To save you some frustration, there are a few other things to note about this version of the CTP:

  • You must be running Visual Studio 2008 Standard Edition or higher or Visual C# 2008 Express Edition.  Those of you running Visual Studio 2005 are out of luck for now.
  • No game development for XBox 360 yet.  This CTP was released for working with the Zune.  Perhaps more CTPs will come out over time.
  • No support for 64-bit operating systems.  They should have support for this by RTM though (I hope).

Posted in XNA, Zune | 3 Comments »

Get the Client’s Address in WCF

Posted by Dan Rigsby on 21st May 2008

In .Net 3.0 there was not a reliable way to obtain the address of the client connecting to a WCF service.  In .Net 3.5 a new property was introduced called RemoteEndpointMessageProperty.  This property gives you the IP address and port that the client connection came into the service on. Obtaining the this information is pretty straight forward.  Just pull it from the IncomingMessageProperties of the current OperationContext by the RemoteEndpointMessageProperty.Name and access the Address and Port properties.

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    string GetAddressAsString();
}

public class MyService : IMyService
{
    public string GetAddressAsString()
    {
        RemoteEndpointMessageProperty clientEndpoint =
            OperationContext.Current.IncomingMessageProperties[
            RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;

        return String.Format(
            “{0}:{1}”,
            clientEndpoint.Address, clientEndpoint.Port);
    }
}

Things to note:

  1. This property only works on http and tcp transports.  On all other transports such as MSMQ and NamedPipes, this property will not be available.
  2. The address and port are reported by the socket or http.sys of the service’s machine.  So if the client came in over a VPN or some other proxy that modified the address, that new address will be represented instead of the client’s local address.  This is desirable and important because this is the address and port that the service sees the client as, not as the client sees itself as.  This also means that there could be some spoofing going on.  A client or something in between the client and server could spoof an address. So, do not use the address or port for any security decisions unless you add in some other custom checking mechanisms.
  3. If you are using duplexing on your service, then not only will the service have this property populated for the client, but the client will also have this property populated for the service for each call from that service.

You can download a sample service using this code here: http://www.danrigsby.com/Files/Rigsby.WcfClientAddress.zip

Posted in Wcf | 2 Comments »

Margins and Padding in WPF

Posted by Dan Rigsby on 20th May 2008

Margins and padding WPF work much like margins and padding other paradigms such as windows forms or CSS.  Margins give you space outside of the control, and padding gives you space inside the control.  The amount of spacing is set by the number of pixels you want to represent.

boxdim

Note: The padding always occurs inside the border. So if you have a border of 2 and padding of 10, the actual content of the control will be 12 pixels in.

In WPF, when you represent the spacing for these, you can set the values in line.  For instance, if you want to place a 2 pixel margin around a control you could write it as Margin=”2″, Margin=”2, 2, 2, 2″, or Margin=”2 2 2 2″.  This is very similar to CSS, but there is a big difference.  In CSS, the values represent “Top, Right, Bottom, Left”, but in WPF, the values represent”Left, Top, Right, Bottom”.  Why did WPF break the mold on this one?   Even if the order made more sense (which it doesn’t), I still can’t agree with this change.  CSS is a standard and has set a precedence.  Designers and developers who are using WPF have probably worked with CSS in some context.  This is going to throw a lot of people off.  Especially if the are going back and forth between CSS and WPF. What about developers who are writing silverlight controls as well as the web pages that contains them?

ClockThe CSS format makes sense. What time is represented by the clock to the right?  With no numbers visible, your eyes will probably start at the top (in the 12 position) and move around in clockwise motion to interpret each number.  Our minds have been trained to look at the top and work around clockwise.  There are exceptions to this, but it is a pattern that makes sense, and one that the CSS guys though was important enough to use in the order of sides. 

Its too late to change WPF now, but I would really like to know what the rational behind this was.  Maybe they chose to start with the Left side because we read Right to Left in most Western cultures.  However, many cultures read Right to Left or Top to Bottom or some other format.  It’s not a reliable paradigm to be based on.

Posted in WPF | 8 Comments »