Comfortably Dumb

Typical blog fare for family, work, gadgets, music, and games.

January 2006 - Posts

Attention: Architects (you know the physical building kind) and Building Planners

On your next public construction project, how hard would it be to make the restroom doors pull to enter and push to exit? If this doesn’t make sense for an existing structure, like where the door swinging out would disrupt a walking path, you can at least put a trash can by the door. I’m not the only freak out there, because I’ve started to notice more and more paper towels piled on the floor next to door in public restrooms.

-CP

 

Posted by Chris | 1 comment(s)
Filed under:

CS 2.0 B3 is out and hosting this blog! As a nice consequence, anonymous comments work again.

-CP

Posted by Chris | with no comments
Filed under:

Scenario: You want to install Visual Studio Team Suite (VSTS) 2005 and/or SQL Server 2005 Developer on Windows Vista build 5270 inside a VMWare Workstation 5.5.1 Virtual Machine. (This may hold true for other scenarios, but this is mine.)

The installations fail for both VSTS and SQL. To work around this issue you have to use the tried and true method of copying the CD/DVD to a local disk and installing from there. I mean this issue comes up so often, with numerous products, that you would think people would test for that or something. Anyway, it comes up so often it is the easiest thing to try. :)

Other notables about my situation, I logged on and installed using the built-in “Administrator” account and shutdown Windows Defender because it is annoying; very annoying.

-CP

Posted by Chris | with no comments
Filed under:

If Microsoft (MS) is nothing else, it is a platform company. At the core of almost everything it does, MS provides a foundation that can used simultaneously by end-users and vendors producing a wide-range of products. Windows Communication Foundation (WCF) is just such a platform. The WCF product team has gone through great lengths to streamline the development and configuration experience for their most frequent use-case: enterprise developers trying to hookup application tiers in a line-of-business application. In fact, they have made it almost trivial. These are the end-users. However, for developers looking to take advantage of everything the platform has to offer, like tool vendors, or enterprises with very precise requirements, they will have ample opportunity to get their hands dirty. The extensibility model and all it is has to offer is a great opportunity for system integrators to develop best practices and approaches for a multitude of scenarios. Service Behaviors and Operation Behaviors are both excellent mechanisms to plug into the WCF infrastructure. Service Behaviors are scoped at the contract level and are applied to all operations. The beauty here is that you can modify your service’s behavior without code changes. In this example, I’m going to create a custom Service Behavior, so I can watch when requests are being dispatched to my service. This will allow me to validate whether or not the Caching Operation Behavior I am going to create works properly or not. The benefit of Operation Behaviors is that they are scoped at the operation level allowing you to fine tune the way your service responds to requests. I’m going to implement my caching behavior as an attribute that won’t require additional code in my business logic or any additional configuration changes. Building upon my service that returns the list of metro markets in Avanade’s South Region, you can see what the developer experience is when using this CachingAspect attribute.

   1:          [CachingAspect]
   2:          public GetMetroListResponse GetMetroList(GetMetroListRequest request)
   3:          {
   4:              Console.WriteLine("MetroManagerService.GetMetroList");
   5:   
   6:              Database db = DatabaseFactory.CreateDatabase();
   7:   
   8:              string sqlCommand = "SELECT id, name FROM metro ORDER BY name;";
   9:              DbCommand dbCommand = db.GetSqlStringCommand(sqlCommand);
  10:   
  11:              GetMetroListResponse response = new GetMetroListResponse();
  12:              response.MetroList = new List<Metro>();
  13:              
  14:              using (IDataReader dataReader = db.ExecuteReader(dbCommand))
  15:              {
  16:                  while (dataReader.Read())
  17:                  {
  18:                      Metro metro = new Metro();
  19:                      metro.Id = dataReader.GetInt32(0);
  20:                      metro.Name = dataReader.GetString(1);
  21:   
  22:                      response.MetroList.Add(metro);
  23:                  }
  24:              }
  25:              
  26:              return response;
  27:          }
  28:      }

This implementation is straightforward and will simply cache the response from the first request using the Enterprise Library 2.0 Caching Application Block. Implementing different expiration strategies is an exercise left to the reader. On line 4 you can see we write to output to indicate that the method is being executed. The key take-away here is that there is no caching logic embedded with the business logic. When you run the server console application you can see that the service implementation is invoked on the first call only.

Even though the service implementation is called once, the client console continues to receive a valid response.

