Unifico has a few paging helpers to make service methods easily paged from a client. Essentially the framework makes consuming a page request object as simple as calling .ToList() on an IQueryable source. The object, the PageRequest, has two collections, Filters and Sorts with several constructors to make instantiation easy. The collections are rather straight forward, providing filtering and sorting ability on a paging source. The uniqueness comes from the ability to request multiple filters and sorts together, along with a paging request. This request is then execute on the IQueryable source, so if DLINQ is used, results in exactly two database hits. A COUNT statement is executed to find out how many pages there are, and a single select statement providing the paged results. This is all done without exposing LINQ or IQueryable to the service's client.
Making an existing source page-able is rather simple, compare the two implementations.
Without paging implemented:
44 public
List<App.Account.Models.Role> GetRoles()
45 {
46 return accountRepository.GetRoles().ToList();
47 }
With paging implemented:
43 public
PageResponse<App.Account.Models.Role> GetRolePage(PageRequest PageRequest)
44 {
45 return accountRepository.GetRoles().ToPageResponse(PageRequest);
46 }
Utilizing the paging is almost painfully easy.
Grabbing the first page at a size of ten:
120 PageResponse<Role> rolePage = accountService.GetRolePage(new
PageRequest(0, 10));
Or grabbing the first page sorting by the role's name (ascending):
120 PageResponse<Role> rolePage = accountService.GetRolePage(new
PageRequest(0, 10, "Name", "string", true));
Or fully defining the page request:
120 accountService.GetRolePage(new
PageRequest
121 {
122 Index = 2,
123 PageSize = 10,
124 Filters = new
ContractList<Filter>(
125 new[]{new
Filter { BinaryExpression=FilterBinaryExpression.Equal, Parameter="Name", TypeName="String",Value="Admin"},
126 new
Filter { BinaryExpression=FilterBinaryExpression.GreaterThan, Parameter="Level", TypeName="Int32", Value=1}}),
127 Sorts = new
ContractList<Sort>(
128 new[] { new
Sort { Ascending = true, TypeName = "Int32", Parameter = "Level" } })
129 });
130 /* Executes
131 SELECT [t1].[RoleID] AS [ID], [t1].[Name], [t1].[Level] AS [Level]
132 FROM (
133 SELECT ROW_NUMBER() OVER (ORDER BY [t0].[Level]) AS [ROW_NUMBER], [t0].[RoleID], [t0].[Name], [t0].[Level]
134 FROM [dbo].[Role] AS [t0]
135 WHERE ([t0].[Level] > 1) AND ([t0].[Name] = 'Admin')
136 ) AS [t1]
137 WHERE [t1].[ROW_NUMBER] BETWEEN 20 + 1 AND 20 + 10
138 ORDER BY [t1].[ROW_NUMBER]
139 */
I'm sure you have notice the TypeName properties and wondered why they are there. They enable the helper's methods to work with the expression tree before the query has been executed. Notice that the paging occurs in SQL against the table names and columns, not against the models. While the syntax is nowhere near that of LINQ, it seals of the service and keeps the paging responsibility within the service without requiring the service to handle specific paging requests. A similar method can be used to search multiple sources, and will be added shortly. Ohh, and it works across WCF.
The Unifico Framework
One major aspect to Unifico is its organization through assemblies and namespacing. Assemblies are 'cut' by component to allow for component plug-ability. One major goal of the project is to allow for a component to be easily added to an existing site without conflicting with other equally significant components. With a few modifications (to come) Unifico allows for a whole component to be dropped in as a dll without recompilation by virtue of Structure Map. Currently, each component's assembly has to be added to structure map in a common class, the 'bootstrapper'.
Within each component there are several namespaces, which are critical to understanding a component.
- App.Component.Controllers – Where ASP.NET MVC Controllers for the component are placed. These are clients to the service.
- App.Component.DataAccess.Interfaces – The interfaces for the data repository(s). These are usually rather small, with a Save, Delete and Get for each model.
- App.Component.DataAccess.SqlServer –Where the SQL specific implementation of the interface resides.
- App.Component.Diagrams – Contains the class diagrams for the component's models.
- App.Component.HttpModules – An optional namespace where any HttpModules for the component would reside.
- App.Component.Models – A namespace containing the models for the component. Models are serialized when remoting is used.
- App.Component.Models.Forms – Contains the 'Form Models', essentially requests to perform an action. For example a 'UserForm' would be populated and sent to the UserService to request a new User.
- App.Component.Service – Defines the service for the component. It is here where the WCF and in-process service definitions are located. The 'real work' of a component is defined within the service implementation.
- App.Component.Views – Contains any embedded views for the component. Embedding views are optional, but are used in the examples provided.
Without delving into details, that introduces the parts of a component's organization. Another aspect to a component is its physical organization. That is, where are various parts hosted in a distributed situation? The physical boundaries are defined by the interfaces, particularly the service interfaces. Within the service the application is hosted on the WCF service host. Outside of the service the application is hosted within the website.
Though very brief, I hope this helps anyone taking a look at the code. As always, any thoughts are appreciated.
First let me say that the code is in early state and publishing it is intended to gauge interest and recruit developers. What is the Unifico Framework (UF)? It's an architecture that has evolved while addressing various concerns in several real world projects. Currently it's nothing more than an example, and at that an example implementation of a simple example. In this example however many issues are addressed such as scalability, dependency injection, test driven development, and plug-in ability.
Written in C# against MVC Beta and ASP.NET 3.5.1 the code currently recreates the account 'component' of the MVC example template with a simple SQL Repository. The ASP.NET Membership Provider is completely replaced with a component written against the Unifico Framework's pattern. In this example several things are achieved:
- A Service Oriented Architecture (SOA) ready to be remoted through Windows Communication Foundation while using StructureMap to provide dependency injection from WCF.
- A repository based data source also protected with dependency injection that is exposed through in a pipes and filters manor. LINQ to SQL is used within a particular repository implementation, but is in no way exposed to the service.
- A Model View Controller (MVC) pattern is also used. The only objects returned from a service are models, and all controller activity is within the service itself. Virtual Paths are used to store the views within the component's assembly.
- Utility methods have been developed to provide paging across the service interfaces while leaving the 'control' in the hands of the service. The paging methods support multiple filters and multiple sorts within any paging method for a general service.
- The framework supports unit testing, however unit tests need to be added specifically for the account service. A project has been setup to show where this is done.
- 'Form' Models are used for requests to a service to allow all validation for a request to occur within the service. The responsibility of form validation is retained within a service in this manor, and prevents outside code from creating models.
There is a lot within the example, and this post will be followed with posts about specific areas. My hope in this early release is to incite interest from other developers in the community for two reasons. First, it would be nice to have the framework reviewed. Second, I hope a few developers would be interested in joining the project. It's released under the MIT license and provides a nice foundation to develop components against.
Check the project out at : Unifico Framework