Beyond Demoware: OData API, EF Core DB, and Blazor
Tags: dotnet, csharp, webdev, tutorial
Published: 2020-01-07 11:29:08

---
title: Beyond Demoware: OData API, EF Core DB, and Blazor
published: true
tags: dotnet, csharp, webdev, tutorial
canonical_url: https://wellsb.com/csharp/aspnet/odata-api-ef-core-blazor/
---

[Original article](https://wellsb.com/csharp/aspnet/odata-api-ef-core-blazor/)

In this tutorial, you will learn how to configure an OData API, integrate it with Entity Framework Core, and call the API from a server-side Blazor front-end targeting .NET Core 3.1.

An OData API allows you to easily and efficiently query, sort, filter, and paginate data from a database. Whereas a JavaScript-only solution in the DOM operating on a standard API would require you to first fetch all the data in order to sort or filter, OData ensures that only the requested data is fetched, thus saving resources.

## Set up EF Core

We will continue the [Contact Management](https://github.com/bradwellsb/blazor-contacts) solution we have been working on. You [should already have](https://wellsb.com/csharp/aspnet/blazor-httpclientfactory-and-web-api/) a `Contacts` model created in the **BlazorContacts.Shared** project. The next step is to create a database context for your contacts. In the **BlazorContacts.API** project, create a **Data** folder and add a class called **ContactsContext.cs**.

Start by referencing the EF Core namespace by adding the following `using` directive. You may have to install the package if you have not already done so.

```csharp
using Microsoft.EntityFrameworkCore;

```

Use the following class constructor to inherit from `DbContext`.

```csharp
public class ContactsContext : DbContext
{
    public ContactsContext(DbContextOptions<ContactsContext> options) : base(options)
    {
    }
 
    public DbSet<Contact> Contacts { get; set; }
}
```

With this context defined, you must now register it in your API’s **Startup.cs** file. I will use an in-memory database for this example, but feel free to use whatever database your project requires. Again, this will use the `Microsoft.EntityFrameworkCore` namespace, as well as the `BlazorContacts.API.Data` namespace you just created. For an in-memory DB, add the following code within your `ConfigureServices()` method:

```csharp
services.AddDbContext<ContactsContext>(options =>
    options.UseInMemoryDatabase("Contacts"));
```

## Configure OData API

To create an OData API, first install version 7.3.0 or greater of the `Microsoft.AspNetCore.OData` NuGet package.

```csharp
Install-Package Microsoft.AspNetCore.OData
```

Next, co configure your OData API, you must make some more changes to the **Startup.cs** file of your **BlazorContacts.API** project. With version 7.3.0, you cannot use endpoint routing on the API project. This is not a problem with our application structure, because you can still use endpoint routing on your Blazor front-end!

Disable endpoint routing and add the OData service to your project’s service collection in `ConfigureServices()`.

```csharp
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvcCore(options =>
	{
		options.EnableEndpointRouting = false;
		...
	});
	
	...
	
    services.AddOData();
 
    ...
	
}
```

Then, in the `Configure()` method, remove `UseEndpoints` and configure MVC routing for your OData project.

```csharp
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    ...

    /*
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
    */
 
    app.UseMvc(routeBuilder =>
    {
        routeBuilder.Select().Filter().OrderBy().Expand().Count().MaxTop(50);
        routeBuilder.MapODataServiceRoute("api", "api", GetEdmModel());
    });
}
```

The first line of `routeBuilder` parameters adds the OData functionality you intend to use in your project. Feel free to remove any functionality you will not need. The second defines a default route prefix `api` for this API. For example, if you configure a contacts controller (which is the next step), you will access it by calling the endpoint located at `api/contacts`, for example http://localhost:5001/api/contacts

Finally, define the EDM model to be used for parsing your API. In this case, that will be the `Contacts` model located in **BlazorContacts.Shared.Models**.

```csharp
private IEdmModel GetEdmModel()
{
    var builder = new ODataConventionModelBuilder();
    builder.EntitySet<Contact>("Contacts");
    return builder.GetEdmModel();
}
```

## Create OData API Controller

Rather than scaffolding a standard API controller based on the model and database context, simply create your own OData API controller by adding a class to the **Controllers** folder of **BlazorContacts.API**. Name the class **ContactsController.cs**.

Add the following `using` directives.

```csharp
using Microsoft.AspNet.OData.Routing;
using Microsoft.AspNet.OData;
using BlazorContacts.API.Data;
using Microsoft.EntityFrameworkCore;
```

Next, your `ContactsController` class should inherit from `ODataController` and inject the Contacts database context as a dependency.

```csharp
public class ContactsController : ODataController
{
    private readonly ContactsContext _context;
 
    public ContactsController (ContactsContext context)
    {
        _context = context;
    }
}
```

Add the following annotation above the ContactsController class definition to define the route prefix for this controller.

```csharp
[ODataRoutePrefix("contacts")]

```

Remember, you previously defined `api` as the route prefix for the entire API. In this line, you are now defining `contacts` as the route prefix for this particular controller. OData API methods in this controller will thus be accessible from `api/contacts`.

Now it is time to add GET, POST, PATCH, and DELETE routes for the API’s **ContactsController**. When configuring an OData controller, there are other annotations that can be helpful. First, the `[EnableQuery]` annotation enables querying for the API method. You can use this to enable sorting and filtering for your API’s GET methods, for example. Second, the `[ODataRoute]` annotation defines the route for the API method. Without optional parameters, it uses the default route of `api/contacts` in this case. You can also use parameters from the OData Uri; for example, you may get a specific contact by ID with the following route `[ODataRoute("({id})")]` accessible via `api/contacts(5)`.

Consider the following example methods.

```csharp
// GET: api/contacts
[EnableQuery(PageSize = 50)]
[ODataRoute]
public IQueryable<Contact> Get()
{
    return _context.Contacts;
}
 
// GET: api/contacts(5)
[EnableQuery]
[ODataRoute("({id})")]
public async Task<IActionResult> GetContact([FromODataUri] long id)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
 
    var contact = await _context.Contacts.FindAsync(id);
 
    if (contact == null)
    {
        return NotFound();
    }
 
    return Ok(contact);
}
```

For other Entity Framework Core compatible OData API methods, check out this [controller’s source code on GitHub](https://github.com/bradwellsb/blazor-contacts/blob/master/BlazorContacts.API/Controllers/ContactsController.cs).

## OData API and Blazor

You will work with an OData API the same way you would any other web API, by [using HttpClientFactory](https://wellsb.com/csharp/aspnet/blazor-httpclientfactory-and-web-api/), registering an instance of HttpClient, and injecting that service instance into your application. Now, however, you have access to extra features available with OData. You can get a count of matching items, modify the sorting order, limit the number of results, filter contacts, and even get paginated results by simply changing the query string.

var response = await \_httpClient.GetAsync($”api/contacts?$count=true&$orderby={orderBy}&$skip={skip}&$top={top}”);

For a complete example of a server-side Blazor front-end interacting with an OData API and EF Core backend, check out the [BlazorContacts.Web project on GitHub](https://github.com/bradwellsb/blazor-contacts/tree/master/BlazorContacts.Web). The [complete solution](https://github.com/bradwellsb/blazor-contacts) also includes source code for the API, the shared models library, and the authentication server. Feel free to use it as a template for your real-world Blazor applications. If you have any questions, let me know in the comments!

[Original article](https://wellsb.com/csharp/aspnet/odata-api-ef-core-blazor/)