Tuesday, November 19, 2013

MEF and deciding which export instance to use

Having used MEF in the past, I was really keen to use more extensively in a up coming project, which will involve extending 'core' functionality with customer extensions (i.e. overriding) . I'm enjoying the simplicity of MEF in regards to resolving dependencies, and the lack of configuration required / setup code when comparing with IOC containers. With the amount of customers extensions that will be implemented eventually, the amount of configuration required to wire these up won't scale (like it didn't for the previous version of the product where Unity was used).

So essentially, if I drop an assembly into the bin folder with customer extensions on base functionality, then the derived Exports would be used over the 'base' Exports. If the customer extension is not present, (i.e. just the base Export is), then just use this one.

In code this would look like:

public class CoreApplicationQueryService : IApplicationQueryService

public class CustomerApplicationQueryService : CoreApplicationQueryService

If CustomerApplicationQueryService is present, use that, if not, default to CoreApplicationQueryService.

[Import] won't suffice because there will be multiple Exports that match if the Customer version is present, therefore an exception will be thrown. Therefore [ImportMany] will have to be used. But, once the multiple Exports have been picked up, I need a way of deciding which instance to use. That is where [ExportMetadata] comes in.

I've used [ExportMetadata] to indicate is the Export is defined as an (Customer) extension of not:

[ExportMetadata("Extension", false)]
public class CoreApplicationQueryService : IApplicationQueryService

[ExportMetadata("Extension", true)]
public class CustomerApplicationQueryService : CoreApplicationQueryService

... where true ("Extension", true) indicates that this instance is a extension instance.

There is a little bit of magic where you then need to create an interface to match the parameters in the ExportMetadata attribute - e.g:

public interface IExportMetaData
{
bool Extension { get; }
}

The next step is to import the parts, e.g. set this property. IExportMetaData is part of the property definition as part of the Lazy type:

[ImportMany(typeof(IApplicationQueryService))]
public IEnumerable<Lazy<IApplicationQueryService, IExportMetaData>> ApplicationQueryServices { get; set; }

Next compose the parts, and then cycle through the instances resolved to find the extended instance (if there). An example is below:

var directoryCatalog = new DirectoryCatalog("bin");
var compositionContainer = new CompositionContainer(directoryCatalog);
compositionContainer.ComposeParts(this);
foreach (var item in ApplicationQueryServices)
{
   if(item.Metadata.Extension)
{
var message = item.Value.GenerateMessage();
}
}

Monday, November 18, 2013

Not your typical MVC validation requirements

When reviewing the wireframes and requirements for a new project I am about to work on, it quickly became clear validation (data and business rules) would have to be implemented differently than previous web based projects I've worked on. 

Typical validation, especially for a web application, means you can't submit (POST) your changes unless all is well on the page - in other words you can't move to another page / screen until there are no validation errors. ASP.Net's validation does this out of the box - any validation errors, the POST isn't performed. Assuming here you're using Client side validation which will be necessary for this new project as the validation errors still need to be displayed on screen (so POSTing to the server to determine the validation errors won't make sense).

