Thursday, 14 April 2011

Inner controls not populating when using UserControls within UserControls

I spent some time writing a new component converting our existing use of a free BDPLite component, which I wanted to replace with a jQuery UI DatePicker control.
I created a basic control, and injected some JavaScript into the page for the jQuery control
<%@ Control .... %>
<div class="datePickerDiv">        
  <input type="text" ID="txtDate" class="datePicker" runat="server"/>
</div>
Code to insert the code once per page:
protected void Page_Load(object sender, EventArgs e)
{  
  if (!Page.ClientScript.IsClientScriptBlockRegistered(this.GetType(), "jQuery"))  
  {     
     Page.ClientScript.RegisterClientScriptBlock(          
        this.GetType(),
        "jQuery",           
        @"$(document).ready( function() { $("".datePicker"").datepicker(); });",
        true);  
  }
}

public DateTime? SelectedDate
{  
  get   
  {      
     DateTime dateTime;            
    
     if(!DateTime.TryParseExact(this.txtDate.Value, "dd/MM/yyyy", out dateTime))
        return null;
     else        
        return dateTime;  
  }  
  set  
  {      
     this.txtDate.Value = value.ToString("dd/MM/yyyy");  
  }
}
Now, assuming:
  • We’ve added our jQuery references at the top of the page too and it is all working fine
  • We’re creating a new control in the same directory as the old one e.g. ~/usercontrols
  • We are referencing the DatePicker control in another control
Here is another control, referencing the first one
<%@ Control ....%>
<%@ Register TagPrefix="ct1" TagName="DatePicker" Src="~/usercontols/DatePicker.ascx" %>
<div class="outerControl">  
  <ct1:DatePicker runat="server" ID="dtDate" /><br/>  
  <ct1:DatePicker runat="server" ID="dtDate2" /><br/>
</div>

And you try and set some default values up in code:

// Set default values for controls.
protected void Page_Load(object sender, EventArgs e)
{    
  dtDate.SelectedDate = DateTime.Now;
  dtDate2.SelectedDate = DateTime.Now.AddDays(1);
}

You’ll find you’ll get a NullReferenceException at this line:

if(!DateTime.TryParseExact(this.txtDate.Value, "dd/MM/yyyy", out dateTime))

Or more specifically – at txtDate
The short answer is that .NET (4.0 anyway) doesn’t like you referencing controls within controls when they are of the same folder level. I’m not 100% sure at this exact second if it matters if they are in the same namespace.
But to fix this, I moved it to a sub-directory, changed the namespace name and changed the reference and voila! It all worked fine.

Wednesday, 13 April 2011

Unity and ASP.NET MVC 2 Controller injection

I’ve been reading a brilliant ASP.NET MVC Framework V2 Book by Steven Sanderson and found that he uses NInject DI framework with MVC. So I thought I’d give it a go with Unity – and it actually isn’t that bad.

So the things we need are:

  1. An interface declaration defining the contract that the concrete class should meet. Also implementation of the controller.
  2. A DI framework (Unity) to carry out the injection
  3. A Controller Factory to provide the DI framework with the controller to populate.
  4. Attach the custom factory to the MVC framework.

So, I won’t provide huge amounts of code for the interface/class implementations, but here is a quick example:

Step 1 – Create an interface, class and controller implementation

interface IProductsRepository
{
IQueryable<Product> Products { get; }
}
//
class SqlDbRepository: DbContext, IProductsRepository
{
IQueryable<Product> Products { get; }
// implementation here
}
//

class ProductsController : Controller
{
private IProductsRepository productsRepository;

public ProductsController (IProductsRepository repository)
{
this.productsRepository = repository;
}
}

Step 2 - Configure the Unity container

Now, create the mapping in the configuration file. I find this the hardest way, hence why I do it :-P

<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</configSections>

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IProductsRepository" type="SportsStore.Domain.Abstract.IProductsRepository,SportsStore.Domain"/>
<alias alias="SqlDbRepository" type="SportsStore.Domain.Concrete.SqlDbRepository,SportsStore.Domain"/>

