>
 Saturday, July 11, 2009

Thanks to a customer of mine (thank you Christoph!) some major improvements have been made to the ExceptionHandlingProxyBase type. Plus, a duplex version now exists. Nothing like using the code in production to work through the real limitations. I knew I had to add a lot of these things, but this week I had a good reason to do it.

The proxy generator can be found at http://wcfproxygenerator.codeplex.com

Invoke() and Value Types
**I had a problem surface when I tried to return a value type (not a reference type) from Invoke(). I created this dependency in the generic method by requiring the generic type parameter to be a class. I changed this so now you can use value types freely.

Thread Safety
** A lock is used for all calls that touch the channel. But you can have parallel calls through Invoke() of course.
** Now you can safely have parallel calls to invoke, but if one thread encounters an exception other threads queue up before invoking the operation until the proxy is safely recreated.
** Disposal is now safe in multithreading environments.

Disposal
** Now all operations check if the object is disposed and throws if it is.

Initialization
** Now constructors call virtual Initialize() methods to support scenarios where the derived class wants to calculate values before calling down to base.
** Initialization only supported once.

Creation and Recreation
** Now the two are considered different so that we can enforce creation only once, while allowing multiple recreation attempts. Recreation also uses a lock to protect Invoke() and fires an event after so clients can do other work after recreation, such as subscribing to a service after the proxy is recreated.

Communication Events
** Clients can subscribe to these events even if channel isn't created yet. Events from the inner channel are fired to listeners.

Support for Message parameter type
** Invoke() retries didn't work if you had a contract that supports Message type. That's because you can't "replay" a Message instance, once it is read, it cannot be read again. There are two possible ways to handle this:
a) Buffer the message before each first attempt to invoke and create a copy of the message for the first and (if applicable) second call. But, this means buffering unnecessarily when things are going well.
b) allow the application to buffer in the derived type when using Message types. Then, subscribe to the RetryInvoke (new) event and supply a message before retry.
** I implemented b).

Hope you like it! Cheers!

7/11/2009 1:19 PM  | Comments [0]  |  View reactions  |  Trackback
 Thursday, July 02, 2009

The cool thing about creating an add-in for my exception handling proxy is that now it makes it easier for me to use it all the time when I create sample projects. Before, I would have to copy and paste the base type and hand-build the proxy, and this just wasn't realistic.

I'm blogging this because of course this also means I will uncover any bugs or missing features more quickly since I'm trying to use it everywhere. One such thing was that a change I made to my proxy wrapper to automate creating the channel in the constructor actually had a nasty side-effect that didn't surface until I tried to use it for a federated security sample. ClientCredentials was not accessible since the channel was already created. My bad.

I have since updated the proxy generator here: http://wcfproxygenerator.codeplex.com and there is a new release that includes the add-in sources in case you want to change how that works.

Even though I've been using this wrapper code in different incarnations for years, I am going to leave the codeplex site in Beta until I have tested with more scenarios. I think it is pretty stable though...aside from that little bug I introduced at the last minute. New code = more testing.

I'm loving using this everywhere, I hope you do to!

7/2/2009 4:31 PM  | Comments [15]  |  View reactions  |  Trackback
 Wednesday, July 01, 2009

I have never run into this problem before, but I just realized that in WCF applications when I provide a certificate reference with FindBySubjectName - it can fail if you have two similarly named (not identical) certificates. I don't think this is by design, it has to be a bug, but I found a workaround.

Short and Sweet...here it is. If I have a certificate reference like this for "RP":

<certificateReference findValue="RP" storeLocation="LocalMachine" 
storeName="My" x509FindType="FindBySubjectName"/>

But, I also have a cert named "RPSTS" in the same cert store, the lookup fails because it can't find a unique cert by the name RP. I don't know about you but I think "RP" and "RPSTS" are pretty unique...but not as far as WCF is concerned. I usually use FIndByThumbprint for production code, but for code samples and reference materials I want it to be obvious which cert we are dealing with, it is hard enough to trouble-shoot certs without having to look up thumbprints every time.

A workaround for this is to use FindBySubjectDistinguishedName so this works even if I have "CN=RP" and "CN=RPSTS" in my cert store.

<certificateReference findValue="CN=RP" storeLocation="LocalMachine" 
storeName="My" x509FindType="FindBySubjectDistinguishedName"/>

Shweet!

Technorati Tags: ,
7/1/2009 10:15 PM WCF  | Comments [1]  |  View reactions  |  Trackback
 Wednesday, June 24, 2009

Updated: 01/07/09 - adding WPF localization link below, and the others are really close...just final details taking forever

If you know where my technology focus lies you might be surprised to see the term WPF in my blog...I know, it's weird. But not really! You see I have been working on a rather large project to give WPF some love as it relates to my world - which means WCF, federated security, globalization/localization, and ClickOnce. Another part of this "client love" is WCF for mobile devices.

