Use OData with MongoDB

For the complete MongoDB documentation index, see www.mongodb.com/docs/llms.txt

Use OData with MongoDB

Overview

OData (Open Data Protocol) is a standardized protocol for building and consuming RESTful APIs that allows for the querying and manipulation of data by using HTTP requests. It provides a uniform way to expose and interact with data from multiple sources.

In this tutorial, you will learn how to integrate OData with your MongoDB application.

Sample Data

This tutorial uses the sample_restaurants.restaurants collection from the Atlas sample datasets. To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see the [Get Started with the .NET/C# Driver.](https://www.mongodb.com/docs/drivers/csharp/current/get-started.md#std-label-csharp-get-started

Tutorial

  1. Install Dependencies

Create a new ASP.Net application named ODataExample and install the .NET/C# Driver. You can install the driver by using the NuGet package manager in your IDE, or by running the following command in the .NET CLI:

shell dotnet add package MongoDB.Driver

Then, install the MongoDB.AspNetCore.OData NuGet package through the NuGet Package Manager or through the .NET CLI by running the following command:

shell dotnet add package MongoDB.AspNetCore.OData

  1. Define your Models

Create a new folder in your solution called Models and copy the following Restaurant.cs, Address.cs, and GradeEntry.cs files into the folder:

```csharp public class Restaurant { [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; }

   public string Name { get; set; }

   [BsonElement("restaurant_id")]
   public string RestaurantId { get; set; }

   public string Cuisine { get; set; }

   public Address Address { get; set; }

   public string Borough { get; set; }

   public List<GradeEntry> Grades { get; set; }

} ```

```csharp public class Address { public string Building { get; set; }

   [BsonElement("coord")]
   public double[] Coordinates { get; set; }

   public string Street { get; set; }

   [BsonElement("zipcode")]
   public string ZipCode { get; set; }

} ```

```csharp public class GradeEntry { public DateTime Date { get; set; }

   public string Grade { get; set; }

   public float? Score { get; set; }

} ```

Note:

The documents in the restaurants collection use the snake-case naming convention. The examples in this guide use a ConventionPack to deserialize the fields in the collection into Pascal case and map them to the properties in the Restaurant class.

To learn more about custom serialization, see [Custom Serialization.](https://www.mongodb.com/docs/drivers/csharp/current/serialization/poco.md#std-label-csharp-custom-serialization

  1. Create an OData Controller

Create a new folder in your solution called Controllers and add a new controller file called RestaurantsController.cs. Copy the following code into the file:

```csharp using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.OData.Routing.Controllers; using MongoDB.AspNetCore.OData; using MongoDB.Driver; using ODataTest.Models;

namespace ODataTest.Controllers;

public class RestaurantsController : ODataController { private readonly IQueryable _restaurants;

   public RestaurantsController(IMongoClient client)
   {
       var database = client.GetDatabase("sample_restaurants");
       _restaurants = database.GetCollection<Restaurant>("restaurants")
           .AsQueryable();
   }

   // Registers Get endpoint and sets max documents to 5
   [MongoEnableQuery(PageSize = 5)]
   public ActionResult<IEnumerable<Restaurant>> Get()
   {
       return Ok(_restaurants);
   }

} ```

This code performs the following actions:

  • Creates a constructor that connects to MongoDB, and gets the restaurants collection.

  • Creates a Get endpoint that returns all restaurants in the collection.

  • Specifies the MongoEnableQuery attribute to enable querying on the Get endpoint.

  • Specifies the PageSize attribute on MongoEnableQuery to limit the number of documents returned to 5.

  • Configure the OData Service

Paste the following code into your Program.cs file to configure the OData service and map your controller endpoints.

```csharp using Microsoft.AspNetCore.OData; using Microsoft.OData.ModelBuilder; using MongoDB.Bson.Serialization.Conventions; using MongoDB.Driver; using ODataTest.Models;

var builder = WebApplication.CreateBuilder(args);

// Registers a convention pack to convert fields to camel case var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() }; ConventionRegistry.Register( "CamelCase", camelCaseConvention, type => true);

builder.Services.AddSingleton( new MongoClient(""));

// Registers the Restaurants entity and sets the Id field as the key var modelBuilder = new ODataConventionModelBuilder(); modelBuilder.EntitySet("Restaurants"); modelBuilder.EntityType().HasKey(r => r.Id);

// Adds OData and specify query capabilities builder.Services.AddControllers().AddOData( options => options.Select() .AddRouteComponents("odata", modelBuilder.GetEdmModel()) );

var app = builder.Build(); app.UseRouting(); app.MapControllers();

app.Run(); ```

Note:

Replace the <“Your connection URI”> placeholder with your MongoDB connection string.

This code performs the following actions:

  • Instantiates a new MongoClient and registers it as a singleton in the dependency injection container.

  • Defines the Entity Data Model (EDM) and registers Restaurants as an entity set with the key Id.

  • Adds the OData service and enables the Select() query operation.

  • Registers the route by using the AddRouteComponents() method.

  • Calls the UseRouting() and MapControllers() methods to match incoming HTTP requests and route them to the appropriate endpoint.

Note:

The .NET/C# Driver does not support OData-Aggregation with the $apply query operation.

  1. Run the Application

Run the application by using your IDE, or by running the following command in your shell at the root directory of your project:

shell dotnet run ODataExample.csproj

After running the application, your terminal displays output similar to the following:

none info: Microsoft.Hosting.Lifetime[14] Now listening on: http://localhost:5183 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: <Path to your project>

Tip:

After running your application, your IDE might automatically open a browser window to the URL where the application is running, which displays a “page can't be found” error. This is expected because the application only has a single Get endpoint configured.

  1. Query the Data

To query the data, navigate to the Get endpoint specified in the application. To do so, open a browser and navigate to the localhost URL specified in the terminal output from the preceding step. Then, append the route for the Get endpoint: /odata/Restaurants. For example, if an application is running at localhost:5183, navigate to http://localhost:5183/odata/Restaurants.

If successful, the browser displays 5 restaurants in the collection, in JSON format. The output is similar to the following:

```json { "@odata.context": "http://localhost:5183/odata/$metadata#Restaurants", "value": [ { "Name": "Glorious Food", "RestaurantId": "40361521", "Cuisine": "American", "Borough": "Manhattan", "Id": "...", "Address": { "Building": "522", "Coordinates": [-73.95171, 40.767461], "Street": "East 74 Street", "ZipCode": "10021" }, "Grades": [ ... ] },

   ...

   ]

} ```

Additional Information

To learn more about ASP.NET Core OData, see the Microsoft OData documentation.

To learn more about OData, see the OData documentation.