<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://www.alexthissen.nl/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"><channel><title>Home of Alex Thissen</title><link>http://www.alexthissen.nl/blogs/</link><description>&lt;P&gt;All of the things I like to share&lt;/P&gt;</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>WCF Extensibility part 5: Make your endpoints behave</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/08/25/wcf-extensibility-part-5-make-your-endpoints-behave.aspx</link><pubDate>Tue, 25 Aug 2009 06:36:00 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22532</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>3</slash:comments><description>&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;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Gaming/default.aspx">Gaming</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Protocols/default.aspx">Protocols</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx">.NET FX 3.5 SP1</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/WCF/default.aspx">WCF</category></item><item><title>WCF Extensibility part 4: Applying formatting to operations</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/08/21/wcf-extensibility-part-4-applying-formatting-to-operations.aspx</link><pubDate>Fri, 21 Aug 2009 20:11:00 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22521</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>5</slash:comments><description>&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;</description></item><item><title>WCF Extensibility part 3: Formatting operations</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/08/21/wcf-extensibility-part-3-formatting-operations.aspx</link><pubDate>Thu, 20 Aug 2009 22:00:00 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22515</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>5</slash:comments><description>&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;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Gaming/default.aspx">Gaming</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Protocols/default.aspx">Protocols</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx">.NET FX 3.5 SP1</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/WCF/default.aspx">WCF</category></item><item><title>WCF Extensibility part 2: The big picture</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/08/20/wcf-extensibility-part-2-the-big-picture.aspx</link><pubDate>Thu, 20 Aug 2009 21:20:36 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22513</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>5</slash:comments><description>&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;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Gaming/default.aspx">Gaming</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Protocols/default.aspx">Protocols</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx">.NET FX 3.5 SP1</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/WCF/default.aspx">WCF</category></item><item><title>WCF Extensibility part 1: background on game server protocols</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/08/17/wcf-extensibility-part-1-background-on-game-server-protocols.aspx</link><pubDate>Mon, 17 Aug 2009 20:38:00 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22509</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>4</slash:comments><description>&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;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Visual+Studio+2008/default.aspx">Visual Studio 2008</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx">.NET FX 3.5 SP1</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/WCF/default.aspx">WCF</category></item><item><title>Windows Communication Foundation extensibility to the max</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/08/17/windows-communication-foundation-extensibility-to-the-max.aspx</link><pubDate>Mon, 17 Aug 2009 19:27:00 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22508</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>5</slash:comments><description>&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;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Protocols/default.aspx">Protocols</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx">.NET FX 3.5 SP1</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/WCF/default.aspx">WCF</category></item><item><title>StackOverflow DevDays 2009</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/08/06/stackoverflow-devdays-2009.aspx</link><pubDate>Thu, 06 Aug 2009 07:13:20 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22507</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>0</slash:comments><description>&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;</description></item><item><title>Catching the .NET Service Bus part 1: Exposing a service on the bus</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/07/21/catching-the-net-service-bus-part-1-exposing-a-service-on-the-bus.aspx</link><pubDate>Tue, 21 Jul 2009 19:58:00 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22506</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>0</slash:comments><description>&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;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx">.NET FX 3.5 SP1</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+Services/default.aspx">.NET Services</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/WCF/default.aspx">WCF</category></item><item><title>Another year of MVP</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/07/10/another-year-of-mvp.aspx</link><pubDate>Fri, 10 Jul 2009 11:44:38 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22505</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>0</slash:comments><description>&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;</description></item><item><title>Bye Class-A, hello Achmea</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/06/30/bye-class-a-hello-achmea.aspx</link><pubDate>Tue, 30 Jun 2009 17:32:12 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22503</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>0</slash:comments><description>&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;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Personal/default.aspx">Personal</category></item><item><title>Developer Days 2009</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/06/02/developer-days-2009.aspx</link><pubDate>Tue, 02 Jun 2009 21:08:25 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22502</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>0</slash:comments><description>&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;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Conferences/default.aspx">Conferences</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/ASP.NET+2.0/default.aspx">ASP.NET 2.0</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+2.0/default.aspx">.NET FX 2.0</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Tools+and+Utilities/default.aspx">Tools and Utilities</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Community/default.aspx">Community</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Oslo/default.aspx">Oslo</category></item><item><title>Do you have an ASP.NET production problem?</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/05/07/do-you-have-an-asp-net-production-problem.aspx</link><pubDate>Thu, 07 May 2009 20:43:49 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22495</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>0</slash:comments><description>&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;</description></item><item><title>Using Unity to do poor man’s tracing</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/03/25/using-unity-to-do-poor-man-s-tracing.aspx</link><pubDate>Wed, 25 Mar 2009 17:02:00 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22490</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>0</slash:comments><description>&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;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/C_2300_+3.0/default.aspx">C# 3.0</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Unity/default.aspx">Unity</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Enterprise+Library/default.aspx">Enterprise Library</category></item><item><title>SDN Event 30th March 2009 in Driebergen</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/03/23/sdn-event-30-maart-2009-in-driebergen.aspx</link><pubDate>Mon, 23 Mar 2009 21:13:00 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22488</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>0</slash:comments><description>&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;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Conferences/default.aspx">Conferences</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Community/default.aspx">Community</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Visual+Studio+2008/default.aspx">Visual Studio 2008</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Unity/default.aspx">Unity</category></item><item><title>Disappearing testrunconfig dialog for Code Coverage</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/03/18/disappearing-testrunconfig-dialog-for-code-coverage.aspx</link><pubDate>Wed, 18 Mar 2009 10:00:37 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22486</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>0</slash:comments><description>&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;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Visual+Studio+2008/default.aspx">Visual Studio 2008</category></item><item><title>Mocking objects that change arguments</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/02/16/mocking-objects-that-change-arguments.aspx</link><pubDate>Mon, 16 Feb 2009 21:01:20 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22460</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;Most mocking framework know how to mock an interface or (abstract) class and fake the method calls that are performed on these mocks. However, hardly any of them can do anything other than provide a return value when the mock method is called.&lt;/p&gt; &lt;p&gt;This poses a serious problem when ref or out parameters are provided or when reference types are used that need to be manipulated as part of the mock method. Here&amp;#39;s a scenario in which I needed to do exactly that.&lt;/p&gt; &lt;p&gt;The System.Net.Sockets.Socket class can send and receive raw data through a byte[] buffer. Take a look at some of the signatures for the Socket::Send method:&lt;/p&gt; &lt;div style="border-bottom:#cccccc 1pt solid;border-left:#cccccc 1pt solid;padding-bottom:1pt;padding-left:1pt;width:100%;padding-right:1pt;font-family:consolas;background:#f5f5f5;color:black;font-size:10pt;border-top:#cccccc 1pt solid;border-right:#cccccc 1pt solid;padding-top:1pt;"&gt; &lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;int&lt;/span&gt; Receive(&lt;span style="color:blue;"&gt;byte&lt;/span&gt;[] buffer)&lt;/p&gt; &lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;int&lt;/span&gt; Receive(&lt;span style="color:#2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;ArraySegment&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;byte&lt;/span&gt;&amp;gt;&amp;gt; buffers, &lt;span style="color:#2b91af;"&gt;SocketFlags&lt;/span&gt; socketFlags);&lt;/p&gt;&lt;/div&gt; &lt;p&gt;When the Receive method is called, a byte[] buffer or list of ArraySegments of byte buffers is passed. The return value of Receive will indicate the actual number of bytes that were received. But, ... more importantly, the buffer now contains the bytes read from the socket. How would you go about mocking this?&lt;/p&gt; &lt;p&gt;At a first impression you could think that you would create a wrapper or abstraction of the Socket, give it an interface and mock it from there. True, but this still leaves you with a new class to test. If you strive for a high code coverage, or want to do an integration test up until the Socket level, then this offers no way out.&lt;/p&gt; &lt;p&gt;Enter stage for &lt;a href="http://www.typemock.com" target="_blank"&gt;TypeMock&lt;/a&gt;. Using this mocking framework you can handle method calls on mocked objects and have dynamic return values. The key to this all is the &lt;a href="http://www.typemock.com/Docs/UserGuide/TypeMock.DynamicReturnValue.html" target="_blank"&gt;DynamicReturnValue&lt;/a&gt; class. I wrote this extension method for the Socket class. This extension method prepares a mocked Socket object to fake reception of network data. This data is provided in a packet (an ArraySegment of byte). From this packet the data is read and transferred to the buffer that is passed to the Receive method when it is called later on.&lt;/p&gt; &lt;div style="border-bottom:#cccccc 1pt solid;border-left:#cccccc 1pt solid;padding-bottom:1pt;padding-left:1pt;width:100%;padding-right:1pt;font-family:consolas;background:#f5f5f5;color:black;font-size:10pt;border-top:#cccccc 1pt solid;border-right:#cccccc 1pt solid;padding-top:1pt;"&gt; &lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; FakeReceive(&lt;span style="color:blue;"&gt;this&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Socket&lt;/span&gt; socket, &lt;span style="color:#2b91af;"&gt;ArraySegment&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;byte&lt;/span&gt;&amp;gt; packet)&lt;/p&gt; &lt;p style="margin:0px;"&gt;{&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp; &lt;span style="color:#2b91af;"&gt;Mock&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;Socket&lt;/span&gt;&amp;gt; mock = &lt;span style="color:#2b91af;"&gt;MockManager&lt;/span&gt;.GetMockOf&amp;lt;&lt;span style="color:#2b91af;"&gt;Socket&lt;/span&gt;&amp;gt;(socket);&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp; &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.IsNotNull(mock, &lt;span style="color:#a31515;"&gt;&amp;quot;Socket is not mocked. Supply a mocked socket object&amp;quot;&lt;/span&gt;);&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp; mock&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ExpectAndReturn(&lt;span style="color:#a31515;"&gt;&amp;quot;Receive&amp;quot;&lt;/span&gt;, &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;DynamicReturnValue&lt;/span&gt;(&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;delegate&lt;/span&gt;(&lt;span style="color:blue;"&gt;object&lt;/span&gt;[] parameters, &lt;span style="color:blue;"&gt;object&lt;/span&gt; context)&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;byte&lt;/span&gt;[] buffer = (&lt;span style="color:blue;"&gt;byte&lt;/span&gt;[])parameters[0];&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;int&lt;/span&gt; offset;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;int&lt;/span&gt; length;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (parameters.Length == 1)&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; offset = packet.Offset;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; length = packet.Count;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;else&lt;/span&gt;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; offset = (&lt;span style="color:blue;"&gt;int&lt;/span&gt;)parameters[1];&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; length = (&lt;span style="color:blue;"&gt;int&lt;/span&gt;)parameters[2];&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;// Check whether packet has enough data&lt;/span&gt;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.IsTrue(packet.Count &amp;lt;= length, &lt;span style="color:#a31515;"&gt;&amp;quot;Size of packet is too small for expected data received from socket.&amp;quot;&lt;/span&gt;);&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#2b91af;"&gt;Array&lt;/span&gt;.Copy(packet.Array, packet.Offset, buffer, offset, length);&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; length;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }));&lt;/p&gt; &lt;p style="margin:0px;"&gt;}&lt;/p&gt;&lt;/div&gt; &lt;p&gt;In this method I expect that the extended Socket object is a mocked object. I arrange the mock to expect and return a DynamicReturnValue for the Receive method. The constructor for the DynamicReturnValue takes a delegate that is called instead of the Receive method on the mocked object. The constructor takes two parameters. The most important one is the object[] parameters, that holds the parameters/arguments of the method called (Receive in our case). &lt;/p&gt; &lt;p&gt;The ExpectAndReturn method does not know which overload of Receive is called. You should have enough control over the situation to know which one it is. The FakeReceive method assumes that the overloads are either of these:&lt;/p&gt; &lt;div style="border-bottom:#cccccc 1pt solid;border-left:#cccccc 1pt solid;padding-bottom:1pt;padding-left:1pt;width:100%;padding-right:1pt;font-family:consolas;background:#f5f5f5;color:black;font-size:10pt;border-top:#cccccc 1pt solid;border-right:#cccccc 1pt solid;padding-top:1pt;"&gt; &lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;int&lt;/span&gt; Receive(&lt;span style="color:blue;"&gt;byte&lt;/span&gt;[] buffer);&lt;/p&gt; &lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;int&lt;/span&gt; Receive(&lt;span style="color:blue;"&gt;byte&lt;/span&gt;[] buffer, &lt;span style="color:blue;"&gt;int&lt;/span&gt; offset, &lt;span style="color:blue;"&gt;int&lt;/span&gt; size, &lt;span style="color:#2b91af;"&gt;SocketFlags&lt;/span&gt; socketFlags);&lt;/p&gt;&lt;/div&gt; &lt;p&gt;For the first overload the number of parameters is 1. The entire packet is transferred to the buffer in that case. Otherwise the requested number of bytes is read into the buffer. The provided packet should contain enough bytes. In both cases the number of bytes read is returned.&lt;/p&gt; &lt;p&gt;The next code fragment shows how to use the FakeReceive method in a test fixture.&lt;/p&gt; &lt;div style="border-bottom:#cccccc 1pt solid;border-left:#cccccc 1pt solid;padding-bottom:1pt;padding-left:1pt;width:100%;padding-right:1pt;font-family:consolas;background:#f5f5f5;color:black;font-size:10pt;border-top:#cccccc 1pt solid;border-right:#cccccc 1pt solid;padding-top:1pt;"&gt; &lt;p style="margin:0px;"&gt;&lt;span style="color:#2b91af;"&gt;MockObject&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;Socket&lt;/span&gt;&amp;gt; mock = &lt;span style="color:#2b91af;"&gt;MockManager&lt;/span&gt;.MockObject&amp;lt;&lt;span style="color:#2b91af;"&gt;Socket&lt;/span&gt;&amp;gt;();&lt;/p&gt; &lt;p style="margin:0px;"&gt;&lt;span style="color:#2b91af;"&gt;Socket&lt;/span&gt; socket = mock.Object;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;byte&lt;/span&gt;[] packet = &lt;span style="color:#2b91af;"&gt;DeploymentItemHelper&lt;/span&gt;.LoadBinaryItem(&lt;span style="color:#a31515;"&gt;@&amp;quot;GameSpyMaster2MultiPacketResponse\GameSpyMasterResponseHeader.bin&amp;quot;&lt;/span&gt;);&lt;/p&gt; &lt;p style="margin:0px;"&gt;socket.FakeReceive(packet, 1);&lt;/p&gt; &lt;p style="margin:0px;"&gt;socket.FakeReceive(&lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ArraySegment&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;byte&lt;/span&gt;&amp;gt;(packet, 1, 16));&lt;/p&gt; &lt;p style="margin:0px;"&gt;socket.FakeReceive(&lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ArraySegment&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;byte&lt;/span&gt;&amp;gt;(packet, 17, 9));&lt;/p&gt; &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt; &lt;p style="margin:0px;"&gt;&lt;span style="color:#2b91af;"&gt;GameSpyMaster2Response&lt;/span&gt; response = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;GameSpyMaster2Response&lt;/span&gt;(key, validation);&lt;/p&gt; &lt;p style="margin:0px;"&gt;response.Receive(socket);&lt;/p&gt;&lt;/div&gt; &lt;p&gt;First, the mock Socket is created. Next, data is loaded from a binary test file. The socket is prepared for three consecutive Receive calls that read more and more from the binary data. Lastly, the GameSpyMaster2Response object is tested by calling the Receive method (not the one from Socket, but of the object under test) passing in the mocked and prepared socket.&lt;/p&gt; &lt;p&gt;Works like a charm. There&amp;#39;s room for improvement, though. You could allow for faking more overloads of Receive. I just called YAGNI and went on.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22460" width="1" height="1"&gt;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Testing/default.aspx">Testing</category></item><item><title>Quick tip on Visual Studio 2008 and UAC</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/02/16/quick-tip-on-visual-studio-2008-and-uac.aspx</link><pubDate>Mon, 16 Feb 2009 09:43:41 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22458</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>2</slash:comments><description>&lt;p&gt;On a Windows Vista (and presumably Windows Server 2008) that has User Account Control (UAC) enabled you are no longer able to drag and drop files from Windows Explorer into your VS solution. I always used this to quickly add files to a project. What a bummer.&lt;/p&gt; &lt;p&gt;There are 2 workarounds:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Copy or move the files to the correct location in your Visual Studio project folder. Then go into Visual Studio and click the Show All Files button for that project. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_2.png"&gt;&lt;img style="border-right-width:0px;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" border="0" alt="image" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb.png" width="240" height="128" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;You might need to click Refresh (not F5) on the project for the new file(s) to show up. Select them all and right-click. Choose Include In Project from the context menu.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_4.png"&gt;&lt;img style="border-right-width:0px;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" border="0" alt="image" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_1.png" width="225" height="240" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;-or-&lt;br /&gt; &lt;li&gt;Instead of dragging the files simply copy and paste them into your project. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_6.png"&gt;&lt;img style="border-right-width:0px;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" border="0" alt="image" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_2.png" width="240" height="148" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Sounds too easy for this to work, but it does. &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Option 2 certainly makes it easier and faster for me.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22458" width="1" height="1"&gt;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Windows+OS/default.aspx">Windows OS</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Visual+Studio+2008/default.aspx">Visual Studio 2008</category></item><item><title>Improvements and changes to Oslo SDK and Repository in January CTP</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/01/31/improvements-and-changes-to-oslo-sdk-and-repository-in-january-ctp.aspx</link><pubDate>Sat, 31 Jan 2009 17:21:19 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22452</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>1</slash:comments><description>&lt;p&gt;Since yesterday the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=f2f4544c-626c-44a3-8866-b2a9fe078956&amp;amp;displaylang=en" target="_blank"&gt;Oslo SDK January 2009 CTP&lt;/a&gt; has been released. I took a quick look to find out what is different from the PDC alpha bits that where released in October 2008.&lt;/p&gt; &lt;p&gt;First off, read the &lt;a href="http://download.microsoft.com/download/5/4/B/54BF5C12-20B8-462E-802E-0BCA2BCBF72C/OsloSDKJan2009CTPReleaseNotes.htm" target="_blank"&gt;Read Me&lt;/a&gt; file found at the download site. It lists a number of changes in detail. To summarize the important changes mentioned:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a name="_Toc220831994"&gt;Token Actions for &lt;/a&gt;MGrammar:&lt;br /&gt;&amp;quot;&lt;em&gt;Any production in a token can now have a code action or a graph action (formerly known as term construction)!&amp;nbsp; You can now specify a return type for a token definition in the case of code actions, similar to a syntax definition.&lt;/em&gt;&amp;quot;&lt;br /&gt;I have to check what this means exactly.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.pluralsight.com/community/blogs/dbox/archive/2009/01/30/fresh-oslo-bits.aspx" target="_blank"&gt;Don Box mentions&lt;/a&gt; that he likes the ability to specify a right-hand side in token rules, just like in syntax rules (see above). I assume he means this one.&lt;br /&gt;&lt;/li&gt; &lt;li&gt;MGraph syntax supported in MGrammar right-hand-side:&lt;br /&gt;You can now use the following:&lt;br /&gt;&lt;br /&gt;syntax EndPoint = uri:Listen =&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ServiceEndPoint { ListenUri = uri, ... }&lt;br /&gt;&lt;br /&gt;where previously you were only able to do&lt;br /&gt;&lt;br /&gt;syntax EndPoint = uri:Listen =&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ServiceEndPoint { ListenUri { &amp;quot;http://...&amp;quot; }, ... }&lt;br /&gt;&lt;/li&gt; &lt;li&gt;&lt;a name="_Toc220831996"&gt;Additional M Collection members have been implemented&lt;/a&gt;: Count, Choose and Distinct for all collections and All and Exists for Logical*.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Besides changing a typo in the Models\System\Mvc\Activities\ValidatingViewActivity .m file and removal of ViewAcitvity.m in the same folder nothing has changed in the models source code.&lt;/p&gt; &lt;p&gt;In my &lt;a href="http://www.alexthissen.nl/blogs/main/archive/2009/01/28/installing-oslo-sdk-and-creating-an-oslo-repository-from-scratch.aspx" target="_blank"&gt;previous post&lt;/a&gt; I explained that the Oslo Repository setup did not install correctly for non-default instances.&amp;nbsp; It contains a better setup procedure, that let&amp;#39;s you choose your SQL instance during setup:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_4.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;border-top:0px;border-right:0px;" border="0" alt="image" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_1.png" width="300" height="234" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;It will also let you choose whether to install a repository at all. Not everyone might want to have a repository on their local machine. There&amp;#39;s a CreateRepository.htm readme file explaining all of the command-line switches for the CreateRepository.exe utility. Nothing much seems to have changed in these switches&lt;/p&gt; &lt;p&gt;The Oslo SDK setup that follows let&amp;#39;s you pick individual items to install.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_8.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;border-top:0px;border-right:0px;" border="0" alt="image" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_3.png" width="300" height="234" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;The Visual Studio integration has some small steps forward as well. If I recall correctly, you could not add references before, which is possible now.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_10.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;border-top:0px;border-right:0px;" border="0" alt="image" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb_5F00_4.png" width="309" height="187" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Still a long way to go towards becoming a full-featured project type, but getting closer.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22452" width="1" height="1"&gt;</description></item><item><title>Installing Oslo SDK and creating an Oslo repository from scratch</title><link>http://www.alexthissen.nl/blogs/main/archive/2009/01/28/installing-oslo-sdk-and-creating-an-oslo-repository-from-scratch.aspx</link><pubDate>Wed, 28 Jan 2009 20:44:43 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:22449</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>2</slash:comments><description>&lt;p&gt;Because my machine doesn&amp;#39;t perform well enough when running a Virtual PC image I ventured out to install the Oslo SDK onto my Windows Vista. Turns out to be a worthwhile experience.&lt;/p&gt; &lt;p&gt;Some requirements while trying to install it caught me off-guard:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Windows Installer 4.5 to be able to install the next one (SQL Server 2008). &lt;li&gt;SQL Server 2008. I installed the Express version which is a free download.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;After preparing your machine, you are ready to install.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;Install Oslo SDK&lt;/strong&gt;&lt;br /&gt;Download and install the &lt;a href="http://download.microsoft.com/download/4/2/3/423FFDF3-B0B9-4EF0-990F-82DDE530B672/OsloSDKOct2008CTP.msi" target="_blank"&gt;Oslo SDK October 2008 CTP&lt;/a&gt; from the &lt;a href="http://msdn.microsoft.com/en-us/oslo/default.aspx" target="_blank"&gt;Oslo Development Center&lt;/a&gt;. Pretty simple. Next, next, Finish. You will notice that the repository could not be installed if you have an Express edition or non-default instance (cheapskate-me installed the Express edition). Not to worry, just read on. Even if you have got a default instance, you might want to create the repository by hand for reason obvious in the next step.&lt;br /&gt; &lt;li&gt;&lt;strong&gt;Create the Oslo repository&lt;/strong&gt;&lt;br /&gt;Go to the C:\Program Files\Microsoft Repository folder and run the following command:&lt;br /&gt;&lt;br /&gt;&lt;font size="2" face="Courier New"&gt;CreateRepository.exe /RepositoryAuditing+ &lt;br /&gt;&amp;nbsp; /SchemaPolicy+ /RepositoryName:TestRepository&lt;br /&gt;&amp;nbsp; /DataFileInitialSize:20MB /DataFileGrowth:10MB &lt;br /&gt;&amp;nbsp; /LogFileInitialSize:20MB /LogFileGrowth:10MB&lt;br /&gt;&amp;nbsp; /Verbose+ /SqlServer:.\SQLExpress&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;Let&amp;#39;s elaborate on some of the command-line options I have specified:&lt;/li&gt; &lt;ul&gt; &lt;li&gt;Repository auditing is not enabled by default. Consider turning it on straight away. I have no real arguments for doing so, and I am not sure if it can be turned on afterwards (I guess it should be possible). Same goes for Schema policies. AFAIK policies and auditing are only available for full SQL Server installations (as in: not for Express editions). &lt;li&gt;The default initial size of the Repository is a whopping &lt;strong&gt;1GB&lt;/strong&gt;. I have plenty of hard disk space on my machine, but not that much. How about you?&lt;br /&gt;Make sure you also change the log file initial size and the growth sizes for both the data and log file. Otherwise you&amp;#39;ll have some 2GB+ less disk space. You have been warned. &lt;li&gt;The SQL server name is critical if you have a named instance or want to install on a remote server. For a local SQL Express it needs to be &amp;#39;.\SQLExpress&amp;#39;. &lt;li&gt;Verbose: it&amp;#39;s always nice to see what is going on &lt;li&gt;Specify a different name for the repository if you want to have multiple instances running side-by-side or don&amp;#39;t like the default one of &amp;#39;Repository&amp;#39;.&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;&lt;strong&gt;Backup the repository&lt;br /&gt;&lt;/strong&gt;Perform a backup of the repository database either at this point or later. This will make it lightning fast to restore a repository database in case of a total mess-up on your behalf or the pre-alpha software (I bet it will be the former). There is no good tooling support just yet for removing models from the repository, so a restore from backup is the recommended workaround. You might consider doing the backup after installing the Microsoft models (see next step).&lt;br /&gt; &lt;li&gt;&lt;strong&gt;Install the Microsoft models into the repository&lt;br /&gt;&lt;/strong&gt;The Oslo SDK has a precompiled image for their Oslo models in it. Check out the &amp;quot;C:\Program Files\Microsoft Repository&amp;quot; folder again and find a model image file called Models.mx. To install this into the repository type:&lt;br /&gt;&lt;font size="2" face="Courier New"&gt;&lt;br /&gt;mx.exe -i:models.mx -s:.\SQLExpress -db:Repository &lt;br /&gt;&lt;/font&gt;&lt;br /&gt;I found that this image and one that you compile by hand from the model source code (at &amp;quot;C:\Program Files\Microsoft Oslo SDK 1.0\Models&amp;quot;) are not equivalent.&lt;br /&gt; &lt;li&gt;&lt;strong&gt;All done&lt;br /&gt;&lt;/strong&gt;Yep, you&amp;#39;re ready to go.&lt;/li&gt;&lt;/ol&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=22449" width="1" height="1"&gt;</description></item><item><title>Early thoughts on MEntity</title><link>http://www.alexthissen.nl/blogs/main/archive/2008/11/15/early-thoughts-on-mentity.aspx</link><pubDate>Sat, 15 Nov 2008 08:06:00 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:2952</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>3</slash:comments><description>&lt;p&gt;Even though no details on MEntity have been revealed yet, here are my thoughts on MEntity and its place and purpose in the world of &amp;quot;Oslo&amp;quot;. This current thinking has been fed by the discussions &lt;a href="http://weblogs.asp.net/pgielens" target="_blank"&gt;Paul Gielens&lt;/a&gt; and I had with Don Box. Here goes.&lt;/p&gt;
&lt;h4&gt;A model and a DSL for the Entity Framework&lt;/h4&gt;
&lt;p&gt;Don mentioned that CSDL/MSL/SSDL (or the EDMX file format for that matter) is essentially the Entity Framework&amp;#39;s model. The &amp;quot;metadata&amp;quot; in these files can be perceived as the model driving any application using the Entity Framework. The EF runtime consume and directly execute the model data, making the EF Oslo model an executable model.&lt;/p&gt;
&lt;p&gt;The Entity Framework team will presumably start working on a model for the conceptual, mapping and storage layers. They will use MSchema to formulate the model and have the schema for storing the model generated using the m.exe and mx.exe compilers. Using MGraph one can define the EF model data for a particular application using the EF. The schema and model data end up in the Oslo repository powered by Microsoft SQL Server.&lt;/p&gt;
&lt;p&gt;To make defining the model data easier and more intuitive the EF team will almost certainly define a new Domain Specific Language (DSL) for the Entity Framework: MEntity. They will use &lt;span style="text-decoration:line-through;"&gt;MSchema&lt;/span&gt; MGrammar (thanks Dennis for spotting this mistake) to specify the MEntity language. The model for EF will be defined in MSchema. I have no clue just yet as to what it will look like. It can be expected though that MEntity will be much easier than the EDMX format if you want to forsake the EF designer in Visual Studio and go for textual modeling. Moreover, you can use Quadrant to inspect and manipulate the model data in the Oslo repository.&lt;/p&gt;
&lt;p&gt;EF having a model might not be much on its own, but look at the larger picture. Your application will probably use more models for other technology stacks (WF, WCF, WPF, ASP.NET and so on) and might have an application-model. To me it seems valuable that EF will have the same model engine that the others use as well. You get to leverage your existing (well, by that time at least) Oslo knowledge and modeling techniques, and work with EF in a more declaratively fashion.&lt;/p&gt;
&lt;h4&gt;Adapting the EF runtime to Oslo&lt;/h4&gt;
&lt;p&gt;So, using the MEntity DSL any EF developer gets to define your EDM and its mappings using Oslo model data. The Entity Framework runtime will need to be able to read the Oslo model data from the SQL Server repository and use it to build up the Entity Data Model (EDM) and the mappings to the storage layer. When you first think of this it may seem a bit silly to have EF bootstrap of off a database. Give it some more thought and it is not so weird that the runtime should read data from a repository with a well-known schema before it can read other (entity) data from databases.&lt;/p&gt;
&lt;p&gt;As an intermediate step to use Oslo without having to go through too much troubles implementing/changing the current runtime, one could use the native support that Oslo will have for a XAML representation of the model data. The WF and WCF runtimes will most likely do the same thing to avoid having to perform big changes in the beginning. Simply &amp;quot;read&amp;quot; the model data in XAML format from the repository and use that just as it is currently done in the runtimes. That would have been a really nice option for EF as well, ... if they had used the XAML format for CSDL, MSDL and SSDL. (read my other (forthcoming post on this question to the EF team). I guess these are just implementation details that get worked out.&lt;/p&gt;
&lt;h4&gt;Oslo, EF and other databases&lt;/h4&gt;
&lt;p&gt;However, this does beg the question of how you can justify the Microsoft SQL Server repository for Oslo in situations where you would want to use EF to target non-Microsoft entity providers and databases. Is Oslo and consequently MEntity only suited for EF in a homogenous situation of SQL Server only?&lt;/p&gt;
&lt;p&gt;Well, I&amp;#39;ll give it some more thought the next couple of weeks. Any comments, ideas or suggestions you might have are more than welcome.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=2952" width="1" height="1"&gt;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx">.NET FX 3.5 SP1</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Oslo/default.aspx">Oslo</category></item><item><title>Lap around Cloud Services</title><link>http://www.alexthissen.nl/blogs/main/archive/2008/10/27/lap-around-cloud-services.aspx</link><pubDate>Mon, 27 Oct 2008 18:48:20 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:2948</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;During the keynote Microsoft has unveiled &lt;a target="_blank"&gt;Microsoft Azure&lt;/a&gt; as their &amp;quot;Operating System for the cloud&amp;quot;. At Microsoft the cloud is seen as a set of connected servers/services.&lt;/p&gt; &lt;p&gt;With Azure an organization does not have to worry about running hardware, operating systems on servers, take care of data storage for a full 100%. Instead, some software can be run in the cloud (using Azure as the &amp;quot;OS&amp;quot;), and spend more time on your business logic as opposed to getting everything to run. Of course you can still use or combine this with on-premise (the old-fashioned) applications and services, as in Software + Services.&lt;/p&gt; &lt;p&gt;Azure gives support for utility computing, meaning that it is always there and for a &amp;quot;pay as you use&amp;quot; pricing model. The business model is consumption based and has SLA levels with financial guarantees should anything go wrong.&lt;/p&gt; &lt;p&gt;The key features of Azure highlighted:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;Automated service management&lt;br /&gt;&lt;/strong&gt;The platform takes care of deployment, monitoring and manages your services given the rules and roles you have defined.&lt;br /&gt;The goal is to keep a service responsive and healthy during failures and upgrades. It is even possible to go into &amp;quot;raw&amp;quot; mode and build your own virtual machine and start managing your services yourself.&lt;/li&gt; &lt;li&gt;&lt;strong&gt;Powerful service hosting environment&lt;br /&gt;&lt;/strong&gt;Based on Hyper-V virtualization.&lt;/li&gt; &lt;li&gt;&lt;strong&gt;Scalable available cloud storage&lt;br /&gt;&lt;/strong&gt;You will be given simple storage abstractions. There are blobs (later on also file streams for videos and such stuff) for large data items, service state using tables (and caches) and queues.&lt;br /&gt;There is an emphasis on massive scale, availability, durability. Important to say that it is not a database in the cloud.&lt;/li&gt; &lt;li&gt;&lt;strong&gt;Develop as you are used to develop&lt;br /&gt;&lt;/strong&gt;You get to run a simulated cloud environment on your developer desktop. ASP.NET Furthermore there is a ecosystem of tools and support, ranging from integration with VS. To help you debug a live service (not very wise to really debug such things) you can use logging and alerts (later on tracing as well). Plus we should get the usual documentation and community sources.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The Technical Preview will start this noon with only limited resources for the first period. The features that matter most are important in this preview are: VMs with dedicated resources, a simple service architectures and a single large datacenter on the west coast of the United States. Initially you can use managed code, but native code will be services later on as well.&lt;/p&gt; &lt;p&gt;In the end there will be a commercial release. This means you will have to pay for these services.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=2948" width="1" height="1"&gt;</description></item><item><title>Some notes on routing in classic ASP.NET web applications</title><link>http://www.alexthissen.nl/blogs/main/archive/2008/10/20/some-notes-on-routing-in-classic-asp-net-web-applications.aspx</link><pubDate>Mon, 20 Oct 2008 21:27:00 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:2947</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>1</slash:comments><description>&lt;p&gt;Routing in .NET 3.5 SP1 differs from regular request handling in many ways. Here&amp;#39;s a quick outline how routing works:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Routes define some URL matching pattern and are configured/held in an ordered list accessible through RouteTable.Routes&lt;/li&gt;
&lt;li&gt;Incoming requests pass through the UrlRoutingModule that will walk the route table and will try to find the first match&lt;/li&gt;
&lt;li&gt;If a match was made, the route can extract values from the URL and store these in a RouteData object under the Values properties (there is more to store in a RouteData, but that&amp;#39;s beyond the basics)&lt;/li&gt;
&lt;li&gt;Assuming a match was made, the route determines the HTTP handler class&lt;/li&gt;
&lt;li&gt;The HTTP handler is passed the RouteData and is called to handle the request.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When you use System.Web.Routing in a &amp;quot;classic&amp;quot; web application, you will need a special kind of http handler class to leverage the new RouteData. (Quick tip: you might not need the Request.QueryString in your handler any more, as you can extract that information when determining the route data.). For Web Forms you can find the WebFormRouteHandler implementation in the &amp;quot;&lt;a href="http://haacked.com/archive/2008/03/11/using-routing-with-webforms.aspx" target="_blank"&gt;Using Routing with WebForms&lt;/a&gt;&amp;quot; article by &lt;a href="http://haacked.com" target="_blank"&gt;Phil Haack&lt;/a&gt;. The route handler by Phil expects the interface IRoutablePage on the web page so it can stick the RequestContext in it (step 4-5).&lt;/p&gt;
&lt;p&gt;But, as soon as you have a custom http handler implementation, you are left empty handed again. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_2.png"&gt;&lt;img height="141" width="456" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb.png" alt="image" border="0" style="border-bottom:0px;border-left:0px;border-top:0px;border-right:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Phil&amp;#39;s implementation assumes two things: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A System.Web.UI.Page derived class.&lt;/li&gt;
&lt;li&gt;A registered http handler endpoint (either through an .ashx file or via web.config&amp;#39;s &amp;lt;httpHandlers&amp;gt; section)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is a quick fix for Phil&amp;#39;s code for the first bullet: simply change line 46 to become:&lt;/p&gt;
&lt;div style="border-bottom:#cccccc 1pt solid;border-left:#cccccc 1pt solid;padding-bottom:1pt;padding-left:1pt;width:100%;padding-right:1pt;font-family:consolas;background:#f5f5f5;color:black;font-size:10pt;border-top:#cccccc 1pt solid;border-right:#cccccc 1pt solid;padding-top:1pt;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;var&lt;/span&gt; page = &lt;span style="color:#2b91af;"&gt;BuildManager&lt;/span&gt;.CreateInstanceFromVirtualPath(virtualPath, &lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:#2b91af;"&gt;IRoutablePage&lt;/span&gt;)) &lt;span style="color:blue;"&gt;as&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IHttpHandler&lt;/span&gt;;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I would also recommend changing some names. The IRoutablePage interface could be IRoutableHttpHandler and the WebFormRouteHandler could be ClassicRouteHandler, or whatever tickles your fancy.&lt;/p&gt;
&lt;p&gt;Bullet 2 is hard to bypass. You need to make peace with that assumption. It should be OK for everyday scenarios.&lt;/p&gt;
&lt;p&gt;To complement this, I quickly wrote up a generic base class and corresponding interface to allow you to write a custom handler using System.Web.Routing without the need to have this registered anywhere. This will give you tremendous freedom for hooking up a custom HTTP handler. (You will have to come up with an example, because I can&amp;#39;t think of one, except you or me being too lazy to do the registration in the web.config. Well, I can, but that involves some crazy on-the-fly generation of handlers that no-one wants. Or do they?)&lt;/p&gt;
&lt;p&gt;The interface IRoutableHttpHandler should be implemented by the HTTP handler instead of IHttpHandler.&lt;/p&gt;
&lt;div style="border-bottom:#cccccc 1pt solid;border-left:#cccccc 1pt solid;padding-bottom:1pt;padding-left:1pt;width:100%;padding-right:1pt;font-family:consolas;background:#f5f5f5;color:black;font-size:10pt;border-top:#cccccc 1pt solid;border-right:#cccccc 1pt solid;padding-top:1pt;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;interface&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IRoutableHttpHandler&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;IHttpHandler&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;{&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; RequestContext RequestContext { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Very similar to the IRoutablePage of Phil (it is exactly similar if you followed my suggested renaming of his code). &lt;/p&gt;
&lt;div style="border-bottom:#cccccc 1pt solid;border-left:#cccccc 1pt solid;padding-bottom:1pt;padding-left:1pt;width:100%;padding-right:1pt;font-family:consolas;background:#f5f5f5;color:black;font-size:10pt;border-top:#cccccc 1pt solid;border-right:#cccccc 1pt solid;padding-top:1pt;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;MySuperbadCustomHandler&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;IRoutableHttpHandler&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;{&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; ProcessRequest(&lt;span style="color:#2b91af;"&gt;HttpContext&lt;/span&gt; context)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; context.Response.ContentType = &lt;span style="color:#a31515;"&gt;&amp;quot;text/plain&amp;quot;&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; context.Response.Write(&lt;span style="color:#a31515;"&gt;&amp;quot;I&amp;#39;m superbad&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; IsReusable&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;get&lt;/span&gt; { &lt;span style="color:blue;"&gt;return&lt;/span&gt; &lt;span style="color:blue;"&gt;false&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp; #region&lt;/span&gt; IRoutableHttpHandler Members&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;RequestContext&lt;/span&gt; RequestContext { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp; #endregion&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Above is a rather silly custom HTTP handler, but it should be clear where to put your stuff. (No, I&amp;#39;m not telling)&lt;/p&gt;
&lt;p&gt;The generic route handler looks like this:&lt;/p&gt;
&lt;div style="border-bottom:#cccccc 1pt solid;border-left:#cccccc 1pt solid;padding-bottom:1pt;padding-left:1pt;width:100%;padding-right:1pt;font-family:consolas;background:#f5f5f5;color:black;font-size:10pt;border-top:#cccccc 1pt solid;border-right:#cccccc 1pt solid;padding-top:1pt;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;GenericHttpRouteHandler&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style="color:#2b91af;"&gt;IRouteHandler&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &lt;span style="color:blue;"&gt;where&lt;/span&gt; T : &lt;span style="color:#2b91af;"&gt;IRoutableHttpHandler&lt;/span&gt;, &lt;span style="color:blue;"&gt;new&lt;/span&gt;()&lt;/p&gt;
&lt;p style="margin:0px;"&gt;{&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp; #region&lt;/span&gt; IRouteHandler Members&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IHttpHandler&lt;/span&gt; GetHttpHandler(&lt;span style="color:#2b91af;"&gt;RequestContext&lt;/span&gt; requestContext)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T handler = &lt;span style="color:blue;"&gt;new&lt;/span&gt; T();&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; handler.RequestContext = requestContext;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; handler;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp; #endregion&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Your route should use this handler and specify the custom HTTP handler as the generic T type. Here&amp;#39;s a sample:&lt;/p&gt;
&lt;div style="border-bottom:#cccccc 1pt solid;border-left:#cccccc 1pt solid;padding-bottom:1pt;padding-left:1pt;width:100%;padding-right:1pt;font-family:consolas;background:#f5f5f5;color:black;font-size:10pt;border-top:#cccccc 1pt solid;border-right:#cccccc 1pt solid;padding-top:1pt;"&gt;
&lt;p style="margin:0px;"&gt;routes.Add(&lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Route&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;sweet&amp;quot;&lt;/span&gt;, &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;GenericHttpRouteHandler&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;MySuperbadCustomHandler&lt;/span&gt;&amp;gt;()));&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Small and simple, so there must be a catch. Yep, there is one major one: without a known endpoint it is hard to do the authorization (file or url) based access checks. So, in essence anyone can access the HTTP handler. Not to be used for secured resources. You have been warned.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=2947" width="1" height="1"&gt;</description><enclosure url="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.00.29.47/ClassicASPNETrouting.zip" length="14446" type="application/x-zip-compressed" /><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/ASP.NET+2.0/default.aspx">ASP.NET 2.0</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+3.5+SP1/default.aspx">.NET FX 3.5 SP1</category></item><item><title>SDN Conference 2008</title><link>http://www.alexthissen.nl/blogs/main/archive/2008/10/12/sdn-conference-2008.aspx</link><pubDate>Sun, 12 Oct 2008 20:28:29 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:2946</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;This year&amp;#39;s edition was great, maybe even the nicest ever. Noordwijkerhout and its hotel annex conference venue are a great place to stay. The previous years at Papendal, Arnhem were very nice, but I guess this one tops it.&lt;/p&gt; &lt;p&gt;Anyway, I met loads of people, from famous to acquaintances from the community, the ones I met on projects, courses or coaching gigs. To name just a few:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a target="_blank" href="http://www.thedatafarm.com/blog/"&gt;Julie Lerman&lt;/a&gt;: had loads of very long and good conversations on the Entity Framework (what else?) and ways to tell people the vision and overview of EF.&lt;/li&gt; &lt;li&gt;&lt;a target="_blank" href="http://www.dennisdoomen.net/"&gt;Dennis Doomen&lt;/a&gt;: yes, &lt;a target="_blank" href="http://www.dennisdoomen.net/2005/08/alex-thissen-is-alive.html"&gt;I am still alive&lt;/a&gt;.&lt;/li&gt; &lt;li&gt;Taco Ditiecher&lt;/li&gt; &lt;li&gt;Jean-Pierre Broeders&lt;/li&gt; &lt;li&gt;Donald Hessing&lt;/li&gt; &lt;li&gt;&lt;a target="_blank" href="http://www.sharepointblogs.com/mirjam/default.aspx"&gt;Mirjam van Olst&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Many, many more, mostly the regulars. Hopefully you/these don&amp;#39;t mind that you&amp;#39;re not in the list. It&amp;#39;s just that I expected to meet you there.&lt;/p&gt; &lt;p&gt;I&amp;#39;ve uploaded the slides and demos to my sessions:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Introduction to ASP.NET (&lt;a target="_blank" href="http://www.alexthissen.nl/media/p/2942.aspx"&gt;demos&lt;/a&gt;, for slides see the nearly identical &lt;a target="_blank" href="http://www.alexthissen.nl/media/p/2910.aspx"&gt;DevDays slides&lt;/a&gt;)&lt;/li&gt; &lt;li&gt;Technology Deatmatch (&lt;a target="_blank" href="http://www.alexthissen.nl/media/p/2943.aspx"&gt;slides&lt;/a&gt; only, don&amp;#39;t expect too much in these)&lt;/li&gt; &lt;li&gt;Introduction to Unity 1.1 (&lt;a target="_blank" href="http://www.alexthissen.nl/media/p/2944.aspx"&gt;slides&lt;/a&gt; and &lt;a target="_blank" href="http://www.alexthissen.nl/media/p/2945.aspx"&gt;demos&lt;/a&gt;)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Everyone, thanks very much for spending the time to come see my sessions and/or talk to me. I appreciate it.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=2946" width="1" height="1"&gt;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Talks/default.aspx">Talks</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Conferences/default.aspx">Conferences</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/O_2F00_R+Mapping/default.aspx">O/R Mapping</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Community/default.aspx">Community</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Unity/default.aspx">Unity</category></item><item><title>Golden Oldie: Dynamically generated thumbnails article</title><link>http://www.alexthissen.nl/blogs/main/archive/2008/08/30/golden-oldie-dynamically-generated-thumbnails-article.aspx</link><pubDate>Sat, 30 Aug 2008 09:20:49 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:2937</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_2.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;margin:0px 0px 10px 10px;border-top:0px;border-right:0px;" border="0" alt="image" align="right" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/image_5F00_thumb.png" width="240" height="136" /&gt;&lt;/a&gt;Related to &lt;a target="_blank" href="http://www.alexthissen.nl/blogs/main/archive/2008/08/29/trivia-fact-asp-net-dynamic-images-retro.aspx"&gt;my previous post on dynamic images&lt;/a&gt;, a long way back I wrote a two-part article for the now deceased (paid) website &lt;a target="_blank" href="http://www.asptoday.com"&gt;ASPToday&lt;/a&gt;. It was about a HttpHandler implementation that would generate a thumbnail image from an existing image. The handler was accompanied by a server control that would allow you to specify the original image as the source. The thumbnail is then created on-the-fly during run-time automatically. Since ASPToday is no longer online, I have posted the article &amp;quot;&lt;a target="_blank" href="http://www.alexthissen.nl/media/p/2934.aspx"&gt;Developing a custom ASP.NET Web control for thumbnails&lt;/a&gt;&amp;quot; in one piece under &lt;a target="_blank" href="http://www.alexthissen.nl/media/5/default.aspx"&gt;my blog downloads&lt;/a&gt;. There&amp;#39;s &lt;a target="_blank" href="http://www.alexthissen.nl/media/p/2935.aspx"&gt;source code&lt;/a&gt; to go with it as well. It&amp;#39;s an old article as I finished writing it in November 2003. Still a good read I hope (and in English). &lt;/p&gt; &lt;p&gt;Also, when you start generating your thumbnail images in an http handler using the new ASP.NET version for dynamic images (or my simpler implementation for that matter), give Matt&amp;#39;s article &amp;quot;&lt;a target="_blank" href="http://www.thebrainparasite.com/post/Creating-great-thumbnails-in-ASPNET.aspx"&gt;Creating great thumbnails in ASP.NET&lt;/a&gt;&amp;quot; a read. You&amp;#39;ll find it worthwhile.&lt;/p&gt; &lt;ul&gt;&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=2937" width="1" height="1"&gt;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/ASP.NET+2.0/default.aspx">ASP.NET 2.0</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+2.0/default.aspx">.NET FX 2.0</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Community/default.aspx">Community</category></item><item><title>Trivia fact: ASP.NET dynamic images retro</title><link>http://www.alexthissen.nl/blogs/main/archive/2008/08/29/trivia-fact-asp-net-dynamic-images-retro.aspx</link><pubDate>Fri, 29 Aug 2008 20:56:06 GMT</pubDate><guid isPermaLink="false">badf6229-ffeb-484a-8c5a-fc9c9987c8f2:2936</guid><dc:creator>Alex Thissen</dc:creator><slash:comments>2</slash:comments><description>&lt;p&gt;You can find a nice release of the ASP.NET team for &lt;a target="_blank" href="http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=16449"&gt;dynamically generated images for web applications&lt;/a&gt; on the Codeplex website. Others have already blogged about this, such as &lt;a target="_blank" href="http://www.hanselman.com/blog/ASPNETFuturesGeneratingDynamicImagesWithHttpHandlersGetsEasier.aspx"&gt;Scott Hanselman&lt;/a&gt; and &lt;a target="_blank" href="http://davidhayden.com/blog/dave/archive/2008/08/27/ASPNETImageGenerationGenerateImagesGetImagesDatabaseTransformImages.aspx"&gt;David Hayden&lt;/a&gt;, so I&amp;#39;m not going to repeat that. I do want to add some information to this though.&lt;/p&gt; &lt;p&gt;It&amp;#39;s a &amp;quot;Did you know that...&amp;quot; trivia fact. This will get the attention of everybody on the parties that I happen to visit. It might do the same for you. Here goes: &lt;u&gt;did you know that&lt;/u&gt; up until .NET Framework version 2.0.40301 (Alpha release of March 2004) there was an entire System.Web.UI.Imaging namespace dedicated to generating images?&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/SystemWebUIImaging_5F00_2.png"&gt;&lt;img style="border-right-width:0px;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" border="0" alt="SystemWebUIImaging" src="http://www.alexthissen.nl/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/main/SystemWebUIImaging_5F00_thumb.png" width="289" height="161" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In fact, there was even more. The System.Web.Handlers namespace contained a handler DynamicContentHandler and there was a DynamicImage control to go with the handler that had the following options:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Specify the image as an System.Drawing.Image, Byte[] or filename.&lt;/li&gt; &lt;li&gt;Separate scaling for both desktop and mobile browsers.&lt;/li&gt; &lt;li&gt;Store the generated image in cache or on disk.&lt;/li&gt; &lt;li&gt;Retrieve parameters from the querystring or the storage format (from the bullet above)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Look at the content of the now released Microsoft.Web.GeneratedImage.dll assembly and tell me if you find similar things. Mind you, the new implementation is definitely what should/could have been built in ASP.NET 2.0: it&amp;#39;s all 2.0-ish now, databinding and generics and stuff. You know, the good things.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://www.alexthissen.nl/aggbug.aspx?PostID=2936" width="1" height="1"&gt;</description><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/Humor/default.aspx">Humor</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/ASP.NET+2.0/default.aspx">ASP.NET 2.0</category><category domain="http://www.alexthissen.nl/blogs/main/archive/tags/.NET+FX+2.0/default.aspx">.NET FX 2.0</category></item></channel></rss>