This project will be different:

  1. Users need to know about the validation errors, however it shouldn't stop them moving through out the application to fill out details on other pages. 
  2. The validation errors need to be shown on screen.
  3. The validation errors will remove the ability to perform a commit of all the data collected (in this particular project, the commit is to a legacy banking system via web services). Which means the validation rules will be used in multiple parts of the application (the page were the data is collected, and a final commit page) - so the validation rules need to be centralized (because I don't want to repeat them)

So, using MVC, and with client side validation enabled (meaning the JQuery Validation plug-in will be used), The solution to these requirements were:

  1. After a while searching the web, I found that adding class="cancel" to the submit button, means the submit will still be performed (which is good, so we don't lose the data even if it is invalid) - and when the user returns, it will be loaded as is. More details can be found here (specifically 'Skipping validation on submit'). 
  2. Invoking the validation on the page being loaded can be performed by doing the following (i.e. perform the validation for everything within the form element):

    $(document).ready(function () {

        $('form').validate();

        $('form').valid();

    });

3. And finally the centralization of the validation / business rules. Because I don't want to 'embed' the validation in the view model for the page because I want re-use, I'm going to centralize on the domain (I'm going to use the Validation block in Enterprise Library). However, because these rules will be on the server, and I'm using Client side validation, the Remote attribute will allow the rules to be invoked via AJAX - e.g.

[Remote("ValidateAge", "Applicant", ErrorMessage = "Age is invalid")]

This results in the following attributes being added to the text input element (i.e. using Razor to create the textbox via Html.TextBoxFor(x => x.Age) )

<input data-val="true" data-val-remote="Age is invalid" data-val-remote-additionalfields="*.Age" data-val-remote-url="/Applicant/ValidateAge" id="Age" name="Age" type="text" class="input-validation-error">

So after every change in the texbox Applicant/ValidateAge will be called (data-val-remote-url), which means the Age validation logic can be invoked on the server. This same validation logic can be invoked again when needed on additional pages (e.g. when determining if the commit call to the banking system can be made). 

Wednesday, April 10, 2013

MEF 101

A new project that I've been working on involved separating customer extensions into their own assemblies. More specifically, a WCF service has a dependency on types within an assembly, however these types may be extended in a customer specific library/assembly depending on the customer we are building the solution for.

WCF Service --> Library with Interface / Base classes etc <-- Client extensions library implementing interfaces, and extending base classes

However I didn't want the WCF service to have a reference to all of the client extension assemblies and use Unity for example to resolve the concrete dependency at runtime through config - this will grow over time so won't scale, and is clumsy. Its worth pointing out that Unity won't load the assembly into the AppDomain by it's self - so another mechanism is needed (eg. project reference)
Never used MEF before, but it's perfect for this scenario - dynamic application composition.
Continuing with the WCF service example, I create a property which is the dependency I want to 'import' - below example is a logger dependency, where the ILogger interface is defined in the base library (i.e. what the WCF service is referencing), I have also decorated the property with the MEF Import attribute:

[Import(typeof(ILogger))]
public ILogger Logger { get; set; }

A customer wants to log in a particular way, so we'll create a specific implementation by implementing the ILogger interface in a customer specific assembly. This class has been decorated with the MEF Export attribute - which indicates it available as a composable part:

Export(typeof(ILogger))]
public class FlatFileLogger : ILogger

The next step is to build up the type with the dependencies / needs to composed using parts (i.e. needs to 'import' an implementation of ILogger). To do this you need to use the CompositionContainer, AggregateCatalog and the ComposablePartCatalog types. In my example, I just wanted to drop an assembly in a specified folder, and MEF would pick it when attempting to compose, so the DirectoryCatalog is the catalog type (there are others) that will allow me to do this.

new DirectoryCatalog("bin")

In the above snippet, I've created a Directory Catalog where MEF will evaluate all the assemblies in the bin folder - relative to the root folder of the AppDomain. Next I need to add this catalog instance to the AggregateCatalog, and then add the AggregateCatalog to the CompositionContainer.

var aggregationCatalog = new AggregateCatalog();
var compositionContainer = new CompositionContainer(aggregationCatalog);

So, assuming I've copied the customer extension assembly into the bin folder (i.e. the FlatFileLogger), I can then compose the parts for my instance the needs to be built up - so in the below example, instance that is passed into ComposeParts, is an instance of my type that needs to be composed with a ILogger (decorated with the Import attribute). Using the configured catalogs, MEF will then try and compose the instance. So since in this example a DirectoryCatalog is used (for the bin folder) - MEF will evaluate all the assemblies in that folder to determine if there are any types that are defined as being a composable part (i.e. decorated with Export). If so, MEF will instantiate the part - e.g. the Logger property will be instantiated as a FlatFileLogger.

compositionContainer.ComposeParts(instance);


Saturday, March 2, 2013

WebRequest.GetResponse causes the application to hang

Recently I built an application which required the use of the WebRequest type. When calling GetResponse to retrieve the response stream all was working fine. By mistake, I incorrectly created the application targetting .Net 4.0 - so I changed the target framework to 3.5 and all was not working fine. When GetResponse was called, the application hung, and looking through Fiddler no request was actually made to the http server. 

After some googling, I found this is a common scenario where GetResponse hangs when not targetting .Net 4.0. Solutions I found to this issue varied, however the one that worked for me was looking at the MSDN example for using the WebRequest type and comparing line by line to how I was using WebRequest.

Turns out, the only difference was I wasn't specifying the Content-Length http header:

webRequest.ContentLength = byteArray.Length;

Once the above was included when setting up the WebRequest - GetResponse no longer hanged when targetting 3.5 (and continues to work fine when targetting 4.0).

The 4.0 WebRequest version is obviously more forgiving and allows you not to specify the Content-Length (and I'm assuming calculates automatically).

Monday, January 21, 2013

Cryptography_CSP_NoPrivateKey

I've been working with a application which is a WSE 2.0 client - which involves signing the message.

When attempting to send the request - an exception of type System.Security.Cryptography.CryptographicException is thrown, where the message is Cryptography_CSP_NoPrivateKey.

This is permissions issue - where the identity of the AppPool (the application I had the issue with was a web service), does not have the required permissions to access the private key of the certificate.

Management of the permissions can be done through the MMC Certificates snap-in - right click on the certificate, select All Tasks, then Manage private keys.