So far, I have the following projects published and ready to go:

  • WCF Guidance for Mobile Developers: http://wcfguidanceformobile.codeplex.com
    • This is fully legit! I worked with Nick Landry to bring the mobile love into this paper...and it is a word of art I think because the community has been really crying out for this content. Here you'll find a whitepaper and lots of code samples.
  • WCF Guidance for WPF Developers: http://wcfguidanceforwpf.codeplex.com
    • This site has a whitepaper, code samples and a short webcast series to bring WPF developers up to speed on necessary WCF topics. Some of it is intro, some of it is help to avoid common issues including proxies and exception handling, multithreading, proxy lifetime management, etc.
  • WPF ServiceHost: http://wpfservicehost.codeplex.com
    • This site has a few templates for WPF developers that need to either a) host a service in their client app, or b) host a service in their client app as part of a pub-sub scenario. Even if you don't need it today, check out the templates and tell me what you think on the codeplex site!
  • Exception Handling WCF Proxy Generator: http://wcfproxygenerator.codeplex.com
    • This has to be one of my favorite installments to this series! I have been using an evolving flavor of an exception handling proxy for years now, to help with proxy lifetime management and to hide unwanted exception from the user such as session timeouts or faulted channels that are not due to any serious communication issues. Basically, recreate the channel when it fails and try to recover. I finally (with the help of my friend Buddhike de Silva) put this into a nice Visual Studio Add-In. It currently works on Service References only, but I plan to add value later by making it work on any service contract in your solution...I'd love to know what you think of this one!
  • WPF Localization Guidance: http://wpflocalization.codeplex.com
    • There isn't much guidance for WPF and there are some choices to make that require explanation indeed. Rich Strahl, a good friend and one of the few people I know who care about localization as well, did most of the work on this paper. There may be some additions to this over the next few months as well.

There are a few more installments to come with this massive project. In the next week or so you'll see the following items that I have already well under way:

  • WPF and ClickOnce
  • WPF localization guidance
  • WPF and CardSpace
  • WPF and claims-based/federated security scenarios

Enjoy!

6/24/2009 7:03 PM  | Comments [7]  |  View reactions  |  Trackback
 Tuesday, June 23, 2009

I just returned from Oslo, Norway from the annual NDC. This was my first time speaking there but it was a really great venue in a stadium setup - and as always the organizers at Program Utvikling did a fantastic job....I will definitely go back! Great conference!

As promised here are links to the code samples for each sessions, and a PDF of the slide decks. Any questions? Email me!

All PDFs are zipped up here: http://www.dasblonde.net/downloads/NDCSlides.zip

A Lap Around Geneva Framework

Access Control Service

WCF Routers

Choosing the right Data Access Technology

Azure Session and Tutorial

6/23/2009 3:33 PM  | Comments [7]  |  View reactions  |  Trackback
 Friday, May 22, 2009

Here is my slightly belated session post from Tech Ed last week, including code samples for my tutorial (with Zoiner Tejada) and two other sessions.

Tutorial: WCF 4 + WF 4 + Dublin

DTL201 - A Strategic Comparison of Data Access Technologies

SOA309 - WCF Load Balancing and Scalability

5/22/2009 6:31 PM  | Comments [6]  |  View reactions  |  Trackback
 Saturday, April 18, 2009

A new CTP was released for .NET Services in March and as I update my Access Control Service (ACS) samples to reflect changes I thought I might post the relevant changes here to save all 5 of you devoted blog readers some time.

First off, the ACS has a new certificate, which means your web sites and WCF services that rely on ACS tokens must update their configuration to reflect the new thumbprint. The old thumbprint was 416e6fa5d982b096931fbf42c4a3dcd608856c95, and the new thumbprint is 6DE1689A739D548A5690DBC3894B953EF6123D93. So, if you provide trusted issuers in configuration, your <microsoft.identityModel> configuration must be updated to reflect this:

<microsoft.identityModel>
  <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry">
    <trustedIssuers>
      <add name=http://{yoursolutionname}.accesscontrol.windows.net thumbprint="6DE1689A739D548A5690DBC3894B953EF6123D93"/>
    </trustedIssuers>
  </issuerNameRegistry>

...more settings

</microsoft.identityModel>

If your trusted issuers are handled with a custom IssuerNameRegistry component, you might do something like this:

<issuerNameRegistry type="TrustedIssuerNameRegistry"/>

and the component:

public class TrustedIssuerNameRegistry : IssuerNameRegistry
{
    public override string GetIssuerName(SecurityToken securityToken)
    {
        X509SecurityToken x509Token = securityToken as X509SecurityToken;
        if (x509Token != null)
        {
            if (String.Equals(x509Token.Certificate.Thumbprint, "6DE1689A739D548A5690DBC3894B953EF6123D93"))
            {
                return x509Token.Certificate.SubjectName.Name;
            }
        }

        throw new SecurityTokenException("Untrusted issuer.");
    }
}