<container>
<register type="IProductsRepository" mapTo="SqlDbRepository" name="">
<lifetime type="singleton"/>
<constructor>
<param name="connectionStringName" type="string" value="Default" />
</constructor>
</register>
</container>
</unity>

<connectionStrings>
<add name="Default" connectionString='Data Source=.\SQLEXPRESS;AttachDbFilename="&amp;lt;path to>\SportsStore.mdf";Integrated Security=True;User Instance=True' providerName='System.Data.SqlClient'/>
</connectionStrings>

I admit, the configuration looks scary. But I am just <register> ing an interface to a class.

  • <alias> means I don’t have to retype the fully qualified type every time I want to use it.
  • I am ‘injecting’ a <constructor> <param> eter into the SqlDbRepository class with the <value=“Default”/>. My SqlDbRepository is based on the DbContext class which accepts the connection string name, which the Entity Framework uses to look up the actual connection string.

Lets get some code together to initialise the UnityContainer…

// Create a container
IUnityContainer container = new UnityContainer();

// Get the section and apply it to the container.
UnityConfigurationSection section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
section.Configure(container);

Next, we need some code that will apply this mapping (IProductsRepository to SqlDbRepository) to a given object. So I give it an object that has an IProductsRepository constructor parameter. It will then return me an initialised instance of that object, with the SqlDbRepository passed directly into it.

Step 3 – Create a custom ControllerFactory to populate the controllers

MVC have a class called the “DefaultControllerFactory”, which has a method called “GetControllerInstance”. This method is used to create a new instance of a given controller type. So for example, when initialising a ProductsController controller, this method is fired with

protected override IController GetControllerInstance(RequestContext context, Type controllerType)
{
// controllerType == ProductsController
}

Therefore, if we want to create a ProductsController created with the IProductsRepository constructor parameter populated, we just call the .Resolve() method.

This method takes a Type object and says .. “hmmm .. interesting, having a look over you, I see you have an IProductsRepository constructor parameter. Veeryyy interesting …. Now the thing is, I’ve been configured to pass in a …….. SqlDbRepository object … to a constructor which requires IProductsRepository“ .. So it creates a SqlDbRepository class (with constructor parameters specified earlier), injects it into the constructor, creating a new instance of the ProductsController class.

Now once that Resolve() has returned, it needs to be cast to an IController (i.e. the interface of Controller i.e. the parent class of ProductsController).

public class UnityControllerFactory : DefaultControllerFactory
{
private IUnityContainer unityContainer;

public UnityControllerFactory(IUnityContainer container)
{
this.unityContainer = container;
}

protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return unityContainer.Resolve(controllerType) as IController;
}
}

Step 4 – Attach the custom ControllerFactory to the framework

And finally, we have to tell MVC that when creating controllers, use this ControllerFactory to populate them. So in Global.asax, I do:

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);

// From earlier
IUnityContainer container = new UnityContainer();
UnityConfigurationSection section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
section.Configure(container);

// Configure framework to populate using my controller factory
UnityControllerFactory unity = new UnityControllerFactory(container);
ControllerBuilder.Current.SetControllerFactory(unity);
}

Job done!

Tuesday, 12 April 2011

Debug and Trace messages not showing in DebugView after upgrading to .NET 4.0

Just a heads up to anyone upgrading to .NET 4.0, and finding their debugging not working.
I have been spending the day scratching our heads over why our stage deployment isn’t writing debugging messages to DebugView, after a recent upgrade to .NET 4.0. Before, in v1.1, v2.0 and v3.5 it was working fine, so why has it stopped now?
We have since found that functionality was removed from .NET 4.0 – therefore is by-design.
If you have any applications which use:

Debug.Write();  
Debug.WriteLine();  
Debug.Print(); 
Trace.Write();  
Trace.WriteLine();  
Trace.Print();

These will only appear while Visual Studio is debugging the application. For any environment where you are not doing any attach-to-process managed debugging, you see nothing.
Therefore, you may have to investigate one of the many logging applications e.g.
However, the System.Diagnostics.DefaultTraceListener will still not render any output, when configured by these frameworks.