Taking Control of WCF Jay Hill Patrick Roeper
Presentation Goals Take the most common WCF experience and make it better – Leverage OO design principles; improve extensibility, maintainability, testability – Reduce repetition Demonstrate techniques when playing role of: – Publisher – Consumer – Publisher and Consumer
Demo Jay is recovering from star-trek-hand syndrome Occasional accidental- reboot while typing
Horizontal API MethodA(ReqA req) { Logger.Log(“Handling ReqA”); try { var result = new ResultA(); result.Name = GetName(req.Id); result. = Get (req.Id); return result; } catch (Exception ex) { Logger.LogError(ex); throw; } MethodB(ReqB req) { Logger.Log(“Handling ReqB”); try { return req.Role == GetRole(req.Id) ? new ResponseB(true) : new ResponseB(false); } catch (Exception ex) { Logger.LogError(ex); throw; } MethodC(ReqC req) { Logger.Log(“Handling ReqC”); try { using(var db = new Ctx()) { return db.Contacts; } catch (Exception ex) { Logger.LogError(ex); throw; } var result = new ResultA(); result.Name = GetName(req.Id); result. = Get (req.Id); return result; return req.Role == GetRole(req.Id) ? new ResponseB(true) : new ResponseB(false); using(var db = new Ctx()) { return db.Contacts; }
Horizontal API var result = new ResultA(); result.Name = GetName(req.Id); result. = Get (req.Id); return result; return req.Role == GetRole(req.Id) ? new ResponseB(true) : new ResponseB(false); using(var db = new Ctx()) { return db.Contacts; } Exception Handling Caching Logging
What we don’t like WCF services have many responsibilities;.svc file makes it hard to modularize operation handling Generated client code is clunky and is a duplication of server-side contracts; easy to get out of sync Client endpoints scale in parallel to server endpoints
Step 1 – Modularizing Operations Move to request/response Re-imagine each operation’s code as a separate class – MessageHandler<> – One-to-One with request Provide a hook into WCF internals that will instantiate and invoke a MessageHandler<> instead of a service instance (.svc) Identify and isolate infrastructural concerns from MessageHandler<> implementations
Demo
Recap Each operation is handled in its own class – Extensible – Maintainable – Testable.svc File Message Handler Invoker
What we don’t like WCF services have many responsibilities;.svc file makes it hard to modularize operation handling Generated client code is clunky and is a duplication of server-side contracts; easy to get out of sync Client endpoints scale in parallel to server endpoints
Step 2 – Deploy an API Goodbye “Add Service Reference” Move service definition and data contract components to a separate assembly Package a client wrapper for invoking a service with the contract assembly Open doors to build integration between products
Demo
Recap Contracts moved to separate assembly and shared with consumers (possibly through build integration) Client API packaged with contracts – DRY – Single LOC invocation – KISS – Hide IDisposable from consumer
Web Host Server Logic Contracts Client App Client Logic Contracts (Build) Shared Contracts Server.slnClient.sln
What we don’t like WCF services have many responsibilities;.svc file makes it hard to modularize operation handling Generated client code is clunky and is a duplication of server-side contracts; easy to get out of sync Client endpoints scale in parallel to server endpoints
Authentication Service Financial Service Search Service Administration Service Authentication Client Financial Client Search Client Administration Client
Step 3 – Create a single gateway Create another service (“Portal”) with a single operation that will process any request Uses the same invoker as all other services to call a MessageHandler for the request Include a client API that will accept any request Add “facilities” under the covers – Compression
Demo
Recap DB Authentication Customer MH 1 MH 3 MH 2 MH 4 … … Portal Byte[] …Request SOA N-Tier
Nitpicker Corner Async Reuse requests for > 1 operations Auditing vs. Tracing Decorator vs. IErrorHandler.Svc exception smell Portal in distributed environment Horizontal APIs enable discoverability