Monday, January 10, 2011

Forcing .NET to proxy requests

Two posts back to back after being away for a couple months....I'm pumped!

So I ran into a situation where I needed to know exactly what my .NET app was doing. In particular I had to log the soap calls it was making to understand them. There are probably many ways of doing this but the way I though of was to make the server proxy it's requests through fiddler. This seems like an easy thing to do but it took me forever googling it to figure it out.

Sure enough the answer is a mere 10 lines of xml in the web.config....enjoy!

<system.net>
    <defaultProxy>
      <proxy
        usesystemdefault="False"
        bypassonlocal="True"
        proxyaddress="http://127.0.0.1:8888"/>
    </defaultProxy>
</system.net>


Put the above anywhere in the configuration section and you'll be going through port 8888.

Castle ActiveRecord and Castle Windsor Configuration for .NET

Well it's been a long time since my last post....over 2 months wow! Started a new job and it's been keeping me busy. Been working a lot with the Castle stack for .NET. It's actually a VERY nice framework based on what are now common enterprise architecture patters, or as Fowler would call them PEAA.

It actually has really good documentation that is not a freaking dissertation (hello SpringSource, I'm talking to you!).

Here is an example of how to configure the ActiveRecord Framework along with the IoC Windsor using the facilitator:

In the web.config in the config section we need to add the castle facilitator:
<configsection>
<section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,   Castle.Windsor">
</section>
</configsection>



Then we need to setup the castle section that we just defined like so:

<castle>
  <facilities>
   <facility id="arfacility" type="Castle.Facilities.ActiveRecordIntegration.ActiveRecordFacility, Castle.Facilities.ActiveRecordIntegration" isWeb="true" isDebug="false">
    <assemblies>
     <item>[assembly_name_to_init_AR]</item>
    </assemblies>
    <config>
     <add key="connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/>
     <add key="dialect" value="NHibernate.Dialect.MsSql2005Dialect"/>
     <add key="connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>
     <add key="connection.connection_string_name" value="[connection_string_name]"/>
     <add key="proxyfactory.factory_class" value="NHibernate.ByteCode.Castle.ProxyFactoryFactory,NHibernate.ByteCode.Castle"/>
     <add key="query.factory_class" value="NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory, NHibernate"/>
    </config>
   </facility>
  </facilities>
 </castle>

if you want to use just active record without the IoC and facilitator you just need:

<section name="activerecord" type="Castle.ActiveRecord.Framework.Config.ActiveRecordSectionHandler, Castle.ActiveRecord" />
instead to the configuration section and the following:

<activerecord 
        isWeb="true|false" 
        isDebug="true|false" 
        pluralizeTableNames="true|false"
        threadinfotype="custom thread info implementation"
        sessionfactoryholdertype="custom session holder implementation"
        namingstrategytype="custom namingstrategy implementation">

        <config
            database="MsSqlServer2000|MsSqlServer2005|MsSqlServer2008|SQLite|MySql|MySql5|Firebird|PostgreSQL|PostgreSQL81|PostgreSQL82|MsSqlCe|Oracle8i|Oracle9i|Oracle10g"
            connectionStringName="name of connection string in config">
            <!-- Any legal NHibernate parameter you want to specify or override its default value -->
        </config>

        <config type="Full Type name to Abstract Class that defines boundaries for different database">
            <add key="connection.driver_class"           value="NHibernate Driver" />
            <add key="dialect"                           value="NHibernate Dialect" />
            <add key="connection.provider"               value="NHibernate Connection Provider" />
      <!-- Use only one of the two attributes below -->
            <add key="connection.connection_string"      value="connection string" />
            <add key="connection.connection_string_name" value="name of connection string in config" />
        </config>
        
    </activerecord>


this is described in nice detail on the castle website

The last step would be to use the global.asax.cs file and on Application_Start do:

//init windsor IoC container
            Castle.Windsor.WindsorContainer container = new Castle.Windsor.WindsorContainer(new Castle.Windsor.Configuration.Interpreters.XmlInterpreter());
            

Now adding classes for automated DI is just as simple. In the same init method you would do the following:

container.Register(Castle.MicroKernel.Registration.Component.For<[class_name_here]>());

To recall a class you just make a setter in another class that has been injected. If you want access from a class that was not injected by Windsor you would do the following:

container.Resolve<[class_name_here]>();


Not so bad huh?