Introduction

Enterlib.NET is library that can be usefull for developing back-end applications. It was initially designed as the back-end support for android applications built with Enterlib Android, another member of the Enterlib suite .Enterlib.NET provides several advantages by using a SOLID component's architecture which developers can use to build its back-ends. Also it provides ODATA support with extended features and mapping from queries results to DTO among other features.

So in more details, Enterlib.NET defines abstractions for some well known patterns like the Repository and UnitOfWork. Those abstractions are implemented with EntityFramework 6.0 but could be implemented using others ORM like NHibertane for instance or a custom one. The advantage of using such patterns results application layers more robust and reliable and also unit test friendly. The IRepository and IUnitOfWork contracts are shown bellow.

Futhermore the library defines a set of interfaces and classes that will increase reausability, robustnes and productivity when developing business logic. All bounded together by a flexible dependency injection engine with autodiscovering of depencencies.

Typically developers coded business logics into simple service type classes that will handle a specific part of your business. Then by combining those classes more complex logics can be constructed. The dependency injection mechanism of Enterlib.NET allow you to do that in a loosly couple and independent way. But it goes beyond that by providing a event comsuming/subscription mechanism throught a message bus inteface that promotes independent service comunications.

Using Enterlib.NET the main interface your business object will implement is IDomainService this contract provide access to the dependecy injection container, logging, localization and message bus services.

On ther other hand, as mentionen at the begining of this article, Enterlib.NET provides support for ODATA (Open Data Protocol) that can be integrated into WebAPI controllers. It works by converting strings containing conditions, include and orderby expressions into LINQ expressions that can be applied to IQuerables. That is achived thanks to a class that implements the following interface:

As you can see in the previus code listing using the IExpressionBuilder<T> you can map directly from the data model to the desire output model. The results is more eficiency due to the response model (DTO) is mapped directly from the database so no instances of the data models are created. Besides only the properties defined in the DTO are specified in the query.

The following operators are compiled by the current IExpressionBuilder<T> implementation:

or : ||

and : &&

true : true

false : false

gt: >

lt: <

ge: >=

le: <=

eq : ==

ne: !=

null: null

like: translated to string.StartWith, string.EndWith or string.Contains in dependence the expression fomat.

plus: +

sub: -

div: /

The following section will use an example to show how to use those components and how to integrates them into WebAPI.

Using the code

Now we are going to show how a backend for a film business can be implemented by integrating Enterlib.NET with ASP.NET WebAPI. Also we are going to write a simple view in AngularJS in order to show the usage of ODATA expressions and the DTO mapping.

The application will follows a code-first approach. Then first of all we are going to define the data models .

The modelsNamespace parameter is the namespace where the data models are defined, the serviceResponseNamespace is optional but when supplied is the namespace where the DTO for the services responses are defined. By last the assemblies parameter is and array of all the assemblies where your components are located.

The helper method above returns a dependency container that you could use for register other dependencies in a scoped context by using factories. For instance after integrating the IOC container we need to configure the message bus service in order to provide inter-component comunications in a decouple way.

In the code section above, a instance of DomainMessageBusService which implements IMessageBusService is created when a request scope begin. Then using the message bus, processors can be registered for messages posted on the bus. The processor must implement the IMessageProcessor<T> interface where T is the type of message or event. The current implementation for the IMessageProcessor<T> will be resolved by the Dependency Injection Container.

Generally business logics are written in a IDomainService implementation. The common aproach is to inherit from EntityService<T> due to it already defines common operations on entities. But it also provides access througout an Authorize property of type IAuthorizeService to security tasks like rolls and action authorization. For instance the business rules for manage Film entities are defined in a FilmsBusinessService class. This class provides additional funtionalities on films like the usage of security, validation , internationalization and message notifications. You can also see the class is registerd for IEntityService<Film> using the RegisterDependencyAttribute with LifeType set to Scoped. So when an IEntityService<Film> is requested and instance of this class will be returned.

As you can see some service references are used in the create film workflow, like for example a custom IUnitOfWork specialization IVideoClubUnitOfWork that defines operations that execute store procedures at the database layer. An IAuthorizeService to check for user's rolls , internationalization using the Localize property of type ILocalizationService that returns strings based on the context's culture, and a message bus to post notifications when a film is succesfully created. The message posted on the bus can be intercepted by a processor to send email notifications to clients in order to inform them a new film has arrived to the store.

The next class will show an example for a CreatedMessage<Film> message processor.

The RegisterDependency attribute allows you to register a class for several interfaces using the same lifetype. On the other hand if you want to provide asynchronous message processing you can implement the following interface:

Next you will see the definitions for some of the services used by the sample back-end app. Even though I want to point out, that by using this architecture no wiring of component references are required. All can be handle declaratively by attributes in your interface implementations, besides using the message bus more complex workflow can be orchestrated in a way easy to evolve and maintain.

In most applications, it is required to call some store procedures during the execution of a business workflow. This can be a decision for increasing performance or for dealing with legacy systems. To handle this scenario you can define a particular IUnitOfWork implementation for your applications. For instance the VideoClub back-end application defines a IVideoClubUnitOfWork interface. The implementation of this interface will call a store procedure. The easiest way to do it, is by extending the base UnitOfWork class which is implemented with Entity Framework. This class is located in the Enterlib.EF assembly.

After the core back-end is completed we can used it in varius platform, meaning web or desktop. This sample back-end will be exposed as REST services with ASP.NET WebAPI. But there is more, by using Enterlib.WebApi and the DataServices.Configure helper method, you are not longer required to implement a ApiController. The controller are automatically resolved by Enterlib, so your business services will be called to handle all operations defined by the IEntityService<T> interface.

Moreover you can define data transfer objects (DTO) at the REST API gateway layer for your busines services results. In order to apply the mapping you just need to pass the namespace where your DTO are located calling the DataServices.Configure method.

Enterlib.WebApi follows a convention for resolving the DTO for an entity api controller. All DTO's names must end with 'Response' and the properties are mapped by name. Also you can include mappings for properties of related models. For instance in the code bellow some DTOs are defined:

GET http://localhost:54697/api/film/get/?filter=Name like 'Ava%'&orderby=Name desc&include=Author.Country

POST http://localhost:54697/api/film/post/

PUT http://localhost:54697/api/film/put/

DELETE http://localhost:54697/api/film/delete/?filter=Id eq 1

GET http://localhost:54697/api/film/count/

GET http://localhost:54697/api/film/find/?filter=Id eq 1

You can use ODATA expressions for filtering, orderby and including related models in the response ,like include=Author.Country where the included models are also mapped DTOs. For instance the response for:

In addition the result of validations routines are also returned to the client in a standart json format. Validations can be applied at the REST API layer after the model binding by the ApiController ModelState property or at the business layer by throwing a ValidationException. The ValidationException can be captured at the REST API layer by setting the following filter:

config.Filters.Add(new ValidateModelActionFilterAttribute());

The ValidateModelActionFilterAttribute resides in the Enterlib.WebApi.Filters namespace. It will capture the ValidationException from the business layer and returns a formatted response to the client. For instance when the film's name policy fails you will recieve the following json with http status code of 400 Bad Request.

You could customize the REST API by defining a ApiController that inherits from EntityApiController<TModel, TResponse>. This scenario could be usefull for setting authorization attributes at the REST API layer as shown bellow:

The Front-End

The Fron-End of the VideoClub is implemented with AngularJS. It consist of only one angularjs controller and a service to make the request to the REST API. The markup for the page layout is presented bellow.

The home page will present a table displaying some film's properties and allows to search and ordering of the rows.

At the front-end the action takes place in the javascript files. The angular app is composed of 2 files app.js where the module and services are defined and the films.js where we define the view controller.

Inside films.js we found the FilmController which loads the films by calling filmsService.getall and provides actions for sorting and searching like orderBy and onSearchValueChanged which is called while the user is typing in the search box.

Points of Interest

Resuming by using Enterlib.NET you can build a SOLID back-end with a REST API quickly with ODATA suppport and a layered architecture that promotes loosely coupling and isolated testing, good for ensuring quality and flexibility. Also by using DTO model and automatic mapping from the models the performance is increased because only the necesary columns are retrieved from the database.

You can use Enterlib.NET by installing the following packages with nuget:

Install the core library with :

PM> Install-Package Enterlib

Install the Entity Framework implementation with:

PM> Install-Package Enterlib.EF

Install the WebApi integration with:

PM>Install-Package Enterlib.WebApi

License

Share

About the Author

Senior Software Engineer with more than 8 years of experience in the industry. Graduated from Computer Science ,focused on .NET and Java technologies with special interest on Computer Graphics, Compilers , Languages and Machine Learning.

Hi,
First of all thanks for reading the article. About your question there are implementations for the IRepository and IUnitOfWork in the Enterlib.EF assembly ,you can install it with nuget package manager as pointed out at the end of the article. I do not put the implementation of those interfaces in the article because I think it would be too much info to digest for a first introduction to the library.
Also to call store procedures use the UnitofWork method

Invoke

passing the name of the procedure and the parameters in a dictionary or object for instance: