Skip to content

Commit 9c74320

Browse files
DOCSP-32418 Add OData tutorial (#286)
(cherry picked from commit 606a34c)
1 parent ea27c34 commit 9c74320

File tree

4 files changed

+319
-0
lines changed

4 files changed

+319
-0
lines changed

source/fundamentals.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,27 @@ Fundamentals
1111
:titlesonly:
1212
:maxdepth: 1
1313

14+
/fundamentals/connection
15+
/fundamentals/database-collection
16+
/fundamentals/crud
17+
/fundamentals/builders
18+
/fundamentals/atlas-search
19+
/fundamentals/stable-api
20+
/fundamentals/authentication
21+
/fundamentals/enterprise-authentication
22+
/fundamentals/aggregation
23+
/fundamentals/linq
24+
/fundamentals/bson
25+
/fundamentals/specify-query
26+
/fundamentals/serialization
27+
/fundamentals/transactions
28+
/fundamentals/indexes
29+
/fundamentals/logging
30+
/fundamentals/time-series
31+
/fundamentals/encrypt-fields
32+
/fundamentals/geo
33+
/fundamentals/odata
34+
1435
Connection </fundamentals/connection>
1536
Databases & Collections </fundamentals/database-collection>
1637
CRUD Operations </fundamentals/crud>
@@ -31,6 +52,8 @@ Fundamentals
3152
In-Use Encryption </fundamentals/encrypt-fields>
3253
Search Geospatially </fundamentals/geo>
3354
Replica Set Operations </fundamentals/read-write-configuration>
55+
OData </fundamentals/odata>
56+
3457

3558
- :ref:`Connecting to MongoDB <csharp-connection>`
3659
- :ref:`csharp-db-coll`
@@ -51,4 +74,5 @@ Fundamentals
5174
- :ref:`csharp-time-series`
5275
- :ref:`Encrypt Fields <csharp-fle>`
5376
- :ref:`csharp-geo`
77+
- :ref:`csharp-odata`
5478
- :ref:`csharp-read-write-config`

source/fundamentals/odata.txt

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
.. _csharp-odata:
2+
3+
======================
4+
Use OData with MongoDB
5+
======================
6+
7+
.. facet::
8+
:name: genre
9+
:values: tutorial
10+
11+
.. meta::
12+
:keywords: asp.net, integration, code example, enable query
13+
14+
.. contents:: On this page
15+
:local:
16+
:backlinks: none
17+
:depth: 2
18+
:class: singlecol
19+
20+
Overview
21+
--------
22+
23+
OData (Open Data Protocol) is a standardized protocol for building and consuming
24+
RESTful APIs that allows for the querying and manipulation of data by using
25+
HTTP requests. It provides a uniform way to expose and interact
26+
with data from multiple sources.
27+
28+
In this tutorial, you will learn how to integrate OData with your MongoDB application.
29+
30+
Sample Data
31+
~~~~~~~~~~~
32+
33+
This tutorial uses the ``sample_restaurants.restaurants`` collection
34+
from the :atlas:`Atlas sample datasets </sample-data>`. To learn how to create a
35+
free MongoDB Atlas cluster and load the sample datasets, see the :ref:`<csharp-quickstart>`.
36+
37+
Tutorial
38+
--------
39+
40+
.. procedure::
41+
42+
.. step:: Install Dependencies
43+
44+
Create a new ASP.Net application named
45+
``ODataExample`` and install the {+driver-short+}. You can install the
46+
driver by using the NuGet package manager in your IDE, or by running the
47+
following command in the .NET CLI:
48+
49+
.. code-block:: shell
50+
51+
dotnet add package MongoDB.Driver
52+
53+
Then, install the ``MongoDB.AspNetCore.OData`` NuGet
54+
package through the NuGet Package Manager or through the .NET CLI by running the
55+
following command:
56+
57+
.. code-block:: shell
58+
59+
dotnet add package MongoDB.AspNetCore.OData
60+
61+
.. step:: Define your Models
62+
63+
Create a new folder in your solution called ``Models`` and copy the
64+
following ``Restaurant.cs``, ``Address.cs``, and ``GradeEntry.cs`` files into the
65+
folder:
66+
67+
.. literalinclude:: /includes/code-examples/RestaurantOdata.cs
68+
:language: csharp
69+
:copyable:
70+
:dedent:
71+
72+
.. literalinclude:: /includes/code-examples/Address.cs
73+
:language: csharp
74+
:copyable:
75+
:dedent:
76+
77+
.. literalinclude:: /includes/code-examples/GradeEntry.cs
78+
:language: csharp
79+
:copyable:
80+
:dedent:
81+
82+
.. include:: /includes/convention-pack-note.rst
83+
84+
.. step:: Create an OData Controller
85+
86+
Create a new folder in your solution called ``Controllers`` and add a new
87+
controller file called ``RestaurantsController.cs``. Copy the following code
88+
into the file:
89+
90+
.. literalinclude:: /includes/fundamentals/code-examples/connection/OData.cs
91+
:language: csharp
92+
:start-after: // start-controller
93+
:end-before: // end-controller
94+
95+
This code performs the following actions:
96+
97+
- Creates a constructor that connects to MongoDB, and gets the
98+
``restaurants`` collection.
99+
- Creates a ``Get`` endpoint that returns all restaurants in the collection.
100+
- Specifies the ``MongoEnableQuery`` attribute to enable querying on the
101+
``Get`` endpoint.
102+
- Specifies the ``PageSize`` attribute on ``MongoEnableQuery`` to limit the
103+
number of documents returned to ``5``.
104+
105+
.. step:: Configure the OData Service
106+
107+
Paste the following code into your ``Program.cs`` file to configure the OData
108+
service and map your controller endpoints.
109+
110+
.. literalinclude:: /includes/fundamentals/code-examples/connection/OData.cs
111+
:language: csharp
112+
:start-after: // start-configure
113+
:end-before: // end-configure
114+
115+
.. note::
116+
117+
Replace the ``<"Your connection URI">`` placeholder with your MongoDB connection string.
118+
119+
This code performs the following actions:
120+
121+
- Instantiates a new ``MongoClient`` and registers it as a singleton in
122+
the dependency injection container.
123+
- Defines the Entity Data Model (EDM) and registers ``Restaurants`` as an
124+
entity set with the key ``Id``.
125+
- Adds the OData service and enables the ``Select()`` query operation.
126+
- Registers the route by using the ``AddRouteComponents()`` method.
127+
- Calls the ``UseRouting()`` and ``MapControllers()`` methods to match
128+
incoming HTTP requests and route them to the appropriate endpoint.
129+
130+
.. note::
131+
132+
The {+driver-short+} does not support OData-Aggregation with the
133+
``$apply`` query operation.
134+
135+
.. step:: Run the Application
136+
137+
Run the application by using your IDE, or by running the following command
138+
in your shell at the root directory of your project:
139+
140+
.. code-block:: shell
141+
142+
dotnet run ODataExample.csproj
143+
144+
After running the application, your terminal displays output similar
145+
to the following:
146+
147+
.. code-block:: none
148+
149+
info: Microsoft.Hosting.Lifetime[14]
150+
Now listening on: http://localhost:5183
151+
info: Microsoft.Hosting.Lifetime[0]
152+
Application started. Press Ctrl+C to shut down.
153+
info: Microsoft.Hosting.Lifetime[0]
154+
Hosting environment: Development
155+
info: Microsoft.Hosting.Lifetime[0]
156+
Content root path: <Path to your project>
157+
158+
.. tip::
159+
160+
After running your application, your IDE might automatically open a
161+
browser window to the URL where the application is running, which
162+
displays a ``"page can't be found"`` error. This is expected because the
163+
application only has a single ``Get`` endpoint configured.
164+
165+
.. step:: Query the Data
166+
167+
To query the data, navigate to the ``Get`` endpoint specified in the
168+
application. To do so, open a browser and navigate to the ``localhost``
169+
URL specified in the terminal output from the preceding step. Then, append
170+
the route for the ``Get`` endpoint: ``/odata/Restaurants``. For example, if an
171+
application is running at ``localhost:5183``, navigate to
172+
``http://localhost:5183/odata/Restaurants``.
173+
174+
If successful, the browser displays 5 restaurants in the
175+
collection, in JSON format. The output is similar to the
176+
following:
177+
178+
.. code-block:: json
179+
180+
{
181+
"@odata.context": "http://localhost:5183/odata/$metadata#Restaurants",
182+
"value": [
183+
{
184+
"Name": "Glorious Food",
185+
"RestaurantId": "40361521",
186+
"Cuisine": "American",
187+
"Borough": "Manhattan",
188+
"Id": "...",
189+
"Address": {
190+
"Building": "522",
191+
"Coordinates": [-73.95171, 40.767461],
192+
"Street": "East 74 Street",
193+
"ZipCode": "10021"
194+
},
195+
"Grades": [
196+
...
197+
]
198+
},
199+
200+
...
201+
202+
]
203+
}
204+
205+
Additional Information
206+
----------------------
207+
208+
To learn more about ASP.NET Core OData, see the `Microsoft OData documentation
209+
<https://learn.microsoft.com/en-us/odata/webapi-8/overview>`__.
210+
211+
To learn more about OData, see the `OData documentation
212+
<https://www.odata.org/documentation>`__.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
public class Restaurant
2+
{
3+
[BsonRepresentation(BsonType.ObjectId)]
4+
public string Id { get; set; }
5+
6+
public string Name { get; set; }
7+
8+
[BsonElement("restaurant_id")]
9+
public string RestaurantId { get; set; }
10+
11+
public string Cuisine { get; set; }
12+
13+
public Address Address { get; set; }
14+
15+
public string Borough { get; set; }
16+
17+
public List<GradeEntry> Grades { get; set; }
18+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// start-controller
2+
using Microsoft.AspNetCore.Mvc;
3+
using Microsoft.AspNetCore.OData.Routing.Controllers;
4+
using MongoDB.AspNetCore.OData;
5+
using MongoDB.Driver;
6+
using ODataTest.Models;
7+
8+
namespace ODataTest.Controllers;
9+
10+
public class RestaurantsController : ODataController
11+
{
12+
private readonly IQueryable<Restaurant> _restaurants;
13+
14+
public RestaurantsController(IMongoClient client)
15+
{
16+
var database = client.GetDatabase("sample_restaurants");
17+
_restaurants = database.GetCollection<Restaurant>("restaurants")
18+
.AsQueryable();
19+
}
20+
21+
// Registers Get endpoint and sets max documents to 5
22+
[MongoEnableQuery(PageSize = 5)]
23+
public ActionResult<IEnumerable<Restaurant>> Get()
24+
{
25+
return Ok(_restaurants);
26+
}
27+
}
28+
// end-controller
29+
30+
// start-configure
31+
using Microsoft.AspNetCore.OData;
32+
using Microsoft.OData.ModelBuilder;
33+
using MongoDB.Bson.Serialization.Conventions;
34+
using MongoDB.Driver;
35+
using ODataTest.Models;
36+
37+
var builder = WebApplication.CreateBuilder(args);
38+
39+
// Registers a convention pack to convert fields to camel case
40+
var camelCaseConvention = new ConventionPack {
41+
new CamelCaseElementNameConvention()
42+
};
43+
ConventionRegistry.Register(
44+
"CamelCase", camelCaseConvention, type => true);
45+
46+
builder.Services.AddSingleton<IMongoClient>(
47+
new MongoClient("<Your connection URI>"));
48+
49+
// Registers the Restaurants entity and sets the Id field as the key
50+
var modelBuilder = new ODataConventionModelBuilder();
51+
modelBuilder.EntitySet<Restaurant>("Restaurants");
52+
modelBuilder.EntityType<Restaurant>().HasKey(r => r.Id);
53+
54+
// Adds OData and specify query capabilities
55+
builder.Services.AddControllers().AddOData(
56+
options => options.Select()
57+
.AddRouteComponents("odata", modelBuilder.GetEdmModel())
58+
);
59+
60+
var app = builder.Build();
61+
app.UseRouting();
62+
app.MapControllers();
63+
64+
app.Run();
65+
// end-configure

0 commit comments

Comments
 (0)