<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://www.alexthissen.nl/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Alex Thissen Weblog Build 1.15.10.1971</title><subtitle type="html">Disassembling my brain</subtitle><id>http://www.alexthissen.nl/blogs/main/atom.aspx</id><link rel="alternate" type="text/html" href="http://www.alexthissen.nl/blogs/main/default.aspx" /><link rel="self" type="application/atom+xml" href="http://www.alexthissen.nl/blogs/main/atom.aspx" /><generator uri="http://communityserver.org" version="4.1.31106.3070">Community Server</generator><updated>2009-03-18T11:00:37Z</updated><entry><title>WCF Extensibility part 5: Make your endpoints behave</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/08/25/wcf-extensibility-part-5-make-your-endpoints-behave.aspx" /><id>/blogs/main/archive/2009/08/25/wcf-extensibility-part-5-make-your-endpoints-behave.aspx</id><published>2009-08-25T06:36:00Z</published><updated>2009-08-25T06:36:00Z</updated><content type="html">&lt;p&gt;In the previous post we looked at an operation behavior that applied the operation formatter to a particular operation description. Because this is default behavior for all operations in the interface defined, we will make life a little easier on us to have the operation behaviors applied automatically. A WCF endpoint consists of address, binding and contract. The latter is represented by the [ServiceContract] annotated interface, in our case IRcon and the target of our exercise. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_7BAA35EC.png"&gt;&lt;img height="252" width="670" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_33C8616B.png" alt="image" border="0" title="image" style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;The extensibility point that the WCF runtime provides is an endpoint behavior. Endpoint behaviors allow you to manipulate an endpoint&amp;rsquo;s definition. To create an endpoint behavior you need to implement the System.ServiceModel.Description.IEndpointBehavior interface:&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:ae19c08b-4e08-41e0-8b3a-0e5d1324c144" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;public interface IEndpointBehavior
{
    void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters);
    void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime);
    void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher);
    void Validate(ServiceEndpoint endpoint);
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This should look pretty familiar to you if you have read the previous part in this series. Again, you can apply your behavior both on the client and service side. There&amp;rsquo;s another validation moment in the Validate method and you can add binding parameters to the binding context for later use.&lt;/p&gt;
&lt;p&gt;The implementation of ApplyClientBehavior is the most interesting one. Here we will apply the operation behavior to each of the endpoint&amp;rsquo;s operations.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:37b23b2a-92e9-4fa0-9453-7312ea3ebd23" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
    if (endpoint.Binding is SourceRconTcpBinding)
    {
        foreach (OperationDescription description in endpoint.Contract.Operations)
        {
            ApplyFormatterBehavior(description, endpoint);
        }
    }
}

