O-Data Rest API in .NET with Entity Framework and AutoFac


This is an introductory article about creating an Odata Rest API in collaboration with Entity Framework. We are also going to use Autofac as our IOC container. Also, Repository and Unit of Work pattern will be used for cleaner access of persistence model through our ORM (Entity Framework).

I originally posted this article on CodeProject.com and you can find the link here

Introduction

The conventional REST API method does not provide much flexibility when it comes to customizing the CRUD operation. This results in adding custom method(s) in the controller of our API that suits our need. 

However, when it comes with OData Rest API, certain things are available out of the box that we can use right from the "URL" instead of writing separate action method(s) in our controller. This is a huge time saver and reduces the code size. 

Since, each technology has its own pros and cons. I wouldn't say OData is Ideal for Rest API development. You should always look at the situation and make a pragmatic decision. However, my motto is to let you know how to create OData res API in collaboration with Entity Framework 6.

We are also going to use Autofac as our IOC container.

We are also going to implement Repository and Unit of Work pattern for cleaner access to persistence model(database) through our ORM.


Github Link


You can also download the source code from my github page at https://github.com/SunnyMakode/OData.NetFramework.git

Background

πŸ‘‰ OData: OData or Open Data Protocol is an open protocol which allows the creation and consumption of queryable and interoperable RESTful APIs in a simple and standard way.

πŸ‘‰Rest API: It is a named or representation state transfer application programming interface that makes use of HTTP verbs like Get for getting some info, Put/Patch for updating info, Delete for delete and so on

πŸ‘‰ IOC: IoC Container (or Dependency Injection Container) is a framework for implementing automatic dependency injection. Example of such IOC containers are Autofac, Castle Windsor, Unity, etc.

πŸ‘‰ ORM: Object-Relational Mapping (ORM) is a technique that lets you query and manipulate data from a database using an object-oriented paradigm.

πŸ‘‰ MVC: An Architectural style that helps in segregating Model ("business model and rules"), Controller ("manipulate or operate on those model based on a request received by means of routing") and Views (presentation)

πŸ‘‰ Repository and Unit of Work Pattern: It's a bridge between database tables and Entity Framework. It(repository pattern) gives an illusion that database tables are nothing but a property or an in memory object. It also helps to insulate your application from changes in the data store (unit of work). It provides cleaner access to persistence model(data base) through our ORM. Some people don't prefer to use this pattern and rely solely on datacontext class of Entity Framework. Well, this is a subjective topic but I personally feel that Repository and Unit of Work provides a cleaner way to do data centric operations.

Let's Get Started

Step 1: Initial Setup

Open Visual Studio (I am using VS 2019) and create ASP.NET web application by name of project as ODataRestApiWithEntityFramework, you can keep the same name for solution.

Select Project Template as WebApi.

Step 2: Create Some Infrastructure

Add a solution folder with name "Infrastructure". Inside this folder, add four library projects with below names:

πŸ‘‰  OData.Business: This will hold our domain classes.

πŸ‘‰  OData.InternalDataService: This will be our internal communication channel or data service.

πŸ‘‰  OData.IOC: This will be used it for Dependency Injection.

πŸ‘‰  OData.ORM: This will be used for Entity Framework related operation.

Your complete solution structure should look as in the image below:


Step 3: Adding Model Files

Create folder DomainClasses in OData.Business and all model files as Project.cs and ProjectDetail.cs.

Project.cs

ProjectDetail.cs


Step 4: Adding Db Context

Inside OData.ORM, add a folder named Context. Add file name ODataDbContext.cs inside it. Also, install the Entity Framework as a nuget package.



Step 5: Add ConnectionString

Step 6: Add Migration and Update Database

πŸ‘‰ I am using MS SQL Server 2014. Make sure you have SQL Server installed. You can also make use of SQL Lite but you need to make the changes accordingly with connection string, etc.

πŸ‘‰Open package manager console (Tools => Nuget Package Manager => Package Manager Console).

πŸ‘‰ And type the following commands in sequence inside OData.ORM.


PM> enable-migrations


enable-migrations will enable the migration for the lifetime of application development. This will create a Configuration.cs file with Migration folder inside OData.ORM project.



Now, add the migration, (in case you have my code from github, simply do enable-migration and update-database).


PM> add-migration "InitialScaffolding"

Now, update the database with migration:
PM> update-database

This will create a database ODataDb with the table, Projects and ProjectDetails.

