SOLID SharePoint apps with MVC
Practical code examples of ASP.NET MVC applications that connect to a SharePoint Server and comply with the SOLID principles.
The principles of SOLID are guidelines that can be applied to software development to improve legibility and maintainability of software applications. In this article I’ll explores a few best practices and design patterns for developing ASP.NET MVC applications that connect to a SharePoint Server and comply with the five SOLID principles:
· Single responsibility
· Open/close
· Liskov substitution
· Interface segregation
· Dependency injection
We also try to understand how to abstract the dependency between MVC and SharePoint, the advantages in general that writing SOLID code brings, and how software development can be really agile and adaptive to changes with minimal effort.
Have you ever checked in a cheap hotel and found something like the hair dryer in the picture below?
A tightly-coupled hair dryer
You may think that the hotel manager doesn’t trust you… and you may be right! For some reasons, hotel management considers more effective tying the hair dryer to the wall and so prevent risk of stealing it, than the cost of replacement in case it burns down and they have to call an electrician to do the wiring, besides leaving the customer without the service for some time.
This is what I call a tightly-coupled service: the hair dryer is physically attached to the power outlet on the wall and cannot be detached. The power outlet provides one service only: power to the hair dryer. The hair dryer itself cannot be considered separately, and the whole appliance has to be considered as a single unit, as it provides one final service only: drying your hair. But its reusability is nil.
In the software engineering practice, this is equivalent to writing large classes of objects that perform several operations, often with strong dependency on other types. For example, assuming that we are writing an application for registration of students to a University course, we may be tempted to define our “big course” and the enrolment process in a single class:
public class BigCourse
{
public List<Student> RegisteredStudents { get; set; }
public List<Student> WaitlistedStudents { get; set; }
public int Capacity { get; set; }
public bool EnrolStudent(Student student)
{
if (RegisteredStudents.Count >= Capacity)
{
WaitlistedStudents.Add(student);
return false;
}
if (RegisteredStudents.Contains(student))
{
return false;
}
RegisteredStudents.Add(student);
return true;
}
}
BigCourse class
As you notice from the class definition in the snippet of code, the BigCourse class defines two collections of Student objects for registered attendees and students in waitlist; it also defines the capacity of the course (max number of student accepted); and a method for enrolment of the student, which checks whether the capacity is exceeded or the student is already registered to the course, before actually adding him/her to the list of registered students. If the capacity is exceeded, the student is added to the waitlist.
In its simplicity, this class is effective and gets to the point, given our current requirements. However, as our business model extends, we immediately encounter some limitations: what if our University wishes to offer online courses, in addition to traditional classroom-based ones? What if there is no waitlist for online courses and students are immediately confirmed? With any change happening in our application, the BigCourse class will be immediately affected, growing into an intricate sequence of if conditions, harder and harder to read and maintain.
The principle of Single Responsibility teaches us to keep our objects as simple and nimble as possible. Irrespective on what design methodology you go for, whether DDD (Domain Driven Design), TDD (Test Driven Design), UXDD (User Experience Driven Design), etc., limiting the scope of classes in your application increases readability and maintainability of your software. Our application for course registration will probably benefit of a separation of concerns into different classes as in the following diagram:
Class diagram of the University Course registration application
Wow, even 8 types to replace my one big fat course? (No pun intended with the Greeks). Yes, and I limited myself J. And each of them serves a precise SOLID purpose:
· CourseTemplate is the base class for abstracting some common information; this will come useful for introducing different types of courses without changing the way they are used – more of this when talking about the Liskov Substitution principle.
· InstructorLedCourse and OnlineCourse are concrete implementation of the abstract class; they can be used interchangeably, providing different business logic during registration; this process does not need to be changed in its implementation, but it is still specific to the type of course: Close to change, Open to extension.
· IRegistrationService is the contract that the relevant services for registration of a student to a course need to implement, in line with the principle of Interface Segregation. When introducing the MVC application in the context of SharePoint, the concrete implementation of this interface will be bound together at runtime in the object composition root (that is, the point of execution of the MVC application where dependencies are injected using a DI – Dependency Injection – container).
· Student and Registration are additional classes to slim the BigCourse down and keep responsibilities separated: one Single Responsibility for each of them, that is describing the entity.
The source code for all these types is in the project attached to this article.
Open to extension, close to change. As simple as that. Simply put, it means that you should not be forced to make changes to your classes every time you want to add capability to your application, but rather extend its functionality by adding “something” around / instead of the base class. Options are:
· Class extensions: Methods added to an existing class by referencing it in a separate static class by special use of the “this” keyword (in C#).
· Programming by contract (interface) and binding the interface to a concrete implementation (dependency injection), then replace the existing object with a new one with the new functionality.
· Implement the Composite design pattern for combining multiple functionalities into a single object (smells of violation of the Single Responsibility principle, but each object is still independent, you are just composing their functionality into a single unit of work for ease of use).
· Implement the Decorator design pattern for adding functionality around the base object. Typically used in AOP (Aspect Oriented Programming) to add execution of cross-cutting concerns before and after each method. Some frameworks facilitate this by intercepting the call to the base method and decorating it with the defined aspects.
Let’s see the implementation of the Composite and Decorator design patterns in our University application.
In respect of the Single Responsibility principle, we have separated the functionality of registration and waitlist management, and have defined the following two interfaces for each service:
public interface IRegistrationService
{
bool Enrol(Registration registration);
}
Interface for the Registration service
public interface IWaitlistService
{
void Add(Registration registration);
}
Interface for the Waitlist service
We want to combine both functionalities into a composite object, for ease of execution (rule of thumb: use this pattern with moderation, you may end up in a tangled code easily).
public class CompositeRegistration : IRegistrationService, IWaitlistService
{
protected IRegistrationService registrationService;
protected IWaitlistService waitlistService;
public CompositeRegistration(
IRegistrationService registrationService, IWaitlistService waitlistService)
{
this.registrationService = registrationService;
this.waitlistService = waitlistService;
}
// Implement IRegistrationService
public bool Enrol(Registration registration)
{
bool result = this.registrationService.Enrol(registration);
if (registration.Status == RegistrationStatus.Waitlisted)
{
Add(registration);
}
return result;
}
// Implement IWaitlistService
public void Add(Registration registration)
{
this.waitlistService.Add(registration);
}
}
The composite Registration class
The CompositeRegistration class implements both IRegistrationService and IWaitlistService interfaces, and their dependency is injected in the constructor. The implementation of each interface simply invokes the pertinent method in the injected concrete implementation of the interface, keeping responsibilities separate.
The Decorator design pattern is used to add functionality around an existing object. In our case, we want to check that the person registering a student to a course is authorised to do so, and, upon successful enrolment, notify the student. Security check and notification are two typical cross-cutting concerns that find their place in AOP.
public class RegistrationDecorator
{
protected IIdentity identity;
protected IRegistrationService registrationService;
protected INotificationService notificationService;
public RegistrationDecorator(IIdentity identity,
IRegistrationService registrationService,
INotificationService notificationService)
{
this.identity = identity;
this.registrationService = registrationService;
this.notificationService = notificationService;
}
public bool Enrol(Registration registration)
{
// Security check: Only Instructors can enrol students
if (!this.identity.IsInRole("Instructor"))
{
return false;
}
bool enrolled = this.registrationService.Enrol(registration);
// Notify student
if (enrolled)
{
this.notificationService.Notify(registration);
}
return enrolled;
}
}
The Registration decorator class
The Enrol method has now been “decorated” with additional functionality for security check and notification. In between these two events, the usual call to the Enrol method of the original registration service remains untouched.
Asking for explaining the SOLID principles is a typical question during interviews for a software engineering position. And when it comes to the L, I see most candidates struggling even with the pronunciation of the name of the American scientist and professor Barbara Liskov, not least attempting into an elucidation of her substitution principle. I won’t attempt to embarrass myself in public too, and the best way I know to clarify what the Turing award winner had in mind is reverting to my hair dryer example once more.
If you remember, we said that the hair dryer in the cheap hotel is tightly coupled to the power outlet: the two systems provide one limited service, despite being designed for different purposes. Now, what happens if we… unplug the cord? No, I am not asking to cut the cord with scissors, that would obviously make the unit unusable. I am suggesting, instead, that we recommend hotel management to supply hotel rooms with detachable hair dryers. As a result of this “independence”, the power outlet is now free to accept other electrical appliances. Hey, I said “electrical appliance”! That’s identifying a class of common objects that has something in common: they all need electricity to operate. And guess who can provide electricity? Yup, our power outlet, which now has a new friend, a hair clipper! And surprise, the power outlet still works (that is, it still supplies electricity, just used by another device). What has just happened? We have replaced a type of devices (the hair dryer) with another type that has a similar dependency (on electricity), and both still work as expected.
That’s exactly the Liskov substitution principle: similar objects (better: objects deriving from the same definition, or implementing the same contract), can be replaced without causing interruption of service on either end of the connection.
The Liskov Substitution principle is the foundation of object segregation and inheritance in Object Oriented Programming
So, in the previous section we learned that two types of objects that have something in common can be swapped without breaking the system. What makes them having that “something in common”? Class inheritance is one approach; the other one is implementing the same interface. The hair dryer and the hair clipper has to respect a “contract” to be able to work with the provided power outlet: they need electricity at the defined frequency and voltage. And they also need to provide a similar “male” plug to fit into the wall outlet (but there are workarounds to that, as we will see shortly when describing the Adapter design pattern). That’s defining the contract of work among electric appliances. That’s what interfaces, in software, are for.
The third design pattern that I want to present in this article is the Adapter design pattern. And it does exactly what it says, it “adapts” (fits) one object into another one. British and Americans, two people separated by the same language and different units of measure, power voltage and love for barbeque can now rejoice: we have the solution!
Our University has decided to offer Saturday events to its students, and the application should reflect this, by adding the possibility to register a student. As these events are organised by a third-party institution called “Saturday Inc.”, we are given a library with close source code. This library contains the SaturdayEvent class, that, in violation of the Single Responsibility principle (we didn’t develop it ourselves, after all, right?) implements definition of the Saturday event itself and the registration process.
namespace SaturdayInc.Models
{
public class SaturdayEvent
{
public Location City { get; set; }
public DateTime EventDate { get; set; }
public IList<Sponsor> Sponsors { get; set; }
public bool Register(Student attendee);
}
}
The third-party SaturdayEvent class
The registration adapter will then add a method to enrol students to a Saturday event, in a similar way as it currently happens for regular courses. The existing functionality remains untouched, and support for a new object type has been introduced.
public class RegistrationAdapter : IRegistrationService
{
protected IRegistrationService registrationService;
public RegistrationAdapter(IRegistrationService registrationService)
{
this.registrationService = registrationService;
}
// Implement IRegistrationService
public bool Enrol(Registration registration)
{
return this.registrationService.Enrol(registration);
}
// Adapt the Enrol method to the external SaturdayEvent object
public bool Enrol(Registration registration, SaturdayEvent saturdayEvent)
{
return saturdayEvent.Register(attendee: registration.Student);
}
}
The Registration adapter class
Entire books have been written about the principle of Inversion of Control and its implementation via the Dependency Injection design pattern. Modern software engineering cannot escape adopting a plausible technique for avoiding object dependency and providing a centralised location for object composition. This can be done “manually” or by adopting a proper DI container, there are no excuses to hard code your concrete objects in your classes!
A few .NET frameworks that help implementing the Dependency Injection design pattern in your applications:
NINJECT |
|
CASTLE WINDSOR |
|
STRUCTUREMAP |
|
SPRING.NET |
|
AUTOFAC |
|
UNITY (formerly Microsoft P&P) |
I would love to provide examples of utilisation for each of them, but principles of use and syntax are very similar, so I’ll stick to Ninject for the sake of our University application. Time to introduce MVC and SharePoint in the mix!
Disclaimer: This is not built on .NET Core, which provides a native DI mechanism built in the .NET framework. We have a dependency on the SharePoint Client-side Object Model (CSOM), so, at least at time of writing, we would need to stick to MVC 5 and .NET 4.x
In our solution, we want to connect our MVC application to a SharePoint Server backend. We use the C# Object Model of SharePoint available in the Microsoft.SharePoint.Client package, easily installable from NuGet.
Microsoft SharePoint Client Object Model package in NuGet
The SharePoint CSOM exposes a Client Context that allows connection to a SharePoint Server from the MVC application. As we have wisely learned in the chapters before, we are not hard-coding the dependency to SharePoint in our controllers. Rather, we will use Ninject to define the dependency in the object composition root of the application, by binding a context interface to its concrete implementation. For immediate testing purposes and for future maintainability (say we want to replace SharePoint with a different backend system), all we need to modify is the binding only, with no further changes to our controllers in the MVC application.
The MVC application and its injected dependency to SharePoint
Models are mapped after entities (list items) in SharePoint and Views are simply displaying those models in HTML, so won’t be spending too much time here. What really matters in the context of our SOLID conversation are controllers. A controller is where services are consumed and business logic executed. Yes, we could introduce an additional layer of abstraction and separation between controllers and services, but that’s purely academic for the purpose.
Let’s make an example of a Course action in the Home controller. This action is accessible via the route /course/{id} and displays the course detail page for the course identified by the “id” parameter.
public class HomeController : Controller
{
public ActionResult Course(int id)
{
var course = this.context.Find<InstructorLedCourse>(id);
if (course == null)
{
return HttpNotFound();
}
course.ContentItems = this.context.Get<Content>()
.Where(c => c.CourseId == course.Id)
.OrderBy(c => c.Name)
.ToList();
return View(course);
}
The Course action in the Home controller
A few things worth noticing here:
· There is a reference to a local context that exposes the method Find for retrieving an instance of an InstructorLedCourse class.
· context is a reference to the SharePoint Client Context, and it is built with Ninject (more in a moment…)
· InstructorLedCourse is a concrete class as extension of the base CourseTemplate; it can be replaced with another class of the same base type for returning different types of courses without breaking functionality
Access to SharePoint is provided by the ClientContext class in the Microsoft.SharePoint.Client namespace. This is encapsulated into a SharePointContext class that implements the IRepositoryContext interface. For more information about using the SharePoint ClientContext, please refer to its MSDN documentation. And in the context of MVC, to my article Building an MVC application for SharePoint.
public class SharePointContext : IRepositoryContext, IDisposable
{
public SharePointContext(string sharePointSiteUrl)
{
Context = new ClientContext(sharePointSiteUrl);
}
public ClientContext Context { get; protected set; }
SharePoint context wrapper around the CSOM ClientContext
We are programming by contract, we are decorating our strong dependency (the SharePoint client context), and soon we will bind the interface to a concrete implementation. You see, the long conversation before start making sense now…
What I surely want to avoid is hard-coding a reference to SharePointContext in my controller, such as something like:
private SharePointContext context = new SharePointContext("<URL>");
This is creating a tight coupling between HomeController and SharePointContext. The MVC application must have an active connection to SharePoint to work properly. I am not able to mock the context for testing purposes as it is declared private inside the controller class and strongly typed to a concrete class.
If you read all the books about Inversion of Control, you will know the answer already: dependency should be abstracted to an interface and injected from outside. Hence the meaning of “inversion”: it’s not the object using the dependency to create an instance internally, but the concrete object being injected into its consumer. How?
· Constructor injection: The dependency is passed as a parameter to the constructor of the controller.
· Property injection: The dependency is assigned to a property of the controller, and then used internally.
public class HomeController : Controller
{
public HomeController(IRepositoryContext context)
{
this.context = context;
}
private readonly IRepositoryContext context;
Injection of dependency by constructor
public class HomeController : Controller
{
public IRepositoryContext Context { get; set; }
Injection of dependency by property
Different schools of thought exist on which method is more appropriate, and each of them has pros and cons. In a nutshell: use constructor injection when the object must have the dependency, that is the dependent reference must exist otherwise the object does not work. Instead, use property injection when you have a good default standard (and don’t forget to set it in the setter method of the property) and you want to have the flexibility to provide an optional alternative, for example a mock for testing purposes. Good news, whatever strategy you decide for dependency injection, our DI container of choice, Ninject, supports both.
The use of DI containers helps maintaining a centralised location for setting all the dependencies, and then inject them at runtime in the consuming objects. This central location is called the Composition Root, and it depends on the nature of the application. In a Console app, it’s typically the Main method of the Program class. In an ASP.NET MVC application, you may want to build all your objects once for the lifecycle of the application, and a good place to do so is the Application_Start method in the Global.asax file.
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
DIContainer = new ServiceInjectionContainer();
}
protected ServiceInjectionContainer DIContainer;
}
Reference to the DI container in the MVC application start up method
Yes, we have a strong reference here to the DI container of choice. But this is the only place in the entire application where object reference is hard coded (at condition that we apply the DI pattern consistently, obviously). If tomorrow you want to replace your dependencies or even the DI container, there is only one place that requires change, with no impact on the rest of the application. Pretty powerful!
The Ninject framework works around two main classes:
· The Injection Container
· The Dependency Resolver
The Injection Container represents the entry point for the DI engine to resolve dependencies. In an application, there should be one instance only of the DI container for a specific set of services to be resolved. Ninject exposes this entry point through the StandardKernel class. This class requires an instance of the Dependency Resolver in input, as we will see shortly.
But first of all, we need to reference Ninject in our project. Easy done, Ninject is available in NuGet.
Ninject package in NuGet
Then we can write our own ServiceInjectionContainer class that was instantiated in the Global.asax. As said, when creating an instance of the Ninject’s Standard Kernel, the Dependency Resolver is passed as parameter. There is where the mapping of interfaces to concrete classes is defined.
public class ServiceInjectionContainer : IDisposable
{
public ServiceInjectionContainer()
{
_kernel = new Ninject.StandardKernel(new ServiceDependencyResolver());
}
private readonly Ninject.IKernel _kernel;
}
Implementation of the Injection Container with Ninject
By programming by interface, we have built our University application with a number of services for registration and waitlist management, as well as abstracted the reference to the SharePoint client context. Now it’s time to specify the concrete class that implements the interface, and bind them in the Dependency Resolver module of Ninject.
This is a class that inherits from NinjectModule. All We have to do is to override the Load method and specify a list of binding conditions between the interface and its concrete implementation. The syntax is:
Bind<Interface>().To<Implementation>();
internal class ServiceDependencyResolver : NinjectModule
{
public override void Load()
{
Bind<IRepositoryContext>().To<SharePointContext>()
.WithConstructorArgument(SharePointContext.SharePointSiteUrl);
}
}
Binding the Repository contract to the SharePoint client context
In the Load method, we would register the dependency to the SharePoint context, as well as the other services used in the application. The DI container will use this mapping for instantiating a concrete object instance every time there is an injected reference to the mapped interface in our code. Easier to do than to say!
Ninject is a lightweight still powerful DI container
Project Name: SolidMvcSharePoint