private void ApplyFormatterBehavior(OperationDescription operationDescription, ServiceEndpoint endpoint)
{
    if (operationDescription.Behaviors.Find&amp;lt;SourceRconOperationFormatterBehavior&amp;gt;() == null)
    {
        SourceRconOperationFormatterBehavior formatterBehavior = new SourceRconOperationFormatterBehavior();
        operationDescription.Behaviors.Add(formatterBehavior);
    }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Inside the implementation a simple loop over the operation descriptions in the contract is enough to get things going. The helper method ApplyFormatterBehavior makes sure that the SourceRconOperationFormatterBehavior behavior is applied only once.&lt;/p&gt;
&lt;p&gt;An endpoint behavior needs to be added to the Behaviors collection of an endpoint to make it do its work. Given the client-side interface definition IRconProxy (which derives from both IRcon and IClientChannel) you can create a channel factory. The factory holds the the definition of the endpoint, provided by the implicit ABC in line 1 (address and binding are obvious, the generic &amp;lt;T&amp;gt; of the ChannelFactory represents the contract).&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:c14be624-47f4-419f-9b12-ff7e0a4b7f16" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;ChannelFactory&amp;lt;IRconProxy&amp;gt; factory = new ChannelFactory&amp;lt;IRconProxy&amp;gt;(binding, new EndpointAddress(uri));
factory.Endpoint.Behaviors.Add(new SourceRconEndpointBehavior());
factory.Open();&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Line 2 adds the behavior to the Behaviors collection of the endpoint. When the factory opens, the behavior gets applied. The operation formatters get applied at that moment as well. The operation formatters are used when the actual calls through the channel are made.&lt;/p&gt;
&lt;p&gt;Side note: if you were to use a ClientBase&amp;lt;T&amp;gt; derived proxy, you would need to drill down into the proxy.ChannelFactory.Endpoint.Behaviors to get at the Behaviors collection, or use the proxy.Endpoint property for easier access.&lt;/p&gt;
&lt;p&gt;To summarize, an endpoint behavior allows you to manipulate your endpoint. Behaviors are an opt-in, so it is your choice whether to apply them or not. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22532" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author><category term="Gaming" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Gaming/default.aspx" /><category term="Protocols" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Protocols/default.aspx" /><category term=".NET FX 3.5 SP1" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx" /><category term="WCF" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/WCF/default.aspx" /></entry><entry><title>WCF Extensibility part 4: Applying formatting to operations</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/08/21/wcf-extensibility-part-4-applying-formatting-to-operations.aspx" /><id>/blogs/main/archive/2009/08/21/wcf-extensibility-part-4-applying-formatting-to-operations.aspx</id><published>2009-08-21T20:11:00Z</published><updated>2009-08-21T20:11:00Z</updated><content type="html">&lt;p&gt;In the previous part we inspected the way you can influence the transition from a service operation to a WCF Message object. This was accomplished with an implementation of the IClientMessageFormatter interface, in our case the SourceRconOperationFormatter class. Now it&amp;rsquo;s time to look at how to apply this message formatter to the client channel stack.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_65ADA55C.png"&gt;&lt;img height="254" width="673" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_3CC29053.png" alt="image" border="0" title="image" style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;The message formatting happens based on the formatter that is specified as part of the description of an operation. This means that in theory you could change the formatter from operation to operation. In order to get the formatter in place you need to change the Formatter property of the System.ServiceModel.Description.OperationDescription for the operation of your choice. Obviously this has to be done before the first method call is made. The extensibility point that allows you define which formatters are used for client and service operations is an operation behavior. When applied an operation behavior will influence the way an operation behaves when called. Hence the name.&lt;/p&gt;
&lt;p&gt;Operation behaviors must implement the System.ServiceModel.Decription.IOperationBehavior interface. First of all look at that interface definition:&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:aa86fa62-127d-4f19-8cf2-bc4ed09015de" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;public interface IOperationBehavior
{
    void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters);
    void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation);
    void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation);
    void Validate(OperationDescription operationDescription);
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As you can see it has two methods to apply the specifics of your behavior to an operation description: one for client-side and one for service-side operations. We need to fill in the client-side proxy part of it only. Furthermore, the behavior can validate the operation to which it is applied. More on this in a moment. And finally, should the behavior need to add specific parameters to the entire binding (which can be accessed later on from the binding context) it is free to do so in the AddBindingParameters method.&lt;/p&gt;
&lt;p&gt;The SourceRconOperationFormatterBehavior class explicitly implements the IOperationBehavior interface. There is no point to have public method as it is unlikely that the implementation will be called other than via the interface.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:cdfeef7d-2528-46b2-89ee-4f49a38deb2b" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;public class SourceRconOperationFormatterBehavior: IOperationBehavior
{
    #region IOperationBehavior Members

    void IOperationBehavior.AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
    {
        // Nothing for us to do
    }

    void IOperationBehavior.ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
    {
        // Apply our own formatter
        clientOperation.Formatter = new SourceRconOperationFormatter(operationDescription);

        // This behavior takes care of both request and replies at client
        clientOperation.SerializeRequest = true;
        clientOperation.DeserializeReply = true;
    }

    void IOperationBehavior.ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
    {
        // Client-side only
        throw new NotImplementedException();
    }

    void IOperationBehavior.Validate(OperationDescription operationDescription)
    {
        // Always valid?
        // In our case we cannot have ref or out parameters
        // We could check that parameters are primitive types
    }

    #endregion
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The ApplyClientBehavior method set the Formatter property of the client operation to which the behavior is applied. It also expresses that the client operation will serialize and deserialize both request and reply messages.&lt;/p&gt;
&lt;p&gt;Inside the Validate method we could check whether the operation is compatible with the behavior. For example, we should check that there are no ref or out parameters. We could check that the parameters are either representable as a string, and whether the return value is either of type string (the reply messages always contain string data) or that it is deserializable from a string. I have not been able to get the validate method to be triggered and all implementations of IOperationBehavior inside the framework have an empty method body. With Reflector you can see that the client validations on behaviors should go off when the ChannelFactory is opening. I&amp;rsquo;m not sure why it does not fire.&lt;/p&gt;
&lt;p&gt;You can go the extra mile and have your behavior derive from Attribute:&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:a37777bd-ae37-4504-ac48-f1392d75f025" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;[AttributeUsage(AttributeTargets.Method)]
public sealed class SourceRconOperationFormatterBehaviorAttribute : Attribute, IOperationBehavior&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;so it can be used as an attribute above a method:&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:87d7b200-7785-4e00-99ab-77891efda061" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;[ServiceContract]
public interface IRcon
{
    [OperationContract(Action = &amp;quot;status&amp;quot;)]
    [SourceRconOperationFormatterBehavior]
    string GetStatus();&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You would probably want to change the name of the behavior/attribute class to something like SourceRconOperationAttribute so it looks like [SourceRconOperation]. This makes more sense. In our case the behavior is not really optional as we need to apply the operation formatter for every operation in a service contract to make things work. Having an interface that is only partially usable for remote control seems weird.&lt;/p&gt;
&lt;p&gt;Having made the remarks above on how behaviors are non-optional, the next topic will be about a streamlined way to accomplish that all operations in a service contract will have the operation formatter behavior applied.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22521" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author></entry><entry><title>WCF Extensibility part 3: Formatting operations</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/08/21/wcf-extensibility-part-3-formatting-operations.aspx" /><id>/blogs/main/archive/2009/08/21/wcf-extensibility-part-3-formatting-operations.aspx</id><published>2009-08-20T22:00:00Z</published><updated>2009-08-20T22:00:00Z</updated><content type="html">&lt;p&gt;Time to get serious and drill down into the first area of the big picture. We are going to take a look at &amp;ldquo;operation formatting&amp;rdquo;, which is roughly located in the highlighted area. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_5049AD0C.png"&gt;&lt;img height="216" width="567" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_5CD75A28.png" alt="image" border="0" title="image" style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;One of the crucial parts of the WCF channel layer is the way that method invocations get transformed into WCF messages. This capability allows the end-programmer to work with the object-oriented paradigm. This means you call methods on proxy objects, instead of having to fiddle with the messages going back and forth between a client and service yourself.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say we have a proxy that was created like so:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:59bea44a-51cf-4c1f-aafe-d2d69ac019a5" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;[ServiceContract]
public interface IRcon
{
    [OperationContract(Action = &amp;quot;kick&amp;quot;)]
    string Kick(string steamID);
}

public interface IRconProxy : IRcon, IClientChannel { }

class Program
{
    static void Main(string[] args)
    {
        SourceRconTcpBinding binding = new SourceRconTcpBinding(&amp;quot;abc123&amp;quot;);
        string uri = &amp;quot;raw.tcp://192.168.100.101:27015&amp;quot;;
        IRconProxy proxy = null;
        ChannelFactory&amp;lt;IRconProxy&amp;gt; factory = new ChannelFactory&amp;lt;IRconProxy&amp;gt;(binding, new EndpointAddress(uri));
        factory.Endpoint.Behaviors.Add(new SourceRconEndpointBehavior());
        factory.Open();

        proxy = factory.CreateChannel();

        string reply = proxy.Kick(&amp;quot;1:0:1337&amp;quot;);&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Take a look at the last line. There you can see a method call being made on the proxy that was created with a call to ChannelFactory&amp;lt;IRconProxy&amp;gt;.CreateChannel. We want to influence the way this method call gets transformed into a specialized System.ServiceModel.Messaging.Message class, called SourceRconMessage. The regular transformation would change a method call into normal Message objects. Our message object holds the spcifics for the Source rcon protocol. Here is the shape of the class, corresponding to the elements of the rcon protocol:&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:23390be6-1db6-4516-9006-ff6f6f2d81ec" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;public class SourceRconMessage : Message
{
    public int RequestID { get { ... } }
    public ServerData ServerData { ... } }
    public string String1 { get { ... } }
    public string String2 { get { ... } }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We will get back to the specifics of the message in a later post.&lt;/p&gt;
&lt;p&gt;The process of changing a method invocation to a message and vice versa is called operation formatting. The key interfaces for all classes that performs this task are System.ServiceModel.Dispatcher.IClientMessageFormatter and IDispatchMessageFormatter. They are essentially the same but mirrored, because they represent the formatting that will happen at the client and service respectively.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:06202aea-f927-4a9e-8597-f4b16fca5089" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;public interface IClientMessageFormatter
{
	object DeserializeReply(Message message, object[] parameters);
	Message SerializeRequest(MessageVersion messageVersion, object[] parameters);
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;We will only look at the client message formatter, since we are building a client-side only implementation of the channel stack. The service&amp;rsquo;s side would have DeserializeRequest and SerializeReply, mirroring the direction requests and replies are sent and received.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s look at each of the implementations of the two methods of the IClientMessageFormatter interface:&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:8047e62f-4faa-45dd-a143-506623a14266" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;// Changes a list of parameters and operation description into a SourceRconMessage
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
    SourceRconMessage message = new SourceRconMessage(operationDescription.Messages[0].Action, parameters);
    message.Headers.MessageId = new UniqueId(message.RequestID.ToString());

    return message;
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;No rocket science here. The process of changing the action and parameters of the method call into a message is performed by a custom-built constructor on the SourceRconMessage class. The one thing to remember for later though is the mysterious property of MessageId in the Headers of the message that we set. This will be revisited at a later stage.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:fa3b973f-5535-4509-b736-1fa4a5a773a7" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;// Goes from SourceRconMessage to return value and parameter list
public object DeserializeReply(Message rawMessage, object[] parameters)
{
    // Deserialize message and return value
    object returnValue = null;
    SourceRconMessage message = (SourceRconMessage)rawMessage;

    // TODO: Use returnParameter.ParameterType to get the type of return parameter
	// and deserialize to that type from string
    returnValue = message.String1;

    return returnValue;
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The DeserializeReply method will get a deserialized reply message that was handed from the channel stack. This should be a SourceRconMessage object (which we should probably check for to be sure it really is). Right now we only extract the single valuable piece of information from the message: the String1 property. It is passed back as the return value, which will work as long as the return value is of type string. Notice how there is no type information available for the return value and parameters.&lt;/p&gt;
&lt;p&gt;The two methods above go into the SourceRconOperationFormatter class. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:ceaf4f0b-f6d7-482c-be64-2d3261f0a367" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;public class SourceRconOperationFormatter: IClientMessageFormatter
{
    // Goes from SteamRconMessage to return value and parameter list
    public object DeserializeReply(Message rawMessage, object[] parameters) { ... }

    // Changes a list of parameters and operation description into a SteamRconMessage
    public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) { ... }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The class can contain much more. A later and improved version will have a special constructor to hold the operation description details to be able to have type information on the parameters and return value for the sake of DeserializeReply.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22515" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author><category term="Gaming" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Gaming/default.aspx" /><category term="Protocols" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Protocols/default.aspx" /><category term=".NET FX 3.5 SP1" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx" /><category term="WCF" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/WCF/default.aspx" /></entry><entry><title>WCF Extensibility part 2: The big picture</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/08/20/wcf-extensibility-part-2-the-big-picture.aspx" /><id>/blogs/main/archive/2009/08/20/wcf-extensibility-part-2-the-big-picture.aspx</id><published>2009-08-20T21:20:36Z</published><updated>2009-08-20T21:20:36Z</updated><content type="html">&lt;p&gt;Before I drill down into each of the smaller parts of the client-side channel stack implementation, I want to sketch out an overview of some of the moving parts of the channel layer. This picture is by no means complete, and I will probably revisit it several times over the next couple of posts. It should however provide you with a better understanding of what we are trying to accomplish in what part of the channel layer. And remember, this picture is a sketch and may not be 100% exact or correct.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_542E2B31.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_234B73C6.png" width="673" height="248" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;What you see in the picture is the client-side of the WCF channel layer. I am trying to convey here that from the method call to the actual transport several things happen along the way. &lt;/p&gt;  &lt;p&gt;First of all, when you call a service (or something else at the other end of the transport) you make a method invocation on a proxy. This might be &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;a raw transparent proxy like we created in the first part of the series with a call to ChannelFactory&amp;lt;T&amp;gt;.CreateChannel. &lt;/li&gt;    &lt;li&gt;a ClientBase derived proxy, like the one you get when you use Add Service Reference (ASR). This proxy uses the same transparent proxy on the inside.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;This method call is translated to a message object representing the method call. This message is dropped into a stack of channels that will massage the message every which way. The different channels in the stack all have their specific purpose, such as security, reliable sessions, or transport. The last channel in the stack is always the transport channel. The final transport channel will encode the message using an encoder and will serialize the bytes across the transport, whatever that may be (HTTP, MSMQ, TCP, UDP, email, …). &lt;/p&gt;  &lt;p&gt;For Request/Reply message exchange patterns there will come a stream of bytes in response. The stream will be decoded by the message encoder, which gives another message object. The same holds true for duplex messaging, but for duplex the incoming request stream might be initiated by the service, without a previous message from us, the client. We will not encounter duplex/callback messages. Finally, the response message will be turned into the completion of the method call by yielding the return value and ref or out parameters. The method call returns to the caller. You may have guessed that this is for synchronous method calls on the proxy and you are absolutely correct. For now, we will leave asynchronous operations out of scope.&lt;/p&gt;  &lt;p&gt;For each of the following posts I will highlight the area that we focus upon. Any feedback is welcome.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22513" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author><category term="Gaming" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Gaming/default.aspx" /><category term="Protocols" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Protocols/default.aspx" /><category term=".NET FX 3.5 SP1" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx" /><category term="WCF" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/WCF/default.aspx" /></entry><entry><title>WCF Extensibility part 1: background on game server protocols</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/08/17/wcf-extensibility-part-1-background-on-game-server-protocols.aspx" /><id>/blogs/main/archive/2009/08/17/wcf-extensibility-part-1-background-on-game-server-protocols.aspx</id><published>2009-08-17T20:38:00Z</published><updated>2009-08-17T20:38:00Z</updated><content type="html">&lt;h3&gt;Talking to game servers&lt;/h3&gt;
&lt;p&gt;There are various kinds of multiplayer games that allow you to battle against other gamers. I&amp;rsquo;ll focus on the First Person Shooters (FPS) and Real Time Strategy (RTS) games and skip the (Massive Multiplayer Online) Role Playing Games (MMORPG and RPG). Usually the FPS and RTS games will connect to a central server that is located on your LAN or out in the Internet. The game players will interact by means of the server using a special protocol. The administrators of the server are regular game players for most of the time, but have elevated privileges to control the game server. Typical things that an admin will do is change the currently played map, restart game rounds, and kick or ban misbehaving players from the server.&lt;/p&gt;
&lt;p&gt;This type of control can be done &amp;ldquo;locally&amp;rdquo; when the admin is one of the players connected to the server, or remotely. The latter is called remote control and it uses a special protocol particular to the type of game engine. Luckily most of these protocols are reasonably well documented. There are not that many game engines out there and hence a small number of protocols. The most famous ones are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unreal (1, 2 and 3)&lt;/li&gt;
&lt;li&gt;Quake (1, 2 and 3)&lt;/li&gt;
&lt;li&gt;Half-Life (aka Goldsource, based on Quake engine)&lt;/li&gt;
&lt;li&gt;Source&lt;/li&gt;
&lt;li&gt;Doom 3&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Right now, we&amp;rsquo;ll zoom in on the Source engine with its protocol for remote control of game servers based on this engine.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.hl2ctf.org/img/screenshots/04.jpg" alt="" /&gt;&lt;/p&gt;
&lt;h3&gt;Issuing commands&lt;/h3&gt;
&lt;p&gt;If you have a Source-based game like Half-Life 2 or Team Fortress 2 it is pretty easy to use control from the game interface. You can simply connect to the server to control by joining a multiplayer game. Once on the server you can access a console window to send commands. A comprehensive &lt;a target="_blank" href="http://developer.valvesoftware.com/wiki/Console_Command_List"&gt;list of commands&lt;/a&gt; is available. Here are some examples of common commands:&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:8d2c64b0-882f-41a3-b844-cb4b1e976c24" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;rcon_password abc123

changelevel de_dust2
kick 1:0:12345
mp_restartround 1&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The first command rcon_password is needed to prevent unwanted control of a game server. &lt;/p&gt;
&lt;p&gt;You can even use remote control by specifying the server address and password first, so you do not have to connect to the game at all.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:ffae6e9f-0afa-4c8d-bffe-7a7a76190d50" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;rcon_address 192.168.100.101:27015
rcon_password abc123&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The game itself is needed to control the server, because the game knows the protocol specific to the engine. But other than that it is inconvenient that you would need to own and start the game just to control the server. There are a fair number of code implementations out there that capture the protocol and allow a programmer to use the API to control a server remotely. I wrote several myself, which is a nice programming exercise with an interesting theme of gaming. Well, at least it beats the common customer/order/product samples.&lt;/p&gt;
&lt;h3&gt;Understanding the protocol&lt;/h3&gt;
&lt;p&gt;The Source engine is created and maintained by &lt;a target="_blank" href="http://www.valvesoftware.com/"&gt;Valve&lt;/a&gt; and their &lt;a target="_blank" href="http://developer.valvesoftware.com/wiki/Main_Page"&gt;developer wiki&lt;/a&gt; holds a pretty good explanation of the &lt;a target="_blank" href="http://developer.valvesoftware.com/wiki/Source_RCON_Protocol"&gt;Source remote control (rcon) protocol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s my take on the protocol:&lt;/p&gt;
&lt;p&gt;Source uses a TCP connection from the client to the game server. After connecting the client should perform an authentication handshake. If the authentication was successful, you can start issuing commands. The protocol uses multiple message exchanges between client and server to accomplish both. Every message has the same structure:&lt;/p&gt;
&lt;li&gt;&lt;b&gt;packet size (int): &lt;/b&gt;entire message excluding packet size integer. It must be at least 10.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;request id (int): &lt;/strong&gt;random number used for correlating responses to requests&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;server data (int): &lt;/strong&gt;depending on purpose of message the server data has one of the following values&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;SERVERDATA_AUTH = 3: initial authentication handshake message&lt;/li&gt;
&lt;li&gt;SERVERDATA_EXECCOMMAND = 2: command message&lt;/li&gt;
&lt;li&gt;SERVERDATA_RESPONSE_VALUE = 0: response from command message&lt;/li&gt;
&lt;li&gt;SERVERDATA_AUTH_RESPONSE = 2: acknowledgement of authentication message&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;string1&lt;/b&gt; &lt;strong&gt;(null-terminated string)&lt;/strong&gt;: either command to run, password or result &lt;/li&gt;
&lt;li&gt;&lt;b&gt;string2 (null-terminated string):&lt;/b&gt; reserverd, must be empty string (&amp;quot;&amp;quot;);&lt;/li&gt;
&lt;p&gt;A typical rcon session will look like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_39EF6E1B.png"&gt;&lt;img height="480" width="373" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_780888CC.png" alt="image" border="0" title="image" style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at some of the individual packets. Let&amp;rsquo;s assume that the password is &amp;ldquo;abc123&amp;rdquo; and that the command that was issued is &amp;ldquo;changelevel de_dust2&amp;rdquo;&lt;/p&gt;
&lt;table width="704" cellpadding="2" cellspacing="0" border="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="90" valign="top"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="99" valign="top"&gt;&lt;strong&gt;Authentication&lt;/strong&gt;&lt;/td&gt;
&lt;td width="103" valign="top"&gt;&lt;strong&gt;Junk&lt;/strong&gt;&lt;/td&gt;
&lt;td width="113" valign="top"&gt;&lt;strong&gt;Acknowledgment&lt;/strong&gt;&lt;/td&gt;
&lt;td width="102" valign="top"&gt;&lt;strong&gt;Exec command&lt;/strong&gt;&lt;/td&gt;
&lt;td width="195" valign="top"&gt;&lt;strong&gt;command reply&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="90" valign="top"&gt;&lt;strong&gt;packet size&lt;/strong&gt;&lt;/td&gt;
&lt;td width="99" valign="top"&gt;4 + 4 + 7 + 1 == 16&lt;/td&gt;
&lt;td width="103" valign="top"&gt;4 + 4 + 1 + 1 == 10&lt;/td&gt;
&lt;td width="113" valign="top"&gt;4 + 4 + 1 + 1 == 10&lt;/td&gt;
&lt;td width="102" valign="top"&gt;4 + 4 + 21 + 1 == 30&lt;/td&gt;
&lt;td width="195" valign="top"&gt;4 + 4 + (string1.length + 1) + 1 == 10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="90" valign="top"&gt;&lt;strong&gt;request id&lt;/strong&gt;&lt;/td&gt;
&lt;td width="99" valign="top"&gt;0x2e0e0000&lt;/td&gt;
&lt;td width="103" valign="top"&gt;0x2e0e0000&lt;/td&gt;
&lt;td width="113" valign="top"&gt;0x2e0e0000&lt;/td&gt;
&lt;td width="102" valign="top"&gt;0xd2010000&lt;/td&gt;
&lt;td width="195" valign="top"&gt;0xd2010000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="90" valign="top"&gt;&lt;strong&gt;server data&lt;/strong&gt;&lt;/td&gt;
&lt;td width="99" valign="top"&gt;3&lt;/td&gt;
&lt;td width="103" valign="top"&gt;0&lt;/td&gt;
&lt;td width="113" valign="top"&gt;2&lt;/td&gt;
&lt;td width="102" valign="top"&gt;2&lt;/td&gt;
&lt;td width="195" valign="top"&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="90" valign="top"&gt;&lt;strong&gt;string 1&lt;/strong&gt;&lt;/td&gt;
&lt;td width="99" valign="top"&gt;&amp;ldquo;abc123\0&amp;rdquo;&lt;/td&gt;
&lt;td width="103" valign="top"&gt;&amp;ldquo;\0&amp;rdquo;&lt;/td&gt;
&lt;td width="113" valign="top"&gt;&amp;ldquo;\0&amp;rdquo;&lt;/td&gt;
&lt;td width="102" valign="top"&gt;&amp;ldquo;changelevel de_dust2\0&amp;rdquo;&lt;/td&gt;
&lt;td width="195" valign="top"&gt;&amp;ldquo;\0&amp;rdquo; (command specific, &lt;br /&gt;varies depending of success or failure of method)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="90" valign="top"&gt;&lt;strong&gt;string 2&lt;/strong&gt;&lt;/td&gt;
&lt;td width="99" valign="top"&gt;&amp;ldquo;\0&amp;rdquo;&lt;/td&gt;
&lt;td width="103" valign="top"&gt;&amp;ldquo;\0&amp;rdquo;&lt;/td&gt;
&lt;td width="113" valign="top"&gt;&amp;ldquo;\0&amp;rdquo;&lt;/td&gt;
&lt;td width="102" valign="top"&gt;&amp;ldquo;\0&amp;rdquo;&lt;/td&gt;
&lt;td width="195" valign="top"&gt;&amp;ldquo;\0&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;After the exec command and corresponding reply packets you can continue issuing exec commands. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/de_5F00_train1a_5F00_623EA06F.jpg"&gt;&lt;img height="253" width="448" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/de_5F00_train1a_5F00_thumb_5F00_68194408.jpg" align="right" alt="de_train1a" border="0" title="de_train1a" style="border-bottom:0px;border-left:0px;display:inline;margin-left:0px;border-top:0px;margin-right:0px;border-right:0px;" /&gt;&lt;/a&gt;The sequence of message above is the ideal picture. In reality things might be a little more difficult, because:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;a reply may consist of multiple reply packets.&lt;/li&gt;
&lt;li&gt;authentication might not be successful because of a wrong password.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Eventually we will take everything into account, but for now we will pretend that multi-packet responses do not exist and that authentication is always successful.&lt;/p&gt;
&lt;p&gt;If that works, the exchange of raw bytes across the network should look something like this (for the 5 messages listed above):&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:ad46c626-721c-461b-b73f-96c0c96c3a84" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;0000   10 00 00 00 2e 0e 00 00 03 00 00 00 61 62 63 31  ............abc1
0010   32 33 00 00                                      23..

0000   0a 00 00 00 2e 0e 00 00 00 00 00 00 00 00        ..............

0000   0a 00 00 00 2e 0e 00 00 02 00 00 00 00 00        ..............

0000   1e 00 00 00 d2 01 00 00 02 00 00 00 63 68 61 6e  ............chan
0010   67 65 6c 65 76 65 6c 20 64 65 5f 64 75 73 74 32  gelevel de_dust2
0020   00 00                                            ..

0000   0a 00 00 00 d2 01 00 00 00 00 00 00 00 00        ..............
&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Next steps&lt;/h3&gt;
&lt;p&gt;Our task at hand is to learn WCF to speak this protocol, while maintaining the channel layer concepts. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22509" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author><category term="Visual Studio 2008" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Visual+Studio+2008/default.aspx" /><category term=".NET FX 3.5 SP1" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx" /><category term="WCF" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/WCF/default.aspx" /></entry><entry><title>Windows Communication Foundation extensibility to the max</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/08/17/windows-communication-foundation-extensibility-to-the-max.aspx" /><id>/blogs/main/archive/2009/08/17/windows-communication-foundation-extensibility-to-the-max.aspx</id><published>2009-08-17T19:27:00Z</published><updated>2009-08-17T19:27:00Z</updated><content type="html">&lt;p&gt;Last week I visited Microsoft at the Redmond campus and spent the larger part of the week with the Windows Communication Foundation and Workflow Foundation team. I spoke with a lot of the team members and managed to get good insights into the things to come in WCF/WF 4.0. &lt;/p&gt;
&lt;p&gt;I got a chance to talk to Nicolas Allen and Kenny Wolf. Besides the work-related issues that I wanted to investigate I also discussed my long-running attempt to create a very odd WCF client implementation. They gave me a couple of hints on how to take the last hurdles to get everything working. While still shrugging off the last bits of jetlag I managed to get the first implementation up and running. Although WCF was never designed with such weird things in mind, this proves that WCF is extensible beyond your imagination. I&amp;rsquo;ll walk you through it all.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.alexthissen.nl/blogs/main/archive/2009/08/17/wcf-extensibility-part-1-background-on-game-server-protocols.aspx"&gt;Part 1: Background on game server protocols&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.alexthissen.nl/blogs/main/archive/2009/08/20/wcf-extensibility-part-2-the-big-picture.aspx"&gt;Part 2: The big picture&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.alexthissen.nl/blogs/main/archive/2009/08/21/wcf-extensibility-part-3-formatting-operations.aspx"&gt;Part 3: Formatting operations&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.alexthissen.nl/blogs/main/archive/2009/08/21/wcf-extensibility-part-4-applying-formatting-to-operations.aspx"&gt;Part 4: Applying formatting to operations&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.alexthissen.nl/blogs/main/archive/2009/08/25/wcf-extensibility-part-5-make-your-endpoints-behave.aspx"&gt;Part 5: Make your endpoints behave&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But, just as a teaser preview, here are some code snippets of what this will all amount to:&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:8b74fc20-f173-47eb-bf90-e1400a3bad12" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true;"&gt;[ServiceContract]
public interface IRcon
{
	[OperationContract(Action = &amp;quot;status&amp;quot;)]
	string GetStatus();
	[OperationContract(Action = &amp;quot;changelevel&amp;quot;)]
	string ChangeLevel(string mapName);
	[OperationContract(Action = &amp;quot;mp_restartround&amp;quot;)]
	void Restart(int seconds);
}

public interface IRconProxy : IRcon, IClientChannel { } 

class Program
{
	static void Main(string[] args)
	{
		SourceRconTcpBinding binding = new SourceRconTcpBinding(&amp;quot;abc123&amp;quot;);
		string uri = &amp;quot;raw.tcp://192.168.100.101:27015&amp;quot;;
		IRconProxy proxy = null;

		try
		{
			ChannelFactory&amp;lt;IRconProxy&amp;gt; factory = new ChannelFactory&amp;lt;IRconProxy&amp;gt;(binding, new EndpointAddress(uri));
			factory.Endpoint.Behaviors.Add(new SourceRconEndpointBehavior());
			factory.Open();

			proxy = factory.CreateChannel();
			proxy.Open(TimeSpan.FromSeconds(10));

			string reply = proxy.GetStatus();
			proxy.Restart(3);
		}
		catch (Exception ex)
		{
			Console.WriteLine(ex);
		}
		finally
		{
			proxy.Close();
		}
	}
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here, the most interesting lines of code are 31 and 32: a WCF client channel talking a proprietary, non-SOAP protocol over a TCP connection.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22508" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author><category term="Protocols" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Protocols/default.aspx" /><category term=".NET FX 3.5 SP1" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx" /><category term="WCF" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/WCF/default.aspx" /></entry><entry><title>StackOverflow DevDays 2009</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/08/06/stackoverflow-devdays-2009.aspx" /><id>/blogs/main/archive/2009/08/06/stackoverflow-devdays-2009.aspx</id><published>2009-08-06T07:13:20Z</published><updated>2009-08-06T07:13:20Z</updated><content type="html">&lt;p&gt;Most of you must know the community site &lt;a href="http://www.StackOverflow.com" target="_blank"&gt;StackOverflow.com&lt;/a&gt;. But did you know that StackOverflow is also organizing the &lt;a href="http://stackoverflow.carsonified.com/" target="_blank"&gt;StackOverflow DevDays&lt;/a&gt;? “A full day of inspiration and learning for developers brought to you by the team behind StackOverflow.com and FogBugz”. The day will feature speakers like Joel Spolsky, Jeff Atwood, Scott Hanselman, Jon Skeet and many others. The DevDays tours several cities in the United States, but they are also coming to Europe! Two editions of the DevDays will take place in England (London and Cambridge) and the last one is in Amsterdam, The Netherlands. Not all speakers will make an appearance everywhere, so make sure you book the right edition to meet your favorite speaker.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_3003AD9A.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_7F00AA94.png" width="640" height="289" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Some details are on the Amsterdam edition still have to be determined, such as venue. I will be presenting a code-only (or very low PowerPoint) presentation on ASP.NET MVC. This presentation will be in English and I guess the others are in English as well given the expected international audience.&lt;/p&gt;  &lt;p&gt;As soon as more details are available, I will update them here. I do know that you will have to hurry, as the seats are running out. Almost every edition in the United States is sold out. In Europe, London is sold out, while &lt;a href="http://www.amiando.com/stackoverflowdevdays-cambridge.html" target="_blank"&gt;Cambridge&lt;/a&gt; has 45 and &lt;a href="http://www.amiando.com/stackoverflowdevdays-amsterdam.html" target="_blank"&gt;Amsterdam&lt;/a&gt; 35 seats left as the time of this blogpost. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://stackoverflow.carsonified.com/" target="_blank"&gt;Go book your seat now&lt;/a&gt;!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22507" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author></entry><entry><title>Catching the .NET Service Bus part 1: Exposing a service on the bus</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/07/21/catching-the-net-service-bus-part-1-exposing-a-service-on-the-bus.aspx" /><id>/blogs/main/archive/2009/07/21/catching-the-net-service-bus-part-1-exposing-a-service-on-the-bus.aspx</id><published>2009-07-21T19:58:00Z</published><updated>2009-07-21T19:58:00Z</updated><content type="html">&lt;p&gt;The last couple of evenings I spent some time getting familiar with the .NET Services and the Service Bus in particular. Here is a story of how I got my sample service to be available on the .NET Service Bus.&lt;/p&gt;
&lt;p&gt;I assume that you are familiar with the .NET Service Bus already; otherwise you can read some good articles on MSDN (&lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/dd129877.aspx"&gt;documentation&lt;/a&gt; and &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/magazine/dd569756.aspx"&gt;two&lt;/a&gt; &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/magazine/dd942847.aspx"&gt;articles&lt;/a&gt;) and &lt;a target="_blank" href="http://vasters.com/clemensv/CategoryView,category,.NET%2BServices.aspx"&gt;Clemens Vasters&amp;rsquo; blog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My goals were easy: what does it take to get a pretty standard WCF service up and running using the .NET Service Bus. For completeness sake, this is the service contract (sticking with my ever lasting theme of gaming):&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:c76c6a43-1c5b-404a-a7c2-6ddbb340a2ba" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true; "&gt;namespace GamingServiceLibrary
{
	[ServiceContract]
	public interface IGameServerManagement
	{
		[OperationContract]
		GameServerStatus RetrieveServerStatus(IPAddress address, int port);
	}
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I wanted to have the request/reply styled service implementation available with message security enabled. Like myself you will need a .NET Services account to be able to use the .NET Services (Service Bus and Access Control service) and have a so-called solution (mine is named &amp;ldquo;KillerApps&amp;rdquo;). You will find that solution names must be globally unique, so don&amp;rsquo;t be late and find out your intended name is already taken!&lt;/p&gt;
&lt;h2&gt;Hosting and exposing your service&lt;/h2&gt;
&lt;p&gt;First of all you need to have the service host register your service endpoint on the service bus. A lot of the plumbing is taking care of by the NetTcpRelayBinding, which does all the negotiation with the bus. All we have to do is choose an endpoint on the service bus and authenticate ourselves to the bus. For simplicity I chose the following name &amp;ldquo;GameServerService&amp;rdquo; as the significant part of the endpoint address.&lt;/p&gt;
&lt;p&gt;To create the complete endpoint address you can use a helper method:&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:c9e7a64e-00c2-404e-b024-1fc743e7543d" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true; "&gt;Uri address = ServiceBusEnvironment.CreateServiceUri(&amp;quot;sb&amp;quot;, solutionName, &amp;quot;GameServerService&amp;quot;);&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;which will generate an URI like so &lt;strong&gt;&lt;em&gt;sb&lt;/em&gt;&lt;/strong&gt;://&lt;strong&gt;&lt;em&gt;KillerApps&lt;/em&gt;&lt;/strong&gt;.servicebus.windows.net/&lt;strong&gt;&lt;em&gt;GameServerService&lt;/em&gt;&lt;/strong&gt;. The italic/bolded parts are the pieces that get filled in for you. The scheme corresponds to the type of relay binding. For TCP it will be sb, for basic, WS, federation and web HTTP bindings it will be http or https.&lt;/p&gt;
&lt;p&gt;The service host needs some preparations that can be done through code or config. I did parts in both.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:1a8eefda-fc12-490f-af52-f9d3df84823b" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true; "&gt;string solutionName = &amp;quot;KillerApps&amp;quot;;
string solutionPassword = &amp;quot;test1234&amp;quot;; // Nope, not my real password and you should replace it with your own

// Create the credentials object for the endpoint.
TransportClientEndpointBehavior userNamePasswordServiceBusCredential = new TransportClientEndpointBehavior();
userNamePasswordServiceBusCredential.CredentialType = TransportClientCredentialType.UserNamePassword;
userNamePasswordServiceBusCredential.Credentials.UserName.UserName = solutionName;
userNamePasswordServiceBusCredential.Credentials.UserName.Password = solutionPassword;

// Create the service host reading the configuration.
ServiceHost host = new ServiceHost(typeof(GameServerService), address);

// Create the ServiceRegistrySettings behavior for the endpoint.
IEndpointBehavior serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public);

// Add the Service Bus credentials to all endpoints specified in configuration.
foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
{
  endpoint.Behaviors.Add(userNamePasswordServiceBusCredential);
  endpoint.Behaviors.Add(serviceRegistrySettings);
}

// Open the service.
host.Open();&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The approach above is from the Getting Started sample in the .NET Services SDK for July 2009. Nothing fancy, just with some fixes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The sample duplicates the line for setting the username instead of one for the password. &lt;/li&gt;
&lt;li&gt;Also, the sample uses the old URIs for the service bus endpoints. You can now use the helper method). &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A quick disclaimer: do not store your password in your code or config like this. Keep it safe and encrypted.&lt;/p&gt;
&lt;p&gt;A service that wants to expose an endpoint on the Service Bus always need to authenticate, so not any odd service can claim an endpoint with your solution name in it. Likewise, the client needs to authenticate, so the service bus can check whether it is allowed to access a particular service endpoint. The endpoint behavior for password based authentication is prepared and added to all endpoints. The behavior takes care of passing a username (always the name of the solution) and password to the bus. &lt;/p&gt;
&lt;p&gt;There are other authentication types, such as CardSpace and certificates. The place to configure each of these authentication types is in another part of the .NET Services: the Access Control Service. That&amp;rsquo;s a topic for another post, but when you are looking for some guidance on the combination of CardSpace and the bus I can recommend the Hands-on Lab &amp;ldquo;.NET Services: Introduction to the Access Control Service&amp;rdquo; from the Geneva Training Kit. The host of your service chooses the authentication type it wants to use and the Access Control Service will perform the authentication.&lt;/p&gt;
&lt;p&gt;Also, the service will be added to the registry discoverable for everyone through the ServiceRegistrySetting endpoint behavior.&lt;/p&gt;
&lt;p&gt;The other part needed for successful hosting resides in the config file. The service&amp;rsquo;s configuration holds two endpoint definitions:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:e722fb9c-9db4-4129-8fc9-c746e749a468" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: xml; gutter: true; first-line: 1; tab-size: 2;  toolbar: true; "&gt;&amp;lt;services&amp;gt;
  &amp;lt;service behaviorConfiguration=&amp;quot;GamingServiceBehavior&amp;quot; name=&amp;quot;GamingServiceLibrary.GameServerService&amp;quot;&amp;gt;
            &amp;lt;endpoint binding=&amp;quot;netTcpRelayBinding&amp;quot; bindingConfiguration=&amp;quot;default&amp;quot; contract=&amp;quot;GamingServiceLibrary.IGameServerManagement&amp;quot;&amp;gt;
                &amp;lt;identity&amp;gt;
                    &amp;lt;dns value=&amp;quot;netbook01&amp;quot;/&amp;gt;
                &amp;lt;/identity&amp;gt;
            &amp;lt;/endpoint&amp;gt;
    &amp;lt;endpoint address=&amp;quot;mex&amp;quot; binding=&amp;quot;mexHttpBinding&amp;quot; contract=&amp;quot;IMetadataExchange&amp;quot; /&amp;gt;
    &amp;lt;host&amp;gt;
      &amp;lt;baseAddresses&amp;gt;
        &amp;lt;add baseAddress=&amp;quot;http://netbook01:8732/Design_Time_&lt;br /&gt;Addresses/GamingServiceLibrary/GameServerService&amp;quot; /&amp;gt;
      &amp;lt;/baseAddresses&amp;gt;
    &amp;lt;/host&amp;gt;
  &amp;lt;/service&amp;gt;
&amp;lt;/services&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Looking at this config section you can see two endpoints: one for the actual service contract implementation and one for metadata exchange. The base address in the host element does not really matter for the first endpoint, because we are providing the sb:// specific adress in the code. Also, both the binding and the service have configurations that are being referred to.&lt;/p&gt;
&lt;p&gt;The binding has this configuration:&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:0b2f73dd-b54a-49b6-ba63-aa2988e2300c" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: xml; gutter: true; first-line: 1; tab-size: 2;  toolbar: true; "&gt;&amp;lt;bindings&amp;gt;
    &amp;lt;netTcpRelayBinding&amp;gt;
        &amp;lt;binding name=&amp;quot;default&amp;quot; connectionMode=&amp;quot;Relayed&amp;quot;&amp;gt;
            &amp;lt;security mode=&amp;quot;Message&amp;quot;&amp;gt;
                &amp;lt;message clientCredentialType=&amp;quot;UserName&amp;quot; algorithmSuite=&amp;quot;Default&amp;quot; /&amp;gt;
            &amp;lt;/security&amp;gt;
        &amp;lt;/binding&amp;gt;
    &amp;lt;/netTcpRelayBinding&amp;gt;
&amp;lt;/bindings&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It specifies the connection mode of the service to the service bus and the client later on. Relayed means a client will be relayed through the service bus. Direct and Hybrid are the other options. The former allows a direct connection between client and service after service bus negotiation (which might not turn out to be possible). The latter is a mode where direct is attempted with a fallback to Relayed when direct connections fail. &lt;/p&gt;
&lt;p&gt;The &amp;lt;security&amp;gt; element configures the security of the messages. This is completely orthogonal to the way authentication has occurred. Security is optional to protect the communication between client and service, whereas authentication does not protect but is mandatory for exposing a service on the bus.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Hosting and exposing your service on the .NET Service Bus requires you to use one of the special Relay binding that are new in the Microsoft.ServiceBus assembly. Upon connection, the binding will negotiate the details of the endpoint with the host. In the process the binding will attempt to authenticate the host to the bus. &lt;/p&gt;
&lt;p&gt;Next time we will take a look at how to enable message security and I will also explain the security configuration, the endpoint behavior and &amp;lt;identity&amp;gt; element that is skipped over for now.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22506" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author><category term=".NET FX 3.5 SP1" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx" /><category term=".NET Services" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+Services/default.aspx" /><category term="WCF" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/WCF/default.aspx" /></entry><entry><title>Another year of MVP</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/07/10/another-year-of-mvp.aspx" /><id>/blogs/main/archive/2009/07/10/another-year-of-mvp.aspx</id><published>2009-07-10T11:44:38Z</published><updated>2009-07-10T11:44:38Z</updated><content type="html">&lt;p&gt;Thanks to the community for appreciating my efforts enough to have Microsoft let me be Most Valuable Professional for another year.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_2E052005.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_2D2CBA1B.png" width="474" height="83" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;A bit late in reporting this. I guess my new job was keeping me occupied. Hopefully lots of articles and conference talks will come from all the new stuff I will encounter at &lt;a href="http://www.achmea.nl" target="_blank"&gt;Achmea&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22505" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author></entry><entry><title>Bye Class-A, hello Achmea</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/06/30/bye-class-a-hello-achmea.aspx" /><id>/blogs/main/archive/2009/06/30/bye-class-a-hello-achmea.aspx</id><published>2009-06-30T17:32:12Z</published><updated>2009-06-30T17:32:12Z</updated><content type="html">&lt;p&gt;Today was my last day as an employee of &lt;a href="http://www.class-a.nl" target="_blank"&gt;Class-A&lt;/a&gt;. Some two months ago I started talking with Achmea about a position there. We were both convinced that there would be real nice opportunities. I have decided to take them up on the offer and will be joining their ranks as an architect. &lt;/p&gt;  &lt;p&gt;This means that I will be moving away a little from teaching and coaching of programmers. Surely I will continue teach others, but with more of a focus on the Achmea developers. This does not mean that I will disappear completely. No way. You will be seeing me at the various conferences, events and the community at large. At Achmea I will probably see a lot of new things that should give me a lot to talk and blog about (who knows I might just get a more frequent rhythm for blogging).&lt;/p&gt;  &lt;p&gt;I have worked for exactly 4 years at Class-A and enjoyed my time there immensely. The primary reason for me to move along was a focus shift to being an architect. I have acted in that role on my last two larger projects at customers and had a lot of fun in doing that. &lt;/p&gt;  &lt;p&gt;I will certainly miss all of my colleagues at Class-A, their wit and the discussions at our “Kennis-sessies”. Our ways will not part completely and I am convinced I will meet them ever so often. Thanks to Anko and Astrid for having me on board the past years.&lt;/p&gt;  &lt;p&gt;In a while I hope to give an update on what I am doing at Achmea and the thing that I learned and can share with you.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22503" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author><category term="Personal" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Personal/default.aspx" /></entry><entry><title>Developer Days 2009</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/06/02/developer-days-2009.aspx" /><id>/blogs/main/archive/2009/06/02/developer-days-2009.aspx</id><published>2009-06-02T21:08:25Z</published><updated>2009-06-02T21:08:25Z</updated><content type="html">&lt;p&gt;Last week Microsoft The Netherlands held another great edition of the Developer Days. With a fantastic line-up of speakers and a smooth organization I guess everyone must have enjoyed it. I know I had a good time and hope you did as well.&lt;/p&gt;  &lt;p&gt;Thanks to those of you who attended any of my sessions. I have uploaded my slides and demo code to the &lt;a href="http://www.alexthissen.nl/media" target="_blank"&gt;Media&lt;/a&gt; section of my &lt;a href="http://www.alexthissen.nl" target="_blank"&gt;site&lt;/a&gt;. &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Production debugging ASP.NET applications&lt;/strong&gt; (&lt;a href="http://www.alexthissen.nl/media/p/22496.aspx" target="_blank"&gt;slides&lt;/a&gt; and &lt;a href="http://www.alexthissen.nl/media/p/22500.aspx" target="_blank"&gt;demos&lt;/a&gt;)      &lt;br /&gt;”&lt;em&gt;&lt;font size="2"&gt;Hoe vaak heb je al meegemaakt dat de ASP.NET applicatie op jouw ontwikkelmachine perfect draait, maar dat er van alles mis gaat op de test- of zelfs productie-omgeving? De problemen die optreden kunnen varieren van bugs, onverklaarbare excepties, memory leaks, hangende pagina’s tot zelfs crashes van de webserver. Als je geen Visual Studio hebt is het lastig te achterhalen wat er mis zou kunnen zijn en zelfs Visual Studio kan je niet altijd helpen in sommige van deze situaties. Er is hoop: in deze sessie zul je een aantal praktische tools en technieken leren om veel productie-problemen te achterhalen en op te lossen. Verplichte kost voor iedere ASP.NET ontwikkelaar.&lt;/font&gt;&lt;/em&gt;”      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;An overview of Oslo&lt;/strong&gt; (&lt;a href="http://www.alexthissen.nl/media/p/22497.aspx" target="_blank"&gt;slides&lt;/a&gt; and &lt;a href="http://www.alexthissen.nl/media/p/22499.aspx" target="_blank"&gt;demos&lt;/a&gt;)      &lt;br /&gt;”&lt;em&gt;&lt;font size="2"&gt;Microsoft werkt met Oslo aan de volgende generatie van een ontwikkelplatform voor applicaties. Oslo gebruikt domein-specifieke modellen, de taal M en nieuwe tooling om je productiever te laten worden bij het ontwikkelen van applicaties. Modelleren van applicaties speelt hierbij&amp;#160; een centrale rol. Maar, wat bedoelt Microsoft met modelleren en welke rol gaat Oslo spelen in je .NET applicatie? Deze sessie geeft een overzicht van Oslo en laat je zien wat de visie van Microsoft is ten aanzien van executable modellen, runtimes en het ontwikkelen van applicaties met behulp van Oslo in het algemeen. De vervolgsessie &amp;quot;The M Language of Oslo&amp;quot; zal dieper ingaan op de taal M. Deze sessie is daarvoor een goede voorbereiding.&lt;/font&gt;&lt;/em&gt;”      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;The M language of Oslo&lt;/strong&gt; (&lt;a href="http://www.alexthissen.nl/media/p/22498.aspx" target="_blank"&gt;slides&lt;/a&gt; and &lt;a href="http://www.alexthissen.nl/media/p/22501.aspx" target="_blank"&gt;demos&lt;/a&gt;)      &lt;br /&gt;”&lt;em&gt;&lt;font size="2"&gt;Het Oslo modelleer platform heeft een eigen taal genaamd M. In deze sessie zul je leren hoe je met behulp van M de schema&amp;#39;s van een model definieert en nieuwe modellen aanmaakt. Daarnaast krijg je te zien dat je met M ook een textuele Domain Specific Language (DSL) kunt maken. Verder gaan we in op de tooling van M, zoals de M compiler voor het compileren en uitrollen van modellen naar de Oslo Repository. Het is aan te raden de eerder geplande Oslo Overview sessie bij te wonen, als je een goed overzicht van het Oslo modelleer platform wilt hebben.&lt;/font&gt;&lt;/em&gt;”&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I do apologize for some of the demos in the production debugging talk not running as smoothly as I had intended them to. It turned out that having too little disc space is not very good for your demos. Although I had prepared several backup demos and strategies, they could not save me from that situation all the time. I hope it wasn’t too disturbing and that the message of how to debug and which tools to use still came across.&lt;/p&gt;  &lt;p&gt;Let me leave you with two pictures from slidedecks:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_5627E345.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_3A36AE4D.png" width="644" height="483" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;on how and when to take a dump.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_22BBFA1C.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_1197809F.png" width="640" height="479" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;And one slide that I removed from the Oslo Overview slidedeck (which is a enhanced version of an earlier presentation “&lt;a href="http://www.alexthissen.nl/media/p/22493.aspx" target="_blank"&gt;Oslo explained&lt;/a&gt;” I did for the &lt;a href="http://www.dotned.nl" target="_blank"&gt;Stichting DotNed&lt;/a&gt;. I had no idea whether any people at the DevDays would be offended, hence I took it out just to be safe. I still think it is a good question with an answer that really describes what Oslo as a modeling platform is all about. (Nope, although the woman called Pernille Holmboe, is a model from Oslo, it is not the correct answer to the popquiz). Drop me a line if you want some more details on the machine.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22502" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author><category term="Conferences" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Conferences/default.aspx" /><category term="ASP.NET 2.0" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/ASP.NET+2.0/default.aspx" /><category term=".NET FX 2.0" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+2.0/default.aspx" /><category term="Tools and Utilities" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Tools+and+Utilities/default.aspx" /><category term="Community" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Community/default.aspx" /><category term="Debugging" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Debugging/default.aspx" /><category term="Oslo" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Oslo/default.aspx" /></entry><entry><title>Do you have an ASP.NET production problem?</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/05/07/do-you-have-an-asp-net-production-problem.aspx" /><id>/blogs/main/archive/2009/05/07/do-you-have-an-asp-net-production-problem.aspx</id><published>2009-05-07T20:43:49Z</published><updated>2009-05-07T20:43:49Z</updated><content type="html">&lt;p&gt;At the end of the month I will present at the &lt;a href="http://www.devdays.nl/" target="_blank"&gt;Developer Days&lt;/a&gt;. One of my sessions is about ASP.NET debugging in production(-like) situations. To demonstrate several tools and techniques I have prepared some cases that I encountered at various companies where I troubleshooted applications. I thought it might also be nice to present some other situations where people are or have been struggling to find a bug or solve a production problem. &lt;/p&gt;  &lt;p&gt;Do you have a production problem or solved one? This could manifesting itself like so:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;weird and slow response times (not performance related)&lt;/li&gt;    &lt;li&gt;“hanging” pages that seem to have unexplainable wait times&lt;/li&gt;    &lt;li&gt;memory leaks&lt;/li&gt;    &lt;li&gt;crashing application pools or unexpected restarts&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_4B77BAA0.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_495ABBD7.png" width="793" height="285" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I know the following might be a long shot, but who knows. In case you’re interested, send me your details and see if we can work something out to have me investigate your problem. As is nearly always the case there are some rules and limitations to this offer:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;No guarantees that I will find your bug or solve the problem&lt;/li&gt;    &lt;li&gt;You should be comfortable with me investigating your applications. I will probably &lt;u&gt;not&lt;/u&gt; need your source code, but chances are you need to give me your dump files. These will also contains a lot of information about your application.&lt;/li&gt;    &lt;li&gt;If I can solve the case, I might want to show it at the &lt;a href="http://www.devdays.nl/" target="_blank"&gt;Developer Days&lt;/a&gt;. Obviously in a simplified situation to isolate the problem or bug and without any ties to your source or dump.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;So, to summarize: if you have an ASP.NET production problem (works on your dev machine, but not on the test or production server) and weren’t able to fix it yourself and found no one who could, why not drop me a mail (athissen AT killer-apps DOT nl) and find out if I can make the difference. I will make sure you get details on retrieving information that helps on tracking down potential problems. If you’ve got any situations you were able to solve that give a nice demo, I would love to hear about it as well.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22495" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author></entry><entry><title>Using Unity to do poor man’s tracing</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/03/25/using-unity-to-do-poor-man-s-tracing.aspx" /><id>/blogs/main/archive/2009/03/25/using-unity-to-do-poor-man-s-tracing.aspx</id><published>2009-03-25T17:02:00Z</published><updated>2009-03-25T17:02:00Z</updated><content type="html">&lt;p&gt;For this post I will assume you are familiar with Dependency Injection, Inversion of Control and Unity. There are a couple of tutorials out there that show you the basics of all of these.&lt;/p&gt;
&lt;p&gt;OK, say you have got a class Widget that others depend upon, and that you have an interface IWidget to loosen the coupling.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:7110db51-ec2c-409d-b311-7e0149461241" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true; "&gt;public interface IWidget
{
	string Tagerize(bool leetified, ref string nickName, out int skillFactor);
	void Fizz();
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Never mind the silly names, I was on some kind of high when I wrote it. Also, the ref and out are there for a purpose. To resolve the Widget object through an IWidget reference, this is what you would do.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:e12cecb9-3d21-437c-9ef3-75ae204c7d56" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true; "&gt;bool leetified = false;
int skillFactor;
string nickName = &amp;quot;IncredibleElmo&amp;quot;;

IWidget tracedViaInterface = container.Resolve&amp;lt;IWidget&amp;gt;();

// Direct invocation of method
string result = tracedViaInterface.Tagerize(leetified, ref nickName, out skillFactor);
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;When dependencies of type IWidget are resolved in your application like above, or via a &amp;ldquo;cascaded&amp;rdquo; resolution (as part of a dependency of a dependency, and so on), you are ready to do some fancy stuff. Unity puts you in control of the creation of the depended-upon object, meaning that you can tell Unity to do cool things and impress all of your friends.&lt;/p&gt;
&lt;p&gt;For example, say your colleagues (or whomever you want to put the blame on) haven&amp;rsquo;t done much about tracing/instrumentation facilities in the application&amp;rsquo;s code. With Unity you can do some quick instrumentation. It can give you tracing for calls to Unity-created objects. Here&amp;rsquo;s how that would go.&lt;/p&gt;
&lt;p&gt;First, you&amp;rsquo;ll need Unity 1.2 (or higher) which is part of Enterprise Library 4.1. Since version 1.2 there is a marriage between the Policy Injection Application Block (PIAB) and Unity, essentially giving you PIAB with the ease of Unity. The marriage can be found in a Unity container extension called &amp;ldquo;Interception&amp;rdquo; inside the assembly Microsoft.Patterns.Unity.Interception.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:3b96e364-8c96-4ee9-b707-a37d92088f60" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true; "&gt;container
	.AddNewExtension&amp;lt;Interception&amp;gt;();
	.Configure&amp;lt;Interception&amp;gt;()
	.SetInterceptorFor&amp;lt;IWidget&amp;gt;(new InterfaceInterceptor());
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This additional configuration of the Unity container uses the interception mechanism to give you a man-in-the-middle object through your interface (call it a interceptor or proxy) to the actual Widget object. The interceptor can do additional work for you on all or some calls to the Widget object. You would like to trace these calls. &lt;/p&gt;
&lt;p&gt;For the tracing to work you need a call handler that knows what to do during the interception of the call. Here&amp;rsquo;s the code for my TraceCallHandler:&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:20d2698c-2a5d-4888-a16f-507b2bb5303f" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true; "&gt;public class TraceCallHandler : ICallHandler
{
	public TraceCallHandler() { }

	#region ICallHandler Members

	public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
	{
		IMethodReturn result = getNext().Invoke(input, getNext);

		// Do interception tracing
		TraceCall(input, result);

		return result;
	}

	private void TraceCall(IMethodInvocation input, IMethodReturn result)
	{
		StringBuilder builder = new StringBuilder();
		builder.AppendFormat(&amp;quot;{0}::{1}(&amp;quot;, input.MethodBase.ReflectedType.Name, input.MethodBase.Name);

		List&amp;lt;string&amp;gt; arguments = new List&amp;lt;string&amp;gt;();
		bool first = true;
		for (int index = 0; index &amp;lt; input.Arguments.Count; index++)
		{
			if (!first) builder.Append(&amp;quot;, &amp;quot;);

			string paramName = input.Arguments.ParameterName(index);
			ParameterInfo info = input.Arguments.GetParameterInfo(paramName);
			builder.AppendFormat(&amp;quot;{0} = {1}&amp;quot;, info, input.Arguments[paramName]);

			if (info.ParameterType.IsByRef || info.IsOut)
			{
				for (int counter = 0; counter &amp;lt; result.Outputs.Count; counter++)
				{
					if (result.Outputs.ParameterName(counter) == info.Name)
						builder.AppendFormat(&amp;quot;=&amp;gt; {0}&amp;quot;, result.Outputs[counter]);
				}
			}

			first = false;
		}

		builder.Append(&amp;quot;)&amp;quot;);
		if (result.ReturnValue != null) builder.AppendFormat(&amp;quot; =&amp;gt; {0}&amp;quot;, result.ReturnValue);

		// Log string
		Log(builder.ToString());
	}

	private void Log(string text)
	{
		Debug.WriteLine(text);
	}

	public int Order { get; set; }

	#endregion
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you want to have a look at what this does, focus on the Invoke first. That is the action that the call handler will perform, should the interceptor object choose to call this handler. Invoke will do the actual call on our Widget target object (but it doesn&amp;rsquo;t even need to) and then trace the call using the contextual information. The TraceCall method is some fancy outputting to the Debug window (or to DbgView if you&amp;rsquo;re not debugging).&lt;/p&gt;
&lt;p&gt;You will need to instruct the interceptor to consider calling your handler. You will need an attribute on whatever you want to handle: your interface method or the entire interface e.g.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:f51a9fd9-efdf-4dcf-ba62-270d1bcc378e" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true; "&gt;public class TraceableAttribute : HandlerAttribute
{
	public override ICallHandler CreateHandler(IUnityContainer container)
	{
		return new TraceCallHandler();
	}
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;By applying this attribute to the traced class, the interface, one or more of its methods you should be good to go. For completeness sake I give you my Widget implementation. Feel free to use the ToBrEzAhCasing extension method in your business logic somewhere.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:026aeea1-7409-48e2-b465-ff0e301ec456" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 2;  toolbar: true; "&gt;[Traceable]
public class Widget : MarshalByRefObject, IWidget
{
	#region IWidget Members

	public string Tagerize(bool leetified, ref string nickName, out int skillFactor)
	{
		nickName = nickName.ToBrEzAhCasing();
		skillFactor = leetified ? 1337 : 42;
		return String.Format(&amp;quot;{0} pwns @{1}&amp;quot;, nickName, skillFactor);
	}

	public void Fizz() { }

	#endregion
}

public static class StringExtensions
{
	public static string ToBrEzAhCasing(this string text)
	{
		int index = 0;
		return new String(text.ToCharArray().Select(c =&amp;gt; index++ % 2 == 0 ? Char.ToUpper(c) : c).ToArray());
	}
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The output is as follows:&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:0ef2f7b8-bf50-4544-a382-97d99a06b2da" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;pre class="brush: plain; gutter: true; first-line: 1; tab-size: 2;  toolbar: true; "&gt;IWidget::Tagerize(Boolean leetified = False, System.String&amp;amp; nickName = InCrEdIbLeElMo, Int32&amp;amp; skillFactor = 42=&amp;gt; 42) =&amp;gt; InCrEdIbLeElMo pwns @42
IWidget::Fizz()&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can go all the way and include much more in this tracing. This serves just to show you how to do the interception. The rest is up to you.&lt;/p&gt;
&lt;p&gt;In conclusion: what this boils down to is tracing through interception of calls to attributed methods (directly attributed or via an interface or their class) provided the objects have been created by the Unity container and pass through the proxy. I.e. no internal calls will be traced, nor will calls to objects that you created without the use of the container. Hey, I said it was poor man&amp;rsquo;s tracing. All you need to do is attribute your stuff.&lt;/p&gt;
&lt;p&gt;Notes and various other kinds of disclaimers/CMA clauses:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;in this article I described the scenario of using an interface to do interception. Wait, there are more options. It is also possible to intercept based on a MarshalByRefObject derived class or a class with virtual methods. These need different interceptor classes (TransparentProxyInterceptor and VirtualMethodInterceptor respectively). There&amp;rsquo;s more to be found &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/dd203214.aspx"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The wiring of the interception extension can be done through configuration as well.&lt;/li&gt;
&lt;li&gt;You can apply matching rules in a Unity policy that will get evaluated before using the call handlers. If a match can be made (e.g. based on type, parameter of a method, some Tag attribute, &amp;hellip;) then the call handlers of the policy will execute (or not for a mismatch).&lt;/li&gt;
&lt;li&gt;You really do not need to build your own log/trace handler. The PIAB ships with a shipload of call handlers, including a LogCallHandler. This handler uses the Logging Application Block to do its logging output. The circle is complete, or whatever. I might just show how to do this in a later post.&lt;/li&gt;
&lt;li&gt;Yes, there are some tiny bugs in the TraceCall method. I should not output values of &amp;lsquo;out&amp;rsquo; parameters and it would be better to capture the ToString of an reference type before the call instead of only after the call has happened.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22490" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author><category term="C# 3.0" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/C_2300_+3.0/default.aspx" /><category term="Unity" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Unity/default.aspx" /><category term="Enterprise Library" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Enterprise+Library/default.aspx" /></entry><entry><title>SDN Event 30th March 2009 in Driebergen</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/03/23/sdn-event-30-maart-2009-in-driebergen.aspx" /><id>/blogs/main/archive/2009/03/23/sdn-event-30-maart-2009-in-driebergen.aspx</id><published>2009-03-23T21:13:00Z</published><updated>2009-03-23T21:13:00Z</updated><content type="html">&lt;p&gt;&lt;img src="http://www.sdn.nl/Portals/0/Upload/Images/2008/SDE/SDN-Event-400px.jpg" alt="SDN Event" /&gt;&lt;/p&gt;
&lt;p&gt;Next Monday, 30th of March there will be an &lt;a target="_blank" href="http://www.sdn.nl/SDN/SDNEvent/tabid/68/Default.aspx"&gt;SDN event&lt;/a&gt; in Driebergen, The Netherlands. The central theme of the event is Testing in software. I will be there talking about two test-related topics (descriptions in Dutch):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Make your software more testable with Unity&lt;/strong&gt;: &lt;br /&gt;&amp;rdquo;&lt;em&gt;Software schijnt beter testbaar te worden wanneer je allerlei design patterns inzet. Termen als Dependency Injection (DI) en Inversion of Control (IoC) worden daarbij regelmatig genoemd. Maar hoe zit dat dan? &lt;br /&gt;In deze sessie zul je niet alleen uitleg krijgen over de design patterns, maar ook het Unity framework voor IoC. Aan de hand van een concrete case wordt duidelijk gemaakt hoe hiermee betere unit tests en beter testbare code geschreven kunnen worden.&lt;/em&gt;&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Testing with Visual Studio 2008&lt;/strong&gt;: &lt;br /&gt;&amp;rdquo;&lt;em&gt;Visual Studio 2008 biedt een scala aan mogelijkheden voor het testen van de software die je ermee ontwikkelt. In deze sessie zul je zien dat VS2008 niet alleen unit testing ondersteunt, maar ook web en load testen. Deze sessie bevat weinig slides en heel veel demos om je alle voorzieningen voor testen in Visual Studio te tonen.&lt;/em&gt;&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Afterwards I will make the slides and demos available as usual.&lt;/p&gt;
&lt;p&gt;Hope to see you there.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22488" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author><category term="Conferences" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Conferences/default.aspx" /><category term="Community" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Community/default.aspx" /><category term="Visual Studio 2008" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Visual+Studio+2008/default.aspx" /><category term="Unity" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Unity/default.aspx" /></entry><entry><title>Disappearing testrunconfig dialog for Code Coverage</title><link rel="alternate" type="text/html" href="/blogs/main/archive/2009/03/18/disappearing-testrunconfig-dialog-for-code-coverage.aspx" /><id>/blogs/main/archive/2009/03/18/disappearing-testrunconfig-dialog-for-code-coverage.aspx</id><published>2009-03-18T10:00:37Z</published><updated>2009-03-18T10:00:37Z</updated><content type="html">&lt;p&gt;Ever had this happen: Whenever you need to make changes to the code coverage settings of a Visual Studio 2008 solution, the “testrunconfig” dialog simply disappears before you get a chance to edit any setting. I’m talking about this dialog:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_0833B6BF.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_53B2E476.png" width="470" height="334" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;an clicking the item highlighted with the yellow marker.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://teamplatt-software.blogspot.com/2008/03/bug-vs-code-coverage-automatically.html" target="_blank"&gt;Martin Platt&lt;/a&gt; mentions this is because of certain custom project templates) and mentions the BizTalk and Reporting Services project templates. &lt;/p&gt;  &lt;p&gt;The Database projects from the Visual Studio 2008 Database Edition (aka DataDude) are also culprits of closing the dialog. This is for the VS2008 SKU of Database with the GDR release. &lt;/p&gt;  &lt;p&gt;The workaround is to right-click the database projects and choosing Unload Project from the context menu, you c/should be able to visit the Code Coverage section again. If other project types are in the way, you may have to unload those as well. Once you have made the changes you can reload the projects if necessary.&lt;/p&gt;  &lt;p&gt;&lt;a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=391255" target="_blank"&gt;The bug&lt;/a&gt; has been filed at &lt;a href="https://connect.microsoft.com" target="_blank"&gt;Microsoft Connect&lt;/a&gt; and appears to be related to another issue regarding &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=377557&amp;amp;wa=wsignin1.0" target="_blank"&gt;empty unit tests&lt;/a&gt;. That issue has been fixed in &lt;a href="http://support.microsoft.com/kb/962866" target="_blank"&gt;KB962866&lt;/a&gt;, but also fixes the disappearing dialog problem. You can get the &lt;a href="http://code.msdn.microsoft.com/KB962866/Release/ProjectReleases.aspx?ReleaseId=2356" target="_blank"&gt;hotfix&lt;/a&gt; from the Code Gallery.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22486" width="1" height="1"&gt;</content><author><name>alexthissen</name><uri>http://www.alexthissen.nl/members/alexthissen/default.aspx</uri></author><category term="Visual Studio 2008" scheme="http://www.alexthissen.nl/blogs/main/archive/tags/Visual+Studio+2008/default.aspx" /></entry></feed>