Another change is the issuer URI format for your hosted STS. What used to be: http://accesscontrol.windows.net/{yoursolutionname} is now http://{yoursolutionname}.accesscontrol.windows.net. Although this may not be an exhaustive list since likely every place you use your solution URI you will have to update this...here are some things I had to update related to the ACS:

1. Declarative trusted issuer entries (this value is used when the ClaimsPrincipal is generated, as the issuer for those claims):

<issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry">
  <trustedIssuers>
    <add name=http://{yoursolutionname}.accesscontrol.windows.net thumbprint="6DE1689A739D548A5690DBC3894B953EF6123D93"/>
  </trustedIssuers>
</issuerNameRegistry>

2. Addressing your passive STS URI, which in this example is the URI for passive federation with Live ID (I am told this will later change to Federation.aspx for all passive federation URI):

  <microsoft.identityModel>
        <federatedAuthentication enabled="true">
            <wsFederation passiveRedirectEnabled="true"
                    issuer=https://{yoursolutionname}.accesscontrol.windows.net/passivests/LiveFederation.aspx realm="http://localhost/PassiveACSWebSite" reply="http://localhost/PassiveACSWebSite/Default.aspx" ></wsFederation>
        </federatedAuthentication>
  </microsoft.identityModel>

3. I have a custom Saml11SecurityTokenHandler that validates that any ACS tokens are from MY solution and not other solutions signed with the same private key. You do this by checking the token's Issuer property as shown in my custom type. Below is the configuration to add the custom token handler and the implementation.

  <microsoft.identityModel>
  <securityTokenHandlers>
      <remove type="Microsoft.IdentityModel.Tokens.Saml11.Saml11SecurityTokenHandler, Microsoft.IdentityModel, Version=0.5.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add type="SecurityExtensions.ACSSamlTokenHandler, SecurityExtensions"/>
    </securityTokenHandlers>     
  </microsoft.identityModel>

public class ACSSamlTokenHandler: Saml11SecurityTokenHandler
{
    private string Issuer { get; set; }

    public ACSSamlTokenHandler()
        : this(new SamlSecurityTokenRequirement())
    {
    }

    public ACSSamlTokenHandler(SamlSecurityTokenRequirement samlSecurityTokenRequirement): base(samlSecurityTokenRequirement)
    {
    }

    public ACSSamlTokenHandler(XmlElement customConfiguration): base(customConfiguration)
    {
    }

    private void Initialize()
    {
        if (MicrosoftIdentityModelSection.Current != null)
        {
            IssuerNameRegistryElement trustedIssuersConfig = MicrosoftIdentityModelSection.Current.IssuerNameRegistry;
            string s = trustedIssuersConfig.ElementAsXml.ToString();

        }
    }

    public override Microsoft.IdentityModel.Claims.ClaimsIdentityCollection ValidateToken(System.IdentityModel.Tokens.SecurityToken token)
    {
        if (token == null)
            throw new ArgumentNullException("token");

        SamlSecurityToken samlToken = token as SamlSecurityToken;
        if (samlToken == null)
            throw new ArgumentException(string.Format("Argument cannot be null: {0}", "token"));

        if (!samlToken.Assertion.Issuer.Contains("http://{yoursolutionname}.accesscontrol.windows.net"))
        {
            throw new SecurityTokenException(string.Format("The token issuer {0} is not expected.", samlToken.Assertion.Issuer));
        }

        return base.ValidateToken(token);
    }
}

So if you are updating ACS samples, this may come in handy. Cheers!

4/18/2009 4:34 AM  | Comments [1]  |  View reactions  |  Trackback
 Friday, April 17, 2009

Well, almost immediately following the tutorials I delivered at SD West and Dev Connections in March, many of the CTPs that I discussed were updated...and so I had to find some time to get my docs updated to reflect the changes. I have finally pulled it together. This post will provide machine setup used for my technology roadmap seminar as of April 2009. Since many of these are CTP technologies, everything is subject to change…some things sooner than later.

Here is a link to a document with the setup links below, in addition to reference materials on each technology. http://www.dasblonde.net/downloads/idesigntechnologyroadmapresourcesv3.doc

I am still working on testing the azure samples with new CTPs before posting the zip with code here. Will update this post with a link.

Platform Setup

These instructions assume you are running on Windows Vista SP1 or Windows Server 2008. This section describes core machine setup for the operating system, .NET 3.0, SQL Server and Visual Studio.

F#

Parallel Computing

Entity Framework

Velocity

WPF

ASP.NET

Silverlight

WCF

Identity Platforms

Azure Services Platform

4/17/2009 4:57 PM  | Comments [1]  |  View reactions  |  Trackback
    ON THIS PAGE
    SEARCH
    CATEGORIES
    ARCHIVES
    BLOGROLL

Designed by NUKEATION STUDIOS