.NET web application product lines

This page is currently a general dumping ground for various ways of implementing variability/feature-oriented development when it comes to .NET web applications.

Blog Posts

The comments of these posts are always worth a read for pros and cons.

Steve Smith outlines the steps needed to get a basic feature folder setup in ASP.NET Core MVC. He discusses how it can be achieved both with the built-in Areas functionality, or by rolling it yourself with an IControllerModelConvention and an IViewLocationExpander. The main differences between the two are: Areas is built-in and requires minimal effort to get it working, however it’s still quite ‘folder-heavy’. The custom Feature Folders approach require more effort to get working, however all artifacts are contained within one folder for each feature that is easier to navigate. Steve shows a way to combine both approaches, so you can have feature folders underneath Areas. This seems like a good way to keep Areas what they are for (separating out large distinct areas of an application), and still being able to have the parts of the Areas navigable by feature names rather than technologies.

What needs composing in an ASP.NET MVC web application?

  • Controllers
  • Routing
  • View Models
  • View Templates
  • JavaScript
  • CSS
  • Static files
  • web.config

Controllers

Controllers are C# code so can make use of the standard mechanisms - #ifdefs, parameterisation, design patterns. If we were to use feature-oriented composition FeatureHouse C# composition could potentially be used.

Routing

Action methods on controllers can be attributed with routes, and the routing engine picks them up from there, so it could be that composing controllers takes care of composing routing.

View Models

As for controllers.

View Templates

One simple approach is extended ViewEngine that allows for view overriding. By making use of partial views this allows overriding at quite a fine level of granularity.

Note that the folder structure here has it broken down by customer/product. For branding concerns, we have to really think of branding as a feature variant that only applies to one customer. So where the alternate views are for branding concerns, it’s OK to have them separated out essentially ‘by product’.

In the case of views being required only for a particular functional feature, we might have a single view engine that searches for views in feature modules, or we could even experiment with a view engine being bundled with every feature and added to the collection of ViewEngines at application startup, based on product configuration.

CSS

CSS is composable by simple concatenation.

Static files

...

web.config

Web.config transforms in Visual Studio can deal with some composition of configuration options. It’s limited though in that you can only have overriding configs per build configuration and per publish profile. There’s no real way to separate this out by feature.

ASP.NET MVC Areas

Areas provide a means for separating an application up into distinct areas. It’s intended more for large subsections of an application however, so not at the fine-grained level of features.

FubuMVC bottles

FubuMVC’s bottles were a way to package up code, web endpoints and views in a single place that could be reused in web applications.

I never worked with it, and I don’t know how it went about composing different artefacts (it seems to be runtime composition?), but it seems to have definite similarities with the idea of feature modules in FOSD.

https://lostechies.com/josharnold/2011/09/05/modularity-via-bottles/

OrchardCMS

Orchard builds on top of ASP.NET MVC and has the idea of extensibility via modules built into it from the ground up.

Behind the scenes, Orchard modules are built on top of the ASP.NET MVC Areas mechanism.

http://docs.orchardproject.net/en/latest/Documentation/How-Orchard-works/