πŸ‘‰ Note: For some reason, the connectionString placed inside app.config file in OData.ORM is not getting recognized so I have to place it in web.config in ODataRestApiWithEntityFramework. If it works for you in OData.ORM, then go for it.

Step 7: Implementing Repository and Unit Of Work Pattern in OData.ORM

Add Interface IGenericRepository.cs and its implementation class GenericRepository.cs.

For repository and unit of work pattern, we are following a generic approach so that our data service can use it with any entity type (data table type).

Note: Please refer to my github link for accuracy.

IGenericRepository.cs:

GenericRepository.cs:

IUnitOfWork.cs:

UnitOfWork.cs:


Step 8: Add IOC Container Autofac in OData.IOC

πŸ‘‰ Install Autofac nuget package in OData.IOC

πŸ‘‰ Add 2 files, DataServiceModule.cs and OrmModule.cs

πŸ‘‰ Also, add AutoFacConfig.cs in project ODataRestApiWithEntityFramework

πŸ‘‰ Make changes in Global.asax file that is present inside the project ODataRestApiWithEntityFramework

Step 9: Add Internal Data Service (Repository Service) in OData.InternalDataService

Add Service.cs that will be our base for UnitOfWork


In order to access our data table like Projects, ProjectDetails, etc., we will make use of our generic repository. For that, add classes like ProjectRepository.cs (this class will act as an illusion of working with Project table in database).

ProjectRepository.cs


Note: I've also added additional Repository class (ProjectDetailRepository.cs) in github project, you can refer to it for more information.

IProjectRepository.cs

Step 10: Adding OData in "ODataRestApiWithEntityFramework"

Kindly install nuget packages like Microsoft.AspNet.OData and Microsoft.AspNet.WebApi.OData.

Arrange your WebApiConfig.cs as below:


πŸ‘‰ Note: Make sure that you don't mix the OData V4 and OData V3 packages. Else, this will create a problem to display data on browser or client side and you won't be getting an error.

Also make sure that if you have ODate V3/V4 packages, then the namespaces should be the same in that of webapiconfig.cs and API controller.

In case you get an Entity Framework error, then do install nuget package for Entity Framework in project ODataRestApiWithEntityFramework as well.

Step 11: Finally, Add ProjectController.cs with REST Full Methods



Test the OData Rest API with PostMan

Just to play around a bit, add some records in the Projects and ProjectDetails table manually or by using seed method inside Configuration.cs. However, it is recommended that you can add the records using the http Post verb. 

Post usually expects an object so it would be recommended to use a tool called as PostMan or similar framework to do that job.

Build the entire solution and run the project ODataRestApiWithEntityFramework.

You will get the following output on browser screen:


πŸ‘‰ In your case the port number might be different, in my case it is 44385

πŸ‘‰ Now to fetch all the records from Project table, use the following query   https://localhost:44385/Project



πŸ‘‰ To fetch a specific record from Project table, use the following query   https://localhost:44385/Project(1)



πŸ‘‰To fetch the inner known properties (Detail is one such property, typical case of lazy loading ) inside Project, then use https://localhost:44385/Project?$expand=Detail


You can play with other actions in Http like Post/Put/Delete etc.


Also there are various OData query options, some common are as under:

πŸ‘‰ $top: Can be used to retrieve top n records from a data store

πŸ‘‰ $orderby: Can be used to sort the data in ascending or descending order

πŸ‘‰ $filter: Can be used to filter the data based on some condition

πŸ‘‰ $skip: Can be used along with $orderby to skip certain number of records



Point of Interest

πŸ‘‰  The steps given above can be reduced if you are using dot net core, since it now has support for Dependency Injection.

πŸ‘‰  We've invested a favorable amount of time in infrastructure because that is the core idea to make this application as loosely coupled as possible so that it can be extended and unit tested.

πŸ‘‰ It is recommended that we should use asynchronous call for our action method.

πŸ‘‰  GraphQL has some similarity with Odata as both of them support URL query based operation.

πŸ‘‰  Special care must be taken that we are not mixing any package of OData v4 or OData V3. Your application on server side won't break however, your browser will not accept the data due to inconsistency.

πŸ‘‰Make sure that webapiconfig.cs and API controller have the same namespaces with respect to the OData. If you mix it with OData v4 and OData V3, then point 5 might occur and there is no proper documentation available for it.

πŸ‘‰  If your client application consuming this API is not in the same domain as your REST API, then consider adding CORS support in your API application.

πŸ‘‰  Odata is not specific with MVC web API, it can be used with Rest full WCF, etc.

Comments

Popular Posts