Tuesday, December 29, 2009

SolrNet 0.2.3 released

I just released SolrNet 0.2.3. There aren't any significant changes from beta1, I just filled in some missing documentation bits and a couple of tests.

For the next release I'll focus on performance improvements and making multi-core access easier.

Downloads:

Wednesday, December 9, 2009

Boo web console

Here's another embeddable web console: a Boo interpreter. You enter some code, hit the Execute button and it compiles and runs the code. You get access to all of the assemblies in your app.

I use this to run short ad-hoc "queries" against a running web app, like:

  • Is this thing in the cache?
    print (context.Cache["pepe"] == null)
  • Do I have all httpmodules correctly registered?
    import System.Web
    for s in context.ApplicationInstance.Container.ResolveAll(typeof(IHttpModule)):
      print s
  • Checking performance counters:
    import System.Diagnostics
    pc = PerformanceCounterCategory("ASP.NET")
    for counter in pc.GetCounters():
      print counter.CounterName, counter.NextValue()
  • Or even running some NHibernate query (although I'd prefer using the NHibernate web console):
    import NHibernate 
    sf = context.ApplicationInstance.Container.Resolve(typeof(ISessionFactory)) 
    using s = sf.OpenSession(): 
      users = s.CreateQuery("from User order by newid()").SetMaxResults(5).List()
      for u in users: 
        print u.Id 

Why Boo? Because it's pretty much the perfect .net scripting language to embed: small (this console with boo merged in is about 1.9MB), type inference, duck typing, low-ceremony syntax.

Setup:

  • Put BooWebConsole.dll in your app's bin directory
  • Add it to your web.config's <httpHandlers> section:
    <add verb="*" path="boo/*" validate="false" type="BooWebConsole.ControllerFactory, BooWebConsole"/>
  • Visit /boo/index.ashx

Notes:

  • Unlike booish, this console is stateless. Each http request creates a new interpreter, it doesn't remember anything you executed in previous requests.
  • Since the code is compiled and run within the main AppDomain, this will leak memory. Not a big deal in a dev environment though. But putting this in a production site is pretty much suicidal.
  • In case it isn't obvious: this is not meant to replace proper testing.

Code is here.

UPDATE: it's now also available on NuGet

Saturday, November 21, 2009

NHibernate web console

When developing web apps, I sometimes need to poke into the app's database, or try out some query. When it's a SQL Server database, I have Management Studio. But what if it's SQLite? Or Firebird? Even when it's SQL Server, most of my apps use NHibernate and I'm really spoiled by HQL. And if it's a local embedded database, you have to browse and open the db file. Boring. I already have the app URL, that should be enough.

So I built a NHibernate web console. It's kind of like NHibernate Query Analyzer, but more web-oriented. Here's a screencast showing its features:

A couple of features that are not evident from the screencast:

Yeah, I know it's butt-ugly and a little rough around the edges, but still it's pretty usable (at least for me).

DISCLAIMER / WARNING: it's up to you to secure this if you put it in a production website! Also, there is no query cancellation, so if you issue a 1M-results query you will effectively kill your app!

Code is here.

UPDATE: just added RSS support for query results.

Sunday, November 8, 2009

Windsor-managed HttpModules

Another interesting question from stackoverflow:

I have a custom HTTP Module. I would like to inject the logger using my IoC framework, so I can log errors in the module. However, of course I don't get a constructor, so can't inject it into that. What's the best way to go about this?

First thing we need to recognize is that there are actually two problems here:

  1. Taking control of IHttpModule instantiation in order to inject it services, and
  2. Managing the lifecycle of the IHttpModule

Let's start with the lifecycle. Ayende has the best summary of the lifecycle of HttpApplication and its related IHttpModules I've found. If you're not familiar with this, go read it now, I'll wait.

Back so soon? Ok, we can implement this in Windsor with a pluggable lifestyle. Lifestyle managers dictate when it's necessary to create a new instance of the component, but not how. They don't get to actually create the instance, that's the responsibility of the component activator. Here's the full component creation flow reference.

So we need to write a new lifestyle manager that allows at most one component instance per HttpApplication instance. I won't bother you with the implementation details since it's very similar to the per-request lifestyle: it's composed of the LifestyleManager itself and a HttpModule as a helper to store component instances.

Now we need a way to manage the IHttpModule instantiation. Unsurprisingly, we can do that with another IHttpModule, which I'll call WindsorHttpModule.
This WindsorHttpModule will be responsible for the initialization of the "user-level", Windsor-managed IHttpModules.

So, to summarize:

  1. Register PerHttpApplicationLifestyleModule and WindsorHttpModule:
    <httpModules>
        <add name="PerHttpApplicationLifestyleModule" type="HttpModuleInjection.PerHttpApplicationLifestyleModule, HttpModuleInjection"/>
        <add name="WindsorModule" type="HttpModuleInjection.WindsorHttpModule, HttpModuleInjection"/>
    </httpModules>
  2. Write your http modules using normal dependency injection style, e.g.:
    public class Service {
        public DateTime Now {
            get { return DateTime.Now; }
        }
    }
    
    public class UserHttpModule : IHttpModule {
        private readonly Service s;
    
        public UserHttpModule(Service s) {
            this.s = s;
        }
    
        public void Init(HttpApplication context) {
            context.BeginRequest += context_BeginRequest;
        }
    
        private void context_BeginRequest(object sender, EventArgs e) {
            var app = (HttpApplication) sender;
            app.Response.Write(s.Now);
        }
    
        public void Dispose() {}
    }
  3. Make your HttpApplication implement IContainerAccessor
  4. Register your http modules in Windsor, using the custom lifestyle:
    container.AddComponent<Service>();
    container.Register(Component.For<IHttpModule>()
                           .ImplementedBy<UserHttpModule>()
                           .LifeStyle.Custom<PerHttpApplicationLifestyleManager>());

    Note that UserHttpModule is not registered in the <httpModules> section of web.config, since it's managed by Windsor now.

You can also combine this with Rashid's BaseHttpModule to make your modules more testable.

Full source code is here.

Tuesday, November 3, 2009

Powered by SolrNet

Some websites and products that use SolrNet:

I'll keep an updated list on the project's wiki. If you have a public website using SolrNet, let me know!