Even a simple example demonstrates the power of tapping into the WCF extension model. To make this happen we need to create our attribute:

   1:      public class CachingAspectInvoker : IOperationInvoker
   2:      {
   3:          CacheManager cache = CacheFactory.GetCacheManager();
   4:          IOperationInvoker innerOperationInvoker;
   5:   
   6:          public CachingAspectInvoker(IOperationInvoker innerOperationInvoker)
   7:          {
   8:              this.innerOperationInvoker = innerOperationInvoker;
   9:          }
  10:   
  11:          public object[] AllocateInputs()
  12:          {
  13:              return this.innerOperationInvoker.AllocateInputs();
  14:          }
  15:   
  16:          public object Invoke(object instance, 
  17:              object[] inputs, out object[] outputs)
  18:          {
  19:              string key = string.Empty;
  20:   
  21:              foreach (object obj in inputs)
  22:              {
  23:                  if (obj != null) key += obj.ToString();
  24:                  key += ";";
  25:              }
  26:   
  27:              object value = cache.GetData(key);
  28:   
  29:              if (value != null)
  30:              {
  31:                  outputs = new object[0];
  32:                  return value;
  33:              }
  34:   
  35:              value = this.innerOperationInvoker.Invoke(instance, inputs, out outputs);
  36:              cache.Add(key, value);
  37:              return value;
  38:          }
  39:   
  40:          public IAsyncResult InvokeBegin(object instance, object[] inputs, 
  41:              AsyncCallback callback, object state)
  42:          {
  43:              return innerOperationInvoker.InvokeBegin(instance, inputs, callback, state);
  44:          }
  45:   
  46:          public object InvokeEnd(object instance, 
  47:              out object[] outputs, IAsyncResult result)
  48:          {
  49:              return innerOperationInvoker.InvokeEnd(instance, out outputs, result);
  50:          }
  51:   
  52:          public bool IsSynchronous
  53:          {
  54:              get { return innerOperationInvoker.IsSynchronous; }
  55:          }
  56:      }

We generate a key in the Invoke method and check for its existence in the cache. If it is there, then we return the value immediately otherwise we invoke the service implementation and store that response in the cache. In a real implementation you would probably want to serialize your request instead, but this IS just a demo. Next, use the Enterprise Library (EntLib) 2.0 Configuration Tool to add the Caching Application Block to your App.config.

By all accounts, our service seems to work in that it return the data we are expecting. However, we still need to validate that our request is actually being cached. Now, to validate that our caching is working we are going to use a Service Behavior. To do this, we need to create a class that understands the behavior extension element we are going to use in our configuration file.

   1:      public class MessageInspectorConfig : BehaviorExtensionSection
   2:      {
   3:          protected override object CreateBehavior()
   4:          {
   5:              return new MessageInspectorBehavior();
   6:          }
   7:   
   8:          protected override void DeserializeElement(XmlReader reader, 
   9:              bool serializeCollectionKey)
  10:          {
  11:              base.DeserializeElement(reader, serializeCollectionKey);
  12:          }
  13:   
  14:          public override string ConfiguredSectionName
  15:          {
  16:              get { return "messageInspector"; }
  17:          }
  18:      }

The MessageInspectorConfig class is solely responsible for understanding the XML configuration and serving as a factory for the actual behavior. This design allows you easily manage extremely complex behaviors with several different strategy implementations. Here I’m going to apply an implementation of message inspector to all the contracts implemented by this service.

   1:      public class MessageInspectorBehavior : IServiceBehavior
   2:      {
   3:          public void ApplyBehavior(ServiceDescription description, 
   4:              ServiceHostBase serviceHostBase, 
   5:              Collection<DispatchBehavior> behaviors, 
   6:              Collection<BindingParameterCollection> parameters)
   7:          {
   8:              foreach (DispatchBehavior behavior in behaviors)
   9:              {
  10:                  Console.WriteLine(behavior.ContractName);
  11:                  behavior.MessageInspectors.Add(new MessageInspector());
  12:              }
  13:          }
  14:      }

This is a message inspector for the stub and their is a separate interface, IProxyMessageInspector, for the proxy.

   1:      public class MessageInspector : IStubMessageInspector
   2:      {
   3:          public object AfterReceiveRequest(ref Message request, 
   4:              IClientChannel channel, InstanceContext instanceContext)
   5:          {
   6:              Console.WriteLine("AfterReceiveRequest");
   7:              return null;
   8:          }
   9:   
  10:          public void BeforeSendReply(ref Message reply, object correlationState)
  11:          {
  12:              Console.WriteLine("BeforeSendReply");
  13:              Console.WriteLine();
  14:          }
  15:      }

The AfterReceiveRequest method is called after WCF receives the request but before it is dispatched to your service. The BeforeSendReply method is called after your service has executed the request but before WCF sends the reply. Obvious stuff, but shows the care that went into designing the object model. To wire all this up, we need to modify our App.config file.

   1:    <system.serviceModel>
   2:      <services>
   3:        <service type="Test00.Services.MetroManagerService" 
   4:                 behaviorConfiguration="test00Behavior">
   5:          <endpoint contract="Test00.Contracts.Services.IMetroManagerService" 
   6:                    binding="basicHttpBinding" />
   7:        </service>
   8:      </services>
   9:      <behaviors>
  10:        <behavior name="test00Behavior">
  11:          <messageInspector />
  12:        </behavior>
  13:      </behaviors>
  14:      <extensions>
  15:        <behaviorExtensions>
  16:          <add name="messageInspector" 
  17:               type="Test00.WinFxExtensions.MessageInspectorConfig, Test00.WinFxExtensions" />
  18:        </behaviorExtensions>
  19:      </extensions>
  20:    </system.serviceModel>

As part of setting up our service we specify a behaviorConfiguration which tells WCF to grab the element on line 8. As WCF iterates over those elements it does not understand it looks at the behaviorExtensions element to see if there is an extension that can understand that element. Extending WCF is extremely powerful and there is a lot of opportunity to innovate on top of what Microsoft has provided out of the box. In this short example we created an Operation Behavior and a Service Behavior to implement response caching and to verify that our cache works properly.

-CP

Technorati Profile
Posted by Chris | 5 comment(s)
Filed under:

I was cleaning out my desk today and come across some old PC games like M1 Tank and Falcon 4.0 from Microprose. I decided to look them up on the web and see what happened to them, so I gave http://www.microprose.com a try and came up with this:

Atari

This is just shameful. Not even a nice error page saying “maybe we should test this in staging before we throw it into production”.

-CP

Posted by Chris | 1 comment(s)

To celebrate the release of Enterprise Library 2.0 January 2006 today, here is a example leveraging the Data Application Block. To use the Data Application Block you need to setup your App.config or your Web.config file like the following:

   1:  <configuration>
   2:    <configSections>
   3:      <section 
   4:        name="dataConfiguration" 
   5:        type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data" />
   6:    </configSections>
   7:    <connectionStrings>
   8:      <add
   9:              name="Test00" 
  10:              providerName="System.Data.SqlClient"
  11:              connectionString="server=(local);database=test00;Integrated Security=false;uid=sa;pwd=P@$$w0rd" />
  12:    </connectionStrings>
  13:    <dataConfiguration defaultDatabase="Test00"/>
  14:  </configuration>

Alternatively, you can use the Enterprise Library Configuration tool. Just open your App.config or Web.config file and add a new Data Application Block.

Enterprise Library Configuration

This is part of larger Windows Communication Foundation example based on the January CTP, but at this point we are working on the service implementation so here it is:

   1:      public class MetroManagerService : IMetroManagerService
   2:      {
   3:          public GetMetroListResponse GetMetroList(GetMetroListRequest request)
   4:          {
   5:              Database db = DatabaseFactory.CreateDatabase();
   6:   
   7:              string sqlCommand = "SELECT id, name FROM metro ORDER BY name;";
   8:              DbCommand dbCommand = db.GetSqlStringCommand(sqlCommand);
   9:   
  10:              GetMetroListResponse response = new GetMetroListResponse();
  11:              response.MetroList = new List<Metro>();
  12:              
  13:              using (IDataReader dataReader = db.ExecuteReader(dbCommand))
  14:              {
  15:                  while (dataReader.Read())
  16:                  {
  17:                      Metro metro = new Metro();
  18:                      metro.Id = dataReader.GetInt32(0);
  19:                      metro.Name = dataReader.GetString(1);
  20:   
  21:                      response.MetroList.Add(metro);
  22:                  }
  23:              }
  24:              
  25:              return response;
  26:          }
  27:      }

On line 3, I am calling the DatabaseFactory.CreateDatabase method without parameters which causes EntLib to use the default connection specified on line 11 of the XML snippet.  If you run this without debugging you get the following:

EntLibDataOutput

 -CP

Posted by Chris | 2 comment(s)
Filed under:

any application you throw together that happens to have [WebMethod] somewhere in the code-base. Just because you are developing a line of business (LoB) application that requires distributed communication between your presentation layer and your business layer and you happen to choose web services for the communication channel doesn’t mean you are doing SOA; period. Now, if you are building a LoB application with web services as part of larger roadmap, then that is something else but doesn’t necessarily mean you are doing SOA either. To me, you are doing SOA if you are doing or have identified the following roadmaps:

  • Enterprise Application Integration Roadmap: You are identifying the systems and outlining how they will be integrated through some type of middleware. This is where LoB applications leveraging enterprise services and application services fit into this space.
  • Business Process Management Roadmap: You are identifying the business processes and how they can streamlined through the enhanced integration capabilities outlined in the EAI Roadmap. This is where orchestration and workflow fit into this space.
  • SDLC Roadmap: You are identifying the software development process changes and how they will be integrated into the core fabric of IT. At a minimum, you need to identify separate processes for Service Providers and Service Consumers. This is where governance and tools fit into this space.

If done properly, SOA is about finally realizing the value of EAI, BPM, and SDLC as part of an Enterprise Architecture.

-CP

Posted by Chris | with no comments
Filed under:

Countless folks have already blogged that the WinFX January CTP is available and that Go-Live licenses are also available. However, they are providing direct links which makes it difficult to find other downloads that you may want. Go here instead:

http://msdn.microsoft.com/windowsvista/getthebeta/default.aspx

-CP

Posted by Chris | with no comments
Filed under:

I finally got Vista 5270 (December ‘05 CTP) to install. I was hoping to connect my XBOX 360 to it as a Media Center, but the folks in Redmond say no. :(

You have to imagine that this will be support once Vista finally ships.

-CP

Posted by Chris | with no comments
Filed under:

I hate the fact that by default Visual Studio 2005 will not show the Solution in the Solution Explorer if you only have 1 project. To enable this go to Tools->Options. In the left side-bar select Projects and Solutions->General. Make sure “Always show solution” is checked.

VS2005-Options

-CP

Posted by Chris | with no comments
Filed under:
More Posts Next page »