Skip to content

Commit a258344

Browse files
weltekialexellis
authored andcommitted
Add announcement blog post for new dotent8-csharp template
Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
1 parent 767414b commit a258344

2 files changed

Lines changed: 265 additions & 0 deletions

File tree

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
---
2+
title: Introducing a new OpenFaaS template for C# and .NET 8
3+
description:
4+
date: 2024-04-19
5+
categories:
6+
- dotnet
7+
- functions
8+
- templates
9+
- postgres
10+
dark_background: true
11+
image: "/images/2024-04-dotnet8-csharp/background.png"
12+
author_staff_member: han
13+
hide_header_image: true
14+
---
15+
16+
We created a new template for C# and .NET 8.0. The template is based on the ASP.NET Core [Minimal API](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-8.0).
17+
18+
In the past we had an official csharp that used the original forking mode of the OpenFaaS watchdog, which created one process per request, and was less efficient than newer templates where one process would handle many requests concurrently. There were also a number of unofficial templates adopted by the community, which were not necessarily kept up to date, or something that we could support directly.
19+
20+
The new template is called: `dotnet8-csharp` and has the following benefits:
21+
22+
- Adding NuGet packages to a function for additional dependencies.
23+
- Register services for dependency injection
24+
- Using ASP.NET Core middleware
25+
26+
In the next section we will walk through an example that show you how to develop and deploy an OpenFaaS function with C# and the new template.
27+
28+
## Prerequisites
29+
30+
We won't go into detail on how to deploy OpenFaaS and assume you are already running OpenFaaS on Kubernetes or on a VM with [faasd](https://github.com/openfaas/faasd). Check out the [deployment guide](https://docs.openfaas.com/deployment/) for more information.
31+
Make sure you have the [faas-cli](https://github.com/openfaas/faas-cli) and docker installed to build and deploy functions.
32+
33+
## Tutorial: Query a Postgres database
34+
35+
In this section we will walk through an example showing how to create a function that queries a Postgres database.
36+
37+
We will assume you are already running a Postgres database somewhere. You can use one of the many DBaaS services available, run a postgres with docker or use [arkade](https://github.com/alexellis/arkade) to quickly deploy a database in your cluster. If you are running faasd, the official guide [Serverless For Everyone Else](https://openfaas.gumroad.com/l/serverless-for-everyone-else) has a chapter that shows how to deploy PostgreSQL as an additional service.
38+
39+
To quickly deploy PostgreSQL in your Kubernetes cluster run `arkade install postgresql`. After the installation it will print out all the instructions to get the password and connect to the database.
40+
41+
We will create a table and insert some records that can be queried by our function:
42+
43+
```sql
44+
CREATE TABLE IF NOT EXISTS employee
45+
(
46+
id INT PRIMARY KEY NOT NULL,
47+
name TEXT NOT NULL,
48+
email TEXT NOT NULL
49+
);
50+
51+
INSERT INTO employee (id,name,email) VALUES
52+
(1,'Alice','alice@example.com'),
53+
(2,'Bob','bob@example.com');
54+
```
55+
56+
Create a new OpenFaaS function using the `dotnet8-csharp` template. This template is available in the OpenFaaS template store.
57+
58+
```bash
59+
faas-cli template store pull dotnet8-csharp
60+
faas-cli new --lang dotnet8-csharp \
61+
employee-api
62+
mv employee-api.yml stack.yml
63+
```
64+
65+
```c#
66+
using Microsoft.AspNetCore.Builder;
67+
using Microsoft.AspNetCore.Http;
68+
using Microsoft.Extensions.DependencyInjection;
69+
using Npgsql;
70+
71+
namespace function;
72+
73+
public static class Handler
74+
{
75+
// MapEndpoints is used to register WebApplication
76+
// HTTP handlers for various paths and HTTP methods.
77+
public static void MapEndpoints(WebApplication app)
78+
{
79+
var connectionString = File.ReadAllText("/var/openfaas/secrets/pg-connection");
80+
var dataSource = NpgsqlDataSource.Create(connectionString);
81+
82+
app.MapGet("/employees", async () =>
83+
{
84+
var employees = new List<Employee>();
85+
await using (var cmd = dataSource.CreateCommand("SELECT id, name, email FROM employee"))
86+
await using (var reader = await cmd.ExecuteReaderAsync())
87+
{
88+
while (await reader.ReadAsync())
89+
{
90+
employees.Add(new Employee{
91+
Id = (int)reader["id"],
92+
Name = reader.GetString(1),
93+
Email = reader.GetString(2)
94+
});
95+
}
96+
}
97+
return Results.Ok(employees);
98+
});
99+
}
100+
101+
// MapServices can be used to configure additional
102+
// WebApplication services
103+
public static void MapServices(IServiceCollection services)
104+
{
105+
}
106+
}
107+
108+
public class Employee {
109+
public int Id { get; set; }
110+
public string? Name { get; set; }
111+
public string? Email { get; set; }
112+
}
113+
```
114+
115+
In this example we use [Npgsql](https://www.npgsql.org/) to query a PostgreSQL database. The NuGet package reference for Npgsql should be added the `function.csproj` file for the `employee-api` function. You can use the dotnet CLI for this:
116+
117+
```bash
118+
dotnet add employee-api package Npgsql --version 8.0.2
119+
```
120+
121+
In this example we use Npgsql directly but you could also use [Dapper](https://github.com/DapperLib/Dapper) for less manual object mapping or even [Entity Framework Core](https://learn.microsoft.com/en-us/ef/). The `MapServices` method can be used to register a database context.
122+
123+
The OpenFaaS philosophy is that environment variables should be used for non-confidential configuration values only, and not to inject secrets. That's why we encourage users to use the secrets functionality built into OpenFaaS. See [OpenFaaS secrets](https://docs.openfaas.com/reference/secrets/) for more information.
124+
125+
Save your database connection string in a file `pg-connection` in the `.secrets` directory. By storing secrets in this directory they can be picked up by `faas-cli local-run` which is can be used to run and test functions locally.
126+
127+
> See: [The faster way to iterate on your OpenFaaS functions](https://www.openfaas.com/blog/develop-functions-locally/)
128+
129+
The connection string for Postgres should be formatted like this:
130+
131+
```
132+
Host=postgresql;Username=postgres;Password=mysecretpassword;Database=postgres
133+
```
134+
135+
Before you deploy the function to OpenFaaS make sure the secret exists. This can be done with the faas-cli:
136+
137+
```bash
138+
faas-cli secret create pg-connection \
139+
--from-file .secrets/pg-connection
140+
```
141+
142+
Update the `stack.yml` file:
143+
144+
```yaml
145+
version: 1.0
146+
provider:
147+
name: openfaas
148+
gateway: http://127.0.0.1:8080
149+
functions:
150+
employee-api:
151+
lang: dotnet8-csharp
152+
handler: ./employee-api
153+
image: ttl.sh/employee-api:latest
154+
secrets:
155+
- pg-connection
156+
```
157+
158+
Now we can deploy to Kubernetes using OpenFaaS and faas-cli.
159+
160+
Before you deploy the function make sure the secret exists in your OpenFaaS cluster. This can be done with the faas-cli:
161+
162+
```bash
163+
faas-cli secret create pg-connection \
164+
--from-file .secrets/pg-connection
165+
```
166+
167+
Next use `faas-cli up` to build and deploy the function.
168+
169+
```
170+
export OPENFAAS_URL="" # Set a remote cluster if you have one available
171+
172+
faas-cli up
173+
```
174+
175+
Invoking the function should return a json response that looks like this:
176+
177+
```
178+
$ curl -i $OPENFAAS_URL/function/employee-api/employees
179+
180+
HTTP/1.1 200 OK
181+
Content-Length: 101
182+
Content-Type: application/json
183+
Date: Wed, 17 Apr 2024 10:30:57 GMT
184+
Server: Kestrel
185+
X-Call-Id: 49e750b6-d813-4139-9d4e-96adcf79d596
186+
X-Duration-Seconds: 0.173345
187+
X-Start-Time: 1669895320281999527
188+
189+
[
190+
{
191+
"id": 1,
192+
"name": Slice",
193+
"email": "alice@example.com"
194+
},
195+
{
196+
"id": 2,
197+
"name": "Bob",
198+
"email": "bob@example.com"
199+
}
200+
]
201+
```
202+
203+
## Dependency Injection
204+
205+
The `MapServices` method in the `Handler` class can be used to register additional services to the dependency injection container.
206+
207+
In this code snippet we register a new database context to query employees using Entity Framework:
208+
209+
```c#
210+
public static class Handler
211+
{
212+
// MapEndpoints is used to register WebApplication
213+
// HTTP handlers for various paths and HTTP methods.
214+
public static void MapEndpoints(WebApplication app)
215+
{
216+
app.MapGet("/employees", async (EmployeeDb db) =>
217+
await db.Employees.ToListAsync());
218+
}
219+
220+
// MapServices can be used to configure additional
221+
// WebApplication services
222+
public static void MapServices(IServiceCollection services)
223+
{
224+
var connectionString = File.ReadAllText("/var/openfaas/secrets/pg-connection");
225+
226+
services.AddDbContext<EmployeeDb>(
227+
optionsBuilder => optionsBuilder.UseNpgsql(connectionString)
228+
);
229+
}
230+
}
231+
```
232+
233+
## Add Middleware
234+
235+
The MapEndpoints methods gives you access the the `WebApplication` class. This makes it possible to add any existing ASP.NET Core middleware from the function.
236+
237+
```c#
238+
public static class Handler
239+
{
240+
// MapEndpoints is used to register WebApplication
241+
// HTTP handlers for various paths and HTTP methods.
242+
public static void MapEndpoints(WebApplication app)
243+
{
244+
// Setup the file server to serve static files.
245+
app.UseFileServer();
246+
247+
app.MapGet("/", () => "Hello from OpenFaaS.");
248+
}
249+
250+
// MapServices can be used to configure additional
251+
// WebApplication services
252+
public static void MapServices(IServiceCollection services)
253+
{
254+
}
255+
}
256+
257+
```
258+
259+
For more information, see: [ASP.NET Core Middleware](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-8.0)
260+
261+
## Conclusion
262+
263+
We walked through a short example to show you how to develop and deploy OpenFaaS function with C#. The new official `dotnet8-csharp` template allows you to quickly develop simple functions or a full featured API. It is based on the APS.NET Core [Minimal API](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-8.0) style and has full support for dependency injection and other ASP.NET core middleware.
264+
265+
If you already have an existing MVC API or microservice there is no need to rewrite your entire app. You can easily deploy an existing .NET app to OpenFaaS and benefit from all the OpenFaaS abstractions as long as it conforms to the [OpenFaaS workload](https://docs.openfaas.com/reference/workloads/). OpenFaaS makes deploying your apps a much simpler task than it would have been if you tried to program directly against Kubernetes. For a full overview see our blog post: [Build ASP.NET Core APIs with Kubernetes and OpenFaaS](https://www.openfaas.com/blog/asp-net-core/)
18.8 KB
Loading

0 commit comments

Comments
 (0)