Random ramblings about Technology

  • Feedback requested: Planning on Enterprise Library 5 has started!

    Planning on Enterprise Library 5 has started! See Gregori's blog for more information if you want your EntLib needs to be in the next release: http://blogs.msdn.com/agile/archive/2009/01/26/enterprise-library-5-what-s-on-your-wish-list.aspx!

  • Reflector add-in: Favorites

    Every developer knows about and uses Reflector ;-) I use it a lot to learn about the inner workings of products. When analyzing what goes where and why, it's easy to lose track (jumping from method to method to base class, etc.). Bookmarks are quick and easy, but don't allow for a description to be added. If I need to get back to a certain point within my analysis two weeks (ok, ok, two minutes ;-)) later, the Type declaration from the bookmarks doesn't help me.

    Meet Reflector Favorites!

    I wrote Reflector Favorites. It allows for developers to:

    • Easily tag a location within Reflector, adding a description that works for you.
    • Import/Export favorites between computers.
    • Share favorites (they work as long as you have the right assemblies opened in Reflector).

    reflector_001 reflector_002

    Reflector Favorites in action.

    reflector_003

    I hope someone finds this useful. As always, use at your own risk, no warranties of any kind.

     

  • Suppressing Personal Identifiable Information (PII) in WCF log files

    Given the vast amount of information transported between systems in today's enterprise environments, a lot of which is considered either private (addresses, social security numbers, credit card information, mortgage and pension plans, etc) or of high business value, information security is key.

    From the release of WCF, it has brought us tremendous flexibility and allowed development teams to be almost completely agnostic of the way information is transported between point A to point B, focusing on adding business value instead.

    Another great feature WCF brings us is runtime troubleshooting. In WCF, an administrator can simply enable logging to troubleshoot an environment which is in production.

    Although a great feature for troubleshooting, Personal Identifiable Information (PII) you care about deeply while on the wire (using transport and message-level security to protect it) is available in plain text if logging is turned on at the server side.

    WCF's logging features currently filter out specific PII by default (only if the message is not malformed). However, this functionality is not exposed to the developer.

    Consider the following scenario:

    • You want the administrator to be able to monitor messages for auditing, logging or troubleshooting purposes;
    • certain information is considered PII and should not show up in the log files.

    You could write your own logging subsystem and hook it in to your services. This takes a lot of work, is error prone, needs custom maintenance, documentation, etc.

    My proposal for the scenario:

    • Use a behavior which
      • introspects the published ServiceEndPoints for published OperationDescriptions and the used DataContracts,
      • finds public properties on the DataContract marked as PII;
      • instructs the WCF logging runtime to ignore the contents of the specified message elements.
    • configure the behavior through code (this is not generally considered a best practice, but the security needs of the service outweighs the flexibility needs of configuration);

    Let's have a look at how the solution works:

    Take a DataContract, e.g. PurchaseOrder and apply an attribute (PII) on each property which represents PII.

    wcf_pii_datacontract

    Next, add a PIIProtectionBehavior attribute to your service implementation class

    wcf_pii_protectionbehavior_attribute

    You're done. The PIIProtectionBehavior attribute is also an IServiceBehavior implementation which performs the introspection on the EndPoints.

    The result when logging is turned on:

    wcf_pii_messagelogging

    As you can see, 'CreditCardnumber' is no longer logged, it just displays '<-- Removed -->' .

    I've attached the sample code, hope it's useful!

    Ofcourse, the normal disclaimers apply, the accompanied sample is for educational purposes only, it has not gone through rigorous testing, might contain bugs due to limited testing (me ;-)), etc. Please see the sourcecode for further remarks.

  • Adding a new BizTalk Server Isolated Host needs a new Application Pool

    Recently, we tried creating a secondary Isolated Host to separate receive and send processing for WCF. After reconfiguring the servers, we were faced with the "Receive location for address '' not found. (The BizTalk receive location may be disabled)". Puzzled, we looked around for configuration issues. After some reading (http://technet.microsoft.com/en-us/library/aa559328.aspx), we remembered a new isolated host needs a new application pool. Adding another application pool to the mix the the new host fixed our trouble... Jotted down for posterity ;-)
  • Running Virtual Machines under alternate user credentials on a Domain Controller

    Introduction

    Recently, I was experimenting with Team Foundation Server 2008, setting it up with SSL and running it within a test domain. For the Team Foundation Server, I couldn't use the host installation as it runs Windows Server 2003 R2 x64 edition and TFS doesn't support (see the TFS installation guide, under 'Overview of Team Foundation Architecture', '64-bit Support in Team Foundation') this setup in a single server scenario. So, I installed Virtual Server 2005 R2 SP1, installed TFS on top, configure SSL and voila, a working TFS setup.

    When I shut down the host computer, I want the virtual machine of TFS to save state and come back up again when the host is turned on again. This can be done in Virtual Server using an alternative use running the actual Virtual Machine instance. Trying to set this up in a least privilege way proved not to be obvious from documentation, so this blog entry documents what I did for posterity (and myself ;-)).

    Outline

    Here's what needs to be done in order to circumvent obscure error messages:

    1.       We need a new user group so the account we'll use doesn't belong to default domain users and inherits no permissions.

    2.       We need a new user to run the Virtual Machine instance, the user should belong to this group only.

    3.       The user needs to be given 'Local on locally' rights.

    4.       Permissions need to be set on the folder containing network configuration information for Virtual Server.

    5.       Permissions need to be set on the folder containing the Virtual Machine and the actual files (*.vhd, .vmc) making up the Virtual Machine.

    6.       The Virtual Machine needs to be configured to use the new user.

    Instuctions

    Let's configure the necessary elements.

    1. Create a new group

    Create a new group within the Active Directory Users and Computers MMC snapin (found under Administration Tools):

    emptygroup

    2. Create a new user

    Create the user which is to run the specific Virtual Machine (done from the same MMC snap-in), add it to the 'empty' group, set the 'empty' group as it's Primary Group and remove the 'Domain Users' group from the list. After this, your user overview should resemble this image:

    vmuser

    3. Assign 'Log on locally' rights to the user

    This step is critical in getting the Virtual Machine running under the new user context. Steps to achieve the appropriate right setting are described here. If the user doesn't receive the 'Log on locally' right, Virtual Server will display an error: 'The account name and password could not be set. The virtual machine account could not be set. The account has not been granted the requested logon type.'. Make sure the security policy is updated before using the account.

    4. Set permissions for the used virtual network interface

    Now that we have the user and it's group configured, let's set the appropriate permissions for the user to make use of the configured network. Mind you, these instructions will only allow the user to use the network it's given access to from the instructions, the 'local network only' et al will not work as the user has no rights on the files used for those configurations.

    The virtual network configuration files for Virtual Server are stored in %SystemDrive%\Documents and Settings\All Users\Application Data\Microsoft\Virtual Server\Virtual Networks. The user needs permissions as specified in order to use the network. If permissions are set incorrectly, the Virtual Machine will not have network access.

    networkpermissions

    5. Set permissions on Virtual Machine folders and files

    In order to start up the Virtual Machine, save state, etc, the new user needs access rights on the folder storing the actual files making up the Virtual Machine as well as specific rights on the Virtual Machine files. The folder structure containing my Virtual Machine files is:

    %SystemDrive%\vms\<Virtual Machine>

    First, let's set the appropriate rights on the folder hosting all Virtual Machines:

    mainvmfolderpermissions

    Now, let's set the permissions for the appropriate Virtual Machine ('tfs') folder:

    vmfolderpermissions

    Lastly, set up permissions for the Virtual Machine files (my TFS has 3: tfs.vmc, tfs.vhd and sql.vhd):

    vmpermissions

    6. Configure the Virtual Machine

    All permissions are set, we're ready to configure Virtual Server to run the Virtual Machine under the new user context:

    configure virtual machine

    Wrap up

    That's it! We've configured the Virtual Machine to run under a user context which has the least amount of privileges it needs to function correctly. The Virtual Machine will save it's state when the host is shut down and will automatically turn back on when the host comes back online.

    HTH

  • Fixing exception messages on the .NET Compact Framework 3.5

    FWIW: I recently ran into trouble while developing for the .NET Compact Framework, v3.5. Upon all exceptions, the framework would tell me:

    "An error message is available for this exception but cannot be displayed because these messages are optional and are not currently installed on this device. Please install ‘NETCFv35.Messages.EN.wm.cab’ for Windows Mobile 5.0 and above or  ‘NETCFv35.Messages.EN.cab’ for other platforms. Restart the application to see the message."

    Interpreting the message as 'I have to run the NETCFv35.Messages.EN.wm.cab (I'm developing an application for WM6) on my device', I copied the file from C:\Program Files (x86)\Microsoft.NET\SDK\CompactFramework\v3.5\WindowsCE\Diagnostics onto my mobile device and ran the installation.

    To no avail, nothing changed and I was stuck. After installing the 'Power Toys for .NET Compact Framework 3.5', however, I configured logging using the '.NETCF Logging Configuration' application and found the following error for the loader log:

    'Attempt to load [\Program Files\SomeApp\System.SR.dll] has failed (err 0x80001000).'

    Renaming the file 'SYCCFA~1.001', included in the aforementioned CAB file into System.SR.dll and adding it as a reference in my application proved to fix the issue. I now had readable exception messages.

    Just jotting this down as there's nothing to be found on the web regarding the issue that I could find.

  • Testing WCF service implementations

    When writing WCF implementations, or any code for that matter, testing is an important part of the process. This week, I was building tests for implemented WCF services and had difficulty aligning all the external dependencies of the tests (running hosts, configuration settings, behavior component references, etc). As a result, I set up my WCF services to be self-hosted services, run from the context of the test itself. This has several advantages, and some pitfalls. The advantages:

     

    ·         Isolation, the test has external dependencies only to the actual service implementation.

    ·         No manual setup running hosts to ensure they are available, the test ‘just works’.

     

    The pitfall might be:

     

    ·       Configuration settings could become out-of-sync. Because the host of the service implementation runs within the context of the test and thereby it’s AppDomain, you need to configure the service ABCs within the test configuration file. This could mean over time you’d get configuration settings for the tests no longer in sync with the actual host.

     

    However, because the scope of the tests is under your control and so is it’s configuration, the described pitfall might not pose an issue.

     

    In order for the test to host it’s own instance of the services to be tested I created a generic container. It’s a simple, but effective, class which can easily host different service types (all tracing and the IDisposable implementation removed for clarity):

     

    /// <summary>

    /// Defines a generic implementation of a runnable background host.

    /// </summary>

    /// <typeparam name="T">The service to run within the host.</typeparam>

    public class RunnableBackgroundHost<T> : IDisposable where T : class, new()

    {

    internal AutoResetEvent stopEvent = new AutoResetEvent(false);

     

    /// <summary>

    /// Starts the host on a new thread.

    /// </summary>

    public void Run()

    {

                ThreadPool.QueueUserWorkItem(

    new WaitCallback(delegate(object state)

                {

                    using (ServiceHost host = new ServiceHost(typeof(T)))

                    {

                        host.Open();

     

                        stopEvent.WaitOne();

     

                        host.Close();

                    }

    }));

    }

     

    /// <summary>

    /// Stops the running host.

    /// </summary>

    public void Stop()

    {

    stopEvent.Set();

    }

    }

     

    Using this class, testing services become quite easy. Set up the host before starting the test:

     

    [System.Diagnostics.CodeAnalysis.SuppressMessage(

    "Microsoft.Performance",

    "CA1812:AvoidUninstantiatedInternalClasses"), TestClass]

    class HostInit

    {

    protected static RunnableBackgroundHost<Service1> service1;

    protected static RunnableBackgroundHost<Service2> service2;

     

    [AssemblyInitialize]

    public static void AssemblyInitalize(TestContext context)

    {

    service1 = new RunnableBackgroundHost<Service1>();

    service2 = new RunnableBackgroundHost<Service2>();

     

    service1.Run();

    service2.Run();

    }

     

    [AssemblyCleanup]

    public static void AssemblyCleanup()

    {

    service1.Stop();

    service2.Stop();

    }

    }

     

    And set up your test, using a generated proxy (svcutil) and assuming the service is alive:

     

    [TestClass]

    public class Service1Tests : IDisposable

    {

    private Service1Client service1Client;

     

    [TestInitialize]

    public void TestInitialize()

    {

    service1Client = new Service1Client();

    }

     

    [TestMethod]

    public void TestService1Method1()

    {

    Service1Request request = new Service1Request();

    request.Id = "1";

     

    Service1Response response = service1Client.Method1(request);

     

                Assert.IsNotNull(response, ErrorMessages.NullResponse);

                Assert.AreEqual<int>(

    response.Field,

    1,

    ErrorMessages.NonMatchingId);

    }

    }

     

    ErrorMessages is a simple resource file containing the messages the test would display in case of failure.

     

    What the test framework does in this case:

     

    ·         Call the static method HostInit.AssemblyInitalize marked with [AssemblyInitialize].

    ·         For every class within the test marked with [TestClass]

    o    Call any instance method marked with [TestInitialize].

    o    Run any method marked with [TestMethod].

    o    ...

    ·         Call the static method HostInit.AssemblyCleanup marked with [AssemblyCleanup].

     

    Within the test configuration file, configure both the service host and the client:

     

    <system.serviceModel>

    <client>

    <endpoint

    address="http://localhost:8889/Services/Service1"

    binding="basicHttpBinding"

    contract="IService1" />

    </client>

    <services>

    <service name="Service1">

    <endpoint

    address="http://localhost:8889/Services/Service1"

    binding="basicHttpBinding"

    contract="IService1" />

                      </service>

    </services>

    </system.serviceModel>

     

    That’s the basic setup. You can now easily test different services by defining the tests for it in it’s own class using it’s own generated client proxy and adding the service to the HostInit class. You could test behaviors by adding them to the configuration file and writing a test for them if they can be tested from the outside.

     

    Just press SHIFT+ALT+X to run the test in the debugger. No console windows popping up, your test just executes :).

  • WCF Message validation (1) – WCF samples to the rescue

    Recently, I needed to validatie messages going into a WCF service. It turned out the WCF samples are a rich source of knowledge and I found a sample which performs XMLSchema-based validation in \TechnologySamples\Extensibility\MessageInspectors.

     

    The sample contains a few classes:

    • ClientValidationException.cs
      • Defines exceptions where validation fails clientside
    • SchemaValidationBehavior.cs
      • Defines an implementation of IEndpointBehavior in order to be an extender for defined endpoints
    • SchemaValidationBehaviorExtensionElement.cs
    • SchemaValidationMessageInspector.cs
    • ValidationFault.cs

    The sample uses a property called Schemas within it’s configuration, allowing us to define which schemas should be taken into account when validating.

     

    <schemaValidator validateRequest="True" validateReply="True">

    <schemas>

    <add location="messages.xsd" /> 

    </schemas>

    </schemaValidator>

     

    That’s great, but as you all probably know, WCF services have the ABC’s: Address, Binding and Contract. What I actually wanted the behavior to do was validate my message against the actual Contract of the endpoint the validator was working on.

    In order for this to work, I did two thing:

     

    1.       I removed all “Schemas” configuration and arguments from the code.

    2.       I modified the SchemaValidationBehavior class to validate the actual contract.

     

    The first steps should be self-explanatory, but the second I want to elaborate on. What I actually did was modify the methods ApplyClientBehavior and ApplyDispatchBehavior. The sample took the configured Schemas property to create the actual SchemaValidationMessageInspector:

     

    SchemaValidationMessageInspector inspector =

    new SchemaValidationMessageInspector(

    schemaSet, validateRequest, validateReply, false);

     

    I wanted to dynamically use the endpoint contract:

     

    WsdlExporter exporter = new WsdlExporter();

    exporter.ExportContract(endpoint.Contract);

     

    SchemaValidationMessageInspector inspector =

    new SchemaValidationMessageInspector(

    exporter.GeneratedXmlSchemas,

    validateRequest, validateReply, false);

     

    After modifying both methods to perform this kind of setup, it was easy to configure validation based on the endpoint contract (some elements abbreviated for clarity):

     

    <system.serviceModel>

    <services>

    <service name="SomeService">

    <endpoint

    address="SomeAddress"

    binding="wsHttpBinding"

    contract=" ISomeService"

    behaviorConfiguration="SomeServiceEndpointBehavior" />

    </service>

    </services>

     

    <behaviors>

    <endpointBehaviors>

    <behavior name="SomeServiceEndpointBehavior">

    <SchemaValidator

    validateRequest="True"

    validateReply="True" />

    </behavior>

    </endpointBehaviors>

    </behaviors>

     

    <extensions>

    <behaviorExtensions>

    <add

    name="SchemaValidator"

    type="SchemaValidationBehaviorExtensionElement, ..."/>

    </behaviorExtensions>

    </extensions>

    </system.serviceModel>

     

    That’s it, now we have a service endpoint validated based on it’s WSDL contract.

     

    The sample code is attached for your enjoyment.

  • Shockwave Flash preview handler for Windows Vista and Outlook 2007.

    Based on the excellent article from Stephen Toub, I was inspired to write a Shockwave Flash preview handler. Basically, it's just a plain UserControl which hosts the ActiveX wrapper for the player. It works from both Outlook 2007 and Windows Vista. The installer is attached.

    Shockwave Flash preview handler in action

  • Programmatic BizTalk Server Orchestrations - code repost

    A previous post of mine had some sample code on creating BizTalk Server Orchestrations programmatically, opening up template based guidance packages. The sourcecode for the sample can now be found here.

  • BizTalk Server Pipeline Component Wizard moved

    As we are phasing out GotDotNet, projects need a new location to be hosted. I've moved the BizTalk Server Pipeline Component Wizard to it's new location. Please find it here.
  • CAB WPF XBAP implementation available (again)

    In the time to come, I'll be uploading packages available from my previous blog in the past because they got lost during my ISP transfer. First off, here's the CompositeUI Application Block XBAP WPF implementation, as I blogged about here.

    Please note the passwords for both protected signing keys are empty within the solution.

    This posting is provided "AS IS" with no warranties, and confers no rights.

  • Integration Masterclass Redelivery

    Microsoft Consulting Services in The Netherlands has developed a great integration masterclass, in which integration specialists compare Microsoft integration technologies and deliver real-world field experience in BizTalk Server implementations including best practices, tips and tricks. Check out the webpage at http://www.microsoft.com/netherlands/evenementen/integration.aspx for more information (Dutch content).

  • Ping!

    Welcome to my blog. My name is Martijn Hoogendoorn, I work for the Dutch Services dvision of Microsoft and will be posting my technical adventures on here. I've been blogging for some time now; previous posts can be found here (archive only).

© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker