diff --git a/docs/reference/csharp/api/api-delete.mdx b/docs/reference/csharp/api/api-delete.mdx
new file mode 100644
index 000000000..9bdef22af
--- /dev/null
+++ b/docs/reference/csharp/api/api-delete.mdx
@@ -0,0 +1,131 @@
+---
+description: "Reference for Nitric's .NET library - Register an API route and set a specific HTTP DELETE handler on that route."
+---
+
+# .NET - Api.Delete()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about APIs
+ in Nitric start with the [API docs](/api).
+
+
+Register an API route and set a specific HTTP DELETE handler on that route.
+
+
+ This method is a convenient short version of
+ [Api().Route().Delete()](./api-route-delete)
+
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Delete("/hello/:name", async (ctx) => {
+ var name = ctx.Req.PathParams["name"];
+
+ ctx.Res.Text($"Deleting {name}!");
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The path matcher to use for the route. Matchers accept path parameters in
+ the form of a colon prefixed string. The string provided will be used as
+ that path parameter's name when calling middleware and handlers. See [create
+ a route with path params](#create-a-route-with-path-params)
+
+
+ One or more middleware functions to use as the handler for HTTP requests.
+ Handlers can be sync or async.
+
+
+
+## Examples
+
+### Register a handler for DELETE requests
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Delete("/hello/:name", async (ctx) => {
+ var name = ctx.Req.PathParams["name"];
+
+ ctx.Res.Text($"Deleting {name}!");
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Chain functions as a single method handler
+
+When multiple functions are provided they will be called as a chain. If one succeeds, it will move on to the next. This allows middleware to be composed into more complex handlers.
+
+```csharp
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Delete("/hello/:userId",
+ new Middleware[] {
+ async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ // Validate the user identity
+ if (user != "1234")
+ {
+ ctx.Res.Text($"User {user} is unauthorised");
+ ctx.Res.Status = 403;
+
+ // Return prematurely to end the middleware chain.
+ return ctx;
+ }
+
+ // Call next to continue the middleware chain.
+ return await next(ctx);
+ }, async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ ctx.Res.Text($"Deleting {user}");
+
+ return await next(ctx);
+ }
+ }
+);
+
+Application.Run();
+```
+
+### Access the request body
+
+The DELETE request body is accessible from the `context.Req` object.
+
+```csharp
+using System.Collections.Generic;
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Delete("/hello/:name", async (ctx) => {
+ var body = ctx.Req.Json>();
+ // parse, validate and store the request payload...
+ return ctx;
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/api/api-get.mdx b/docs/reference/csharp/api/api-get.mdx
new file mode 100644
index 000000000..c719e02fc
--- /dev/null
+++ b/docs/reference/csharp/api/api-get.mdx
@@ -0,0 +1,112 @@
+---
+description: "Reference for Nitric's .NET library - Register an API route and set a specific HTTP GET handler on that route."
+---
+
+# .NET - Api.Get()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about APIs
+ in Nitric start with the [API docs](/api).
+
+
+Register an API route and set a specific HTTP GET handler on that route.
+
+
+ This method is a convenient short version of
+ [Api().Route().Get()](./api-route-get)
+
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Get("/hello/:name", async (ctx) => {
+ var name = ctx.Req.PathParams["name"];
+
+ ctx.Res.Text($"Getting {name}!");
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The path matcher to use for the route. Matchers accept path parameters in
+ the form of a colon prefixed string. The string provided will be used as
+ that path parameter's name when calling middleware and handlers. See [create
+ a route with path params](#create-a-route-with-path-params)
+
+
+ One or more middleware functions to use as the handler for HTTP requests.
+ Handlers can be sync or async.
+
+
+
+## Examples
+
+### Register a handler for GET requests
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Get("/hello/:name", async (ctx) => {
+ var name = ctx.Req.PathParams["name"];
+
+ ctx.Res.Text($"Getting {name}!");
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Chain functions as a single method handler
+
+When multiple functions are provided they will be called as a chain. If one succeeds, it will move on to the next. This allows middleware to be composed into more complex handlers.
+
+```csharp
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Get("/hello/:userId",
+ new Middleware[] {
+ async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ // Validate the user identity
+ if (user != "1234")
+ {
+ ctx.Res.Text($"User {user} is unauthorised");
+ ctx.Res.Status = 403;
+
+ // Return prematurely to end the middleware chain.
+ return ctx;
+ }
+
+ // Call next to continue the middleware chain.
+ return await next(ctx);
+ }, async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ ctx.Res.Text($"Getting {user}");
+
+ return await next(ctx);
+ }
+ }
+);
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/api/api-patch.mdx b/docs/reference/csharp/api/api-patch.mdx
new file mode 100644
index 000000000..9e8abb28d
--- /dev/null
+++ b/docs/reference/csharp/api/api-patch.mdx
@@ -0,0 +1,131 @@
+---
+description: "Reference for Nitric's .NET library - Register an API route and set a specific HTTP PATCH handler on that route."
+---
+
+# .NET - Api.Patch()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about APIs
+ in Nitric start with the [API docs](/api).
+
+
+Register an API route and set a specific HTTP PATCH handler on that route.
+
+
+ This method is a convenient short version of
+ [Api().Route().Patch()](./api-route-patch)
+
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Patch("/hello/:name", async (ctx) => {
+ var name = ctx.Req.PathParams["name"];
+
+ ctx.Res.Text($"Patching {name}!");
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The path matcher to use for the route. Matchers accept path parameters in
+ the form of a colon prefixed string. The string provided will be used as
+ that path parameter's name when calling middleware and handlers. See [create
+ a route with path params](#create-a-route-with-path-params)
+
+
+ One or more middleware functions to use as the handler for HTTP requests.
+ Handlers can be sync or async.
+
+
+
+## Examples
+
+### Register a handler for PATCH requests
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Patch("/hello/:name", async (ctx) => {
+ var name = ctx.Req.PathParams["name"];
+
+ ctx.Res.Text($"Patching {name}!");
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Chain functions as a single method handler
+
+When multiple functions are provided they will be called as a chain. If one succeeds, it will move on to the next. This allows middleware to be composed into more complex handlers.
+
+```csharp
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Patch("/hello/:userId",
+ new Middleware[] {
+ async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ // Validate the user identity
+ if (user != "1234")
+ {
+ ctx.Res.Text($"User {user} is unauthorised");
+ ctx.Res.Status = 403;
+
+ // Return prematurely to end the middleware chain.
+ return ctx;
+ }
+
+ // Call next to continue the middleware chain.
+ return await next(ctx);
+ }, async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ ctx.Res.Text($"Patching {user}");
+
+ return await next(ctx);
+ }
+ }
+);
+
+Application.Run();
+```
+
+### Access the request body
+
+The PATCH request body is accessible from the `context.Req` object.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var api = Application.Api("main");
+
+api.Patch("/hello/:name", async (ctx) => {
+ var body = ctx.Req.Json>();
+ // parse, validate and store the request payload...
+ return ctx;
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/api/api-post.mdx b/docs/reference/csharp/api/api-post.mdx
new file mode 100644
index 000000000..7eaf41cfa
--- /dev/null
+++ b/docs/reference/csharp/api/api-post.mdx
@@ -0,0 +1,131 @@
+---
+description: "Reference for Nitric's .NET library - Register an API route and set a specific HTTP POST handler on that route."
+---
+
+# .NET - Api.Post()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about APIs
+ in Nitric start with the [API docs](/api).
+
+
+Register an API route and set a specific HTTP POST handler on that route.
+
+
+ This method is a convenient short version of
+ [Api().Route().Post()](./api-route-post)
+
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Post("/hello/:name", async (ctx) => {
+ var name = ctx.Req.PathParams["name"];
+
+ ctx.Res.Text($"Creating {name}!");
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The path matcher to use for the route. Matchers accept path parameters in
+ the form of a colon prefixed string. The string provided will be used as
+ that path parameter's name when calling middleware and handlers. See [create
+ a route with path params](#create-a-route-with-path-params)
+
+
+ One or more middleware functions to use as the handler for HTTP requests.
+ Handlers can be sync or async.
+
+
+
+## Examples
+
+### Register a handler for POST requests
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Post("/hello/:name", async (ctx) => {
+ var name = ctx.Req.PathParams["name"];
+
+ ctx.Res.Text($"Creating {name}!");
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Chain functions as a single method handler
+
+When multiple functions are provided they will be called as a chain. If one succeeds, it will move on to the next. This allows middleware to be composed into more complex handlers.
+
+```csharp
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Post("/hello/:userId",
+ new Middleware[] {
+ async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ // Validate the user identity
+ if (user != "1234")
+ {
+ ctx.Res.Text($"User {user} is unauthorised");
+ ctx.Res.Status = 403;
+
+ // Return prematurely to end the middleware chain.
+ return ctx;
+ }
+
+ // Call next to continue the middleware chain.
+ return await next(ctx);
+ }, async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ ctx.Res.Text($"Creating {user}");
+
+ return await next(ctx);
+ }
+ }
+);
+
+Application.Run();
+```
+
+### Access the request body
+
+The POST request body is accessible from the `ctx.req` object.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var api = Application.Api("main");
+
+api.Post("/hello/:name", async (ctx) => {
+ var body = ctx.Req.Json>();
+ // parse, validate and store the request payload...
+ return ctx;
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/api/api-put.mdx b/docs/reference/csharp/api/api-put.mdx
new file mode 100644
index 000000000..3e58c8495
--- /dev/null
+++ b/docs/reference/csharp/api/api-put.mdx
@@ -0,0 +1,131 @@
+---
+description: "Reference for Nitric's .NET library - Register an API route and set a specific HTTP PUT handler on that route."
+---
+
+# .NET - Api.Put()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about APIs
+ in Nitric start with the [API docs](/api).
+
+
+Register an API route and set a specific HTTP PUT handler on that route.
+
+
+ This method is a convenient short version of
+ [Api().Route().Put()](./api-route-put)
+
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Put("/hello/:name", async (ctx) => {
+ var name = ctx.Req.PathParams["name"];
+
+ ctx.Res.Text($"Updating {name}!");
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The path matcher to use for the route. Matchers accept path parameters in
+ the form of a colon prefixed string. The string provided will be used as
+ that path parameter's name when calling middleware and handlers. See [create
+ a route with path params](#create-a-route-with-path-params)
+
+
+ One or more middleware functions to use as the handler for HTTP requests.
+ Handlers can be sync or async.
+
+
+
+## Examples
+
+### Register a handler for PUT requests
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Put("/hello/:name", async (ctx) => {
+ var name = ctx.Req.PathParams["name"];
+
+ ctx.Res.Text($"Updating {name}!");
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Chain functions as a single method handler
+
+When multiple functions are provided they will be called as a chain. If one succeeds, it will move on to the next. This allows middleware to be composed into more complex handlers.
+
+```csharp
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+api.Put("/hello/:userId",
+ new Middleware[] {
+ async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ // Validate the user identity
+ if (user != "1234")
+ {
+ ctx.Res.Text($"User {user} is unauthorised");
+ ctx.Res.Status = 403;
+
+ // Return prematurely to end the middleware chain.
+ return ctx;
+ }
+
+ // Call next to continue the middleware chain.
+ return await next(ctx);
+ }, async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ ctx.Res.Text($"Updating {user}");
+
+ return await next(ctx);
+ }
+ }
+);
+
+Application.Run();
+```
+
+### Access the request body
+
+The PUT request body is accessible from the `ctx.req` object.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var api = Application.Api("main");
+
+api.Put("/hello/:name", async (ctx) => {
+ var body = ctx.Req.Json>();
+ // parse, validate and store the request payload...
+ return ctx;
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/api/api-route-all.mdx b/docs/reference/csharp/api/api-route-all.mdx
new file mode 100644
index 000000000..a0caa0f46
--- /dev/null
+++ b/docs/reference/csharp/api/api-route-all.mdx
@@ -0,0 +1,164 @@
+---
+description: "Reference for Nitric's .NET library - Register a single handler for all HTTP Methods (GET, POST, PUT, DELETE, PATCH) on the route."
+---
+
+# .NET - Api.Route.All()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about APIs
+ in Nitric start with the [API docs](/api).
+
+
+Register a single handler for all HTTP Methods (GET, POST, PUT, DELETE, PATCH) on the route.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+route.All(async (ctx) => {
+ // Construct a response for all incoming HTTP requests
+ var responseBody = new Dictionary();
+ ctx.Res.Json(responseBody);
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ One or more middleware functions to use as the handler for HTTP requests.
+ Handlers can be sync or async.
+
+
+
+## Notes
+
+When using the `All()` method to register a single function as the handler for all HTTP methods, none of the other methods should be defined on that route.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var route = Application.Api("main").Route("/customers");
+
+route.All(async (ctx) => {
+ /* handle all requests */
+});
+
+// Don't call `Get()`, `Post()`, etc., they're already handled by `all()`
+route.Get(async (ctx) => {
+ // This handler won't work
+})
+
+Application.Run();
+```
+
+## Examples
+
+### Register a method handler function
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+route.All(async (ctx) => {
+ // Construct a response for all incoming HTTP requests
+ var responseBody = new Dictionary();
+ ctx.Res.Json(responseBody);
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Chain functions as a single method handler
+
+When multiple functions are provided they will be called as a chain. If one succeeds, it will move on to the next. This allows middleware to be composed into more complex handlers.
+
+```csharp
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+var route = Application.Api("main").Route("/customers");
+
+route.All(new Middleware[] {
+ async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ // Validate the user identity
+ if (user != "1234")
+ {
+ ctx.Res.Text($"User {user} is unauthorised");
+ ctx.Res.Status = 403;
+
+ // Return prematurely to end the middleware chain.
+ return ctx;
+ }
+
+ // Call next to continue the middleware chain.
+ return next(ctx);
+ }, async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ ctx.Res.Text($"Handling {user}");
+
+ return next(ctx);
+ }
+});
+
+Application.Run();
+```
+
+### Access the request body
+
+For methods that include a request body, such as `POST` and `PUT`, you can access the body from the `ctx.req` object.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+route.All(async (ctx) => {
+ var body = ctx.Req.Json>();
+ // parse, validate and store the request payload...
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Error Handling
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+try {
+ route.All(async (ctx) => {
+ // Construct a response for all incoming HTTP requests
+ var responseBody = new Dictionary();
+ ctx.Res.Json(responseBody);
+
+ return ctx;
+ });
+
+ Application.Run();
+} catch (Error err) {
+ // error handling
+}
+```
diff --git a/docs/reference/csharp/api/api-route-delete.mdx b/docs/reference/csharp/api/api-route-delete.mdx
new file mode 100644
index 000000000..aa8da139c
--- /dev/null
+++ b/docs/reference/csharp/api/api-route-delete.mdx
@@ -0,0 +1,126 @@
+---
+description: "Reference for Nitric's .NET library - Register a handler for HTTP DELETE requests to the route."
+---
+
+# .NET - Api.Route.Delete()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about APIs
+ in Nitric start with the [API docs](/api).
+
+
+Register a handler for HTTP DELETE requests to the route.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+route.Delete(async (ctx) => {
+ // Construct a response for all incoming HTTP requests
+ var responseBody = new Dictionary();
+ ctx.Res.Json(responseBody);
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The path matcher to use for the route. Matchers accept path parameters in
+ the form of a colon prefixed string. The string provided will be used as
+ that path parameter's name when calling middleware and handlers. See [create
+ a route with path params](#create-a-route-with-path-params)
+
+
+ One or more middleware functions to use as the handler for HTTP requests.
+ Handlers can be sync or async.
+
+
+
+## Examples
+
+### Register a handler for DELETE requests
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+route.Delete(async (ctx) => {
+ // Construct a response for all incoming HTTP requests
+ var responseBody = new Dictionary();
+ ctx.Res.Json(responseBody);
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Chain functions as a single method handler
+
+When multiple functions are provided they will be called as a chain. If one succeeds, it will move on to the next. This allows middleware to be composed into more complex handlers.
+
+```csharp
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+var route = Application.Api("main").Route("/customers/:userId");
+
+route.Delete(new Middleware[] {
+ async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ // Validate the user identity
+ if (user != "1234")
+ {
+ ctx.Res.Text($"User {user} is unauthorised");
+ ctx.Res.Status = 403;
+
+ // Return prematurely to end the middleware chain.
+ return ctx;
+ }
+
+ // Call next to continue the middleware chain.
+ return await next(ctx);
+ }, async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ ctx.Res.Text($"Deleting {user}");
+
+ return await next(ctx);
+ }
+});
+
+Application.Run();
+```
+
+### Access the request body
+
+The DELETE request body is accessible from the `ctx.req` object.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+route.Delete(async (ctx) => {
+ var body = ctx.Req.Json>();
+ // parse, validate and store the request payload...
+ return ctx;
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/api/api-route-get.mdx b/docs/reference/csharp/api/api-route-get.mdx
new file mode 100644
index 000000000..b83c3f23e
--- /dev/null
+++ b/docs/reference/csharp/api/api-route-get.mdx
@@ -0,0 +1,107 @@
+---
+description: "Reference for Nitric's .NET library - Register a handler for HTTP GET requests to the route."
+---
+
+# .NET - Api.Route.Get()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about APIs
+ in Nitric start with the [API docs](/api).
+
+
+Register a handler for HTTP GET requests to the route.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+route.Get(async (ctx) => {
+ // Construct a response for all incoming HTTP requests
+ var responseBody = new Dictionary();
+ ctx.Res.Json(responseBody);
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The path matcher to use for the route. Matchers accept path parameters in
+ the form of a colon prefixed string. The string provided will be used as
+ that path parameter's name when calling middleware and handlers. See [create
+ a route with path params](#create-a-route-with-path-params)
+
+
+ One or more middleware functions to use as the handler for HTTP requests.
+ Handlers can be sync or async.
+
+
+
+## Examples
+
+### Register a handler for GET requests
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+route.Get(async (ctx) => {
+ // Construct a response for all incoming HTTP requests
+ var responseBody = new Dictionary();
+ ctx.Res.Json(responseBody);
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Chain functions as a single method handler
+
+When multiple functions are provided they will be called as a chain. If one succeeds, it will move on to the next. This allows middleware to be composed into more complex handlers.
+
+```csharp
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+var route = Application.Api("main").Route("/customers");
+
+route.Get(new Middleware[] {
+ async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ // Validate the user identity
+ if (user != "1234")
+ {
+ ctx.Res.Text($"User {user} is unauthorised");
+ ctx.Res.Status = 403;
+
+ // Return prematurely to end the middleware chain.
+ return ctx;
+ }
+
+ // Call next to continue the middleware chain.
+ return await next(ctx);
+ }, async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ ctx.Res.Text($"Getting {user}");
+
+ return await next(ctx);
+ }
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/api/api-route-patch.mdx b/docs/reference/csharp/api/api-route-patch.mdx
new file mode 100644
index 000000000..1845d3e4d
--- /dev/null
+++ b/docs/reference/csharp/api/api-route-patch.mdx
@@ -0,0 +1,124 @@
+---
+description: "Reference for Nitric's .NET library - Register a handler for HTTP PATCH requests to the route."
+---
+
+# .NET - Api.Route.Patch()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about APIs
+ in Nitric start with the [API docs](/api).
+
+
+Register a handler for HTTP PATCH requests to the route.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var route = Application.Api("main").Route("/customers/:userId");
+
+route.Patch(async (ctx) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ ctx.Res.Text($"Patching {user}");
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The path matcher to use for the route. Matchers accept path parameters in
+ the form of a colon prefixed string. The string provided will be used as
+ that path parameter's name when calling middleware and handlers. See [create
+ a route with path params](#create-a-route-with-path-params)
+
+
+ One or more middleware functions to use as the handler for HTTP requests.
+ Handlers can be sync or async.
+
+
+
+## Examples
+
+### Register a handler for PATCH requests
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var route = Application.Api("main").Route("/customers/:userId");
+
+route.Patch(async (ctx) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ ctx.Res.Text($"Patching {user}");
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Chain functions as a single method handler
+
+When multiple functions are provided they will be called as a chain. If one succeeds, it will move on to the next. This allows middleware to be composed into more complex handlers.
+
+```csharp
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+var route = Application.Api("main").Route("/customers/:userId");
+
+route.Patch(new Middleware[] {
+ async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ // Validate the user identity
+ if (user != "1234")
+ {
+ ctx.Res.Text($"User {user} is unauthorised");
+ ctx.Res.Status = 403;
+
+ // Return prematurely to end the middleware chain.
+ return ctx;
+ }
+
+ // Call next to continue the middleware chain.
+ return await next(ctx);
+ }, async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ ctx.Res.Text($"Patching {user}");
+
+ return await next(ctx);
+ }
+});
+
+Application.Run();
+```
+
+### Access the request body
+
+The PATCH request body is accessible from the `ctx.Req` object.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var api = Application.Api("main").Route("/customers");
+
+route.Patch(async (ctx) => {
+ var body = ctx.Req.Json>();
+ // parse, validate and store the request payload...
+ return ctx;
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/api/api-route-post.mdx b/docs/reference/csharp/api/api-route-post.mdx
new file mode 100644
index 000000000..20a271350
--- /dev/null
+++ b/docs/reference/csharp/api/api-route-post.mdx
@@ -0,0 +1,126 @@
+---
+description: "Reference for Nitric's .NET library - Register a handler for HTTP POST requests to the route."
+---
+
+# .NET - Api.Route.Post()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about APIs
+ in Nitric start with the [API docs](/api).
+
+
+Register a handler for HTTP POST requests to the route.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+route.Post(async (ctx) => {
+ // Construct a response for all incoming HTTP requests
+ var responseBody = new Dictionary();
+ ctx.Res.Json(responseBody);
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The path matcher to use for the route. Matchers accept path parameters in
+ the form of a colon prefixed string. The string provided will be used as
+ that path parameter's name when calling middleware and handlers. See [create
+ a route with path params](#create-a-route-with-path-params)
+
+
+ One or more middleware functions to use as the handler for HTTP requests.
+ Handlers can be sync or async.
+
+
+
+## Examples
+
+### Register a handler for POST requests
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+route.Post(async (ctx) => {
+ // Construct a response for all incoming HTTP requests
+ var responseBody = new Dictionary();
+ ctx.Res.Json(responseBody);
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Chain functions as a single method handler
+
+When multiple functions are provided they will be called as a chain. If one succeeds, it will move on to the next. This allows middleware to be composed into more complex handlers.
+
+```csharp
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+var route = Application.Api("main").Route("/customers/:userId");
+
+route.Post(new Middleware[] {
+ async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ // Validate the user identity
+ if (user != "1234")
+ {
+ ctx.Res.Text($"User {user} is unauthorised");
+ ctx.Res.Status = 403;
+
+ // Return prematurely to end the middleware chain.
+ return ctx;
+ }
+
+ // Call next to continue the middleware chain.
+ return await next(ctx);
+ }, async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ ctx.Res.Text($"Creating {user}");
+
+ return await next(ctx);
+ }
+});
+
+Application.Run();
+```
+
+### Access the request body
+
+The POST request body is accessible from the `ctx.req` object.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+route.Post(async (ctx) => {
+ var body = ctx.Req.Json>();
+ // parse, validate and store the request payload...
+ return ctx;
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/api/api-route-put.mdx b/docs/reference/csharp/api/api-route-put.mdx
new file mode 100644
index 000000000..2d5ec221a
--- /dev/null
+++ b/docs/reference/csharp/api/api-route-put.mdx
@@ -0,0 +1,125 @@
+---
+description: "Reference for Nitric's .NET library - Register a handler for HTTP PUT requests to the route."
+---
+
+# .NET - Api.Route.Put()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about APIs
+ in Nitric start with the [API docs](/api).
+
+
+Register a handler for HTTP PUT requests to the route.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+route.Put(async (ctx) => {
+ // Construct a response for all incoming HTTP requests
+ var responseBody = new Dictionary();
+ ctx.Res.Json(responseBody);
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The path matcher to use for the route. Matchers accept path parameters in
+ the form of a colon prefixed string. The string provided will be used as
+ that path parameter's name when calling middleware and handlers. See [create
+ a route with path params](#create-a-route-with-path-params)
+
+
+ One or more middleware functions to use as the handler for HTTP requests.
+ Handlers can be sync or async.
+
+
+
+## Examples
+
+### Register a handler for PUT requests
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var route = Application.Api("main").Route("/customers");
+
+route.Put(async (ctx) => {
+ // Construct a response for all incoming HTTP requests
+ var responseBody = new Dictionary();
+ ctx.Res.Json(responseBody);
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Chain functions as a single method handler
+
+When multiple functions are provided they will be called as a chain. If one succeeds, it will move on to the next. This allows middleware to be composed into more complex handlers.
+
+```csharp
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+var route = Application.Api("main").Route("/customers/:userId");
+
+route.Put(new Middleware[] {
+ async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ // Validate the user identity
+ if (user != "1234")
+ {
+ ctx.Res.Text($"User {user} is unauthorised");
+ ctx.Res.Status = 403;
+
+ // Return prematurely to end the middleware chain.
+ return ctx;
+ }
+
+ // Call next to continue the middleware chain.
+ return await next(ctx);
+ }, async (ctx, next) => {
+ var user = ctx.Req.PathParams["userId"];
+
+ ctx.Res.Text($"Updating {user}");
+
+ return await next(ctx);
+ }
+});
+
+Application.Run();
+```
+
+### Access the request body
+
+The PUT request body is accessible from the `ctx.req` object.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using System.Collections.Generic;
+
+var route = Application.Api("main").Route("/customers");
+
+route.Put(async (ctx) => {
+ var body = ctx.Req.Json>();
+ // parse, validate and store the request payload...
+ return ctx;
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/api/api-route.mdx b/docs/reference/csharp/api/api-route.mdx
new file mode 100644
index 000000000..975725bad
--- /dev/null
+++ b/docs/reference/csharp/api/api-route.mdx
@@ -0,0 +1,103 @@
+---
+description: "Reference for Nitric's .NET library - Creates a new route (path) within an API."
+---
+
+# .NET - Api.Route()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about APIs
+ in Nitric start with the [API docs](/api).
+
+
+Creates a new route (path) within an API.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var route = Application.Api("main").Route("/customers");
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The path matcher to use for this route. Calling `route` on the same API more
+ than once with the same matcher will return the same route object. Matchers
+ accept path parameters in the form of a colon prefixed string. The string
+ provided will be used as that path parameter's name when calling middleware
+ and handlers. See [create a route with path
+ params](#create-a-route-with-path-params)
+
+
+ Additional options when creating the route.
+
+
+ Middleware to apply to all methods on this route.
+
+
+
+
+
+## Notes
+
+The `middleware` property on the `options` param is useful for applying universal middleware such as CORS headers or Auth, across an entire route. However, if methods aren't registered, the route won't be deployed. If you need to run the same handler for all methods on a route, you should use [route.all()](./api-route-all)
+
+## Examples
+
+### Create a route
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var route = Application.Api("main").Route("/customers");
+
+Application.Run();
+```
+
+### Create a route with path params
+
+Route paths can include dynamic parameters. These values will automatically be parsed and provided in the context object for your middleware and handlers as a `string`.
+
+For example, if you have a customers path and you want to include a `customerId` param you would define the route like this.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var route = Application.Api("main").Route("/customers/:customerId");
+
+Application.Run();
+```
+
+### Create a route with middleware
+
+```csharp
+using Nitric.Sdk.Service;
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var main = Application.Api("main");
+
+var route = main.Route("/customers", new RouteOptions(middleware: new Middleware[] {
+ async (ctx, next) =>
+ {
+ var user = ctx.Req.PathParams["userId"];
+
+ // Validate the user identity
+ if (user != "1234")
+ {
+ ctx.Res.Text($"User {user} is unauthorised");
+ ctx.Res.Status = 403;
+
+ // Return prematurely to end the middleware chain.
+ return ctx;
+ }
+
+ // Call next to continue the middleware chain.
+ return await next(ctx);
+ }
+}));
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/api/api.mdx b/docs/reference/csharp/api/api.mdx
new file mode 100644
index 000000000..7cea2eef2
--- /dev/null
+++ b/docs/reference/csharp/api/api.mdx
@@ -0,0 +1,160 @@
+---
+description: "Reference for Nitric's .NET library - Create APIs with the Nitric C# SDK"
+---
+
+# .NET - Api()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about APIs
+ in Nitric start with the [API docs](/api).
+
+
+Creates a new HTTP API.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The unique name of this API within the app. Subsequent calls to `api` with
+ the same name will return the same object.
+
+
+ Additional options when creating the API.
+
+
+ Base path for all routes in the API.
+
+
+ Middleware to apply to all routes and methods of the API.
+
+
+ Security rules to apply with scopes to the entire API.
+
+
+
+
+
+### OidcOptions Parameters
+
+
+
+ the name of the security definition
+
+
+ the issuer for the JWT tokens e.g.{' '}
+ https://account.region.auth0.com
+
+
+ the aud that will be applied to JWT tokens from the issuer.
+
+
+ the scopes that will be required to authenticate.
+
+
+
+## Notes
+
+The `middleware` property on the `options` param is useful for applying universal middleware such as CORS headers or Auth, across an entire API from a single place.
+
+## Examples
+
+### Create an API
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var api = Application.Api("main");
+
+Application.Run();
+```
+
+### Create an API with universal middleware
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using Nitric.Sdk.Resource;
+using Nitric.Sdk.Service;
+
+var api = Application.Api("main", new ApiOptions(
+ middleware: new Middleware[] {
+ async (ctx, next) => {
+ return next(ctx);
+ }
+ }
+));
+
+api.Get("/example", async (ctx) =>
+{
+ ctx.Res.Text("Hello World!");
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Create an API with a base path
+
+If you need to put all the routes in your api below a shared base path, you can do that with the `BaseRoute` option. In this example we ensure all routes start with `/api/v1/` before the route specific path.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using Nitric.Sdk.Resource;
+
+var api = Application.Api("main", new ApiOptions(
+ basePath: "/api/v1"
+));
+
+// Define API routes
+api.Get("/example", async (ctx) =>
+{
+ ctx.Res.Text("Hello World!");
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Apply JWT authentication to an API
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using Nitric.Sdk.Resource;
+using System.Collections.Generic;
+
+// Define security configuration
+var securityOptions = new OidcOptions[]
+{
+ new OidcOptions(
+ name: "user",
+ audiences: ["YOUR_AUDIENCES"],
+ issuer: "https://example-issuer.com",
+ // Optionally apply required scopes to this api
+ // in this case users will require the products:read scope to access the API
+ scopes: new string[] { "products:read" }
+ )
+};
+
+var secureApi = Application.Api("main", new ApiOptions(
+ security: securityOptions
+));
+
+// Define API routes
+api.Get("/example", async (ctx) =>
+{
+ ctx.Res.Text("Hello, Secure World!");
+ return ctx;
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/batch/job-handler.mdx b/docs/reference/csharp/batch/job-handler.mdx
new file mode 100644
index 000000000..ac444c0a6
--- /dev/null
+++ b/docs/reference/csharp/batch/job-handler.mdx
@@ -0,0 +1,94 @@
+---
+description: "Reference for Nitric's .NET library - Register a job handler"
+---
+
+# .NET - Job.Handler()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about Batch
+ Services in Nitric start with the [Batch docs](/batch).
+
+
+Job handlers are the code that is run when a job request is submitted. These handlers should be written in a separate file to your services.
+
+```csharp
+using Nitric.Sdk.Resource;
+using System.Collections.Generic;
+using Application = Nitric.Sdk.Nitric;
+
+var analyze = Application.Job>("analyze");
+
+analyze.Handler(async (ctx) =>
+{
+ // Do some work
+ return ctx;
+}, new JobResourceRequirements(cpus: 1, memory: 1024, gpus: 1));
+
+Application.Run();
+```
+
+## Defining Batches
+
+Batches are defined in different files to services and referenced in a project's `nitric.yaml` file. For example:
+
+```yaml
+batch-services:
+ - match: ./batch/**/*.csproj
+ start: dotnet run --project $SERVICE_PATH
+```
+
+## Parameters
+
+
+
+ One or more middleware services to use as the handler which will run on the
+ defined frequency.
+
+
+
+ The number of CPUs to allocate to the handler
+
+
+ The number of GPUs to allocate to the handler
+
+
+ The amount of memory (MB) to allocate to the handler
+
+
+
+
+## Examples
+
+### Define a job handler with default resource requirements
+
+```csharp
+using System.Collections.Generic;
+using Application = Nitric.Sdk.Nitric;
+
+var analyze = Application.Job>('analyze');
+
+analyze.Handler(async (ctx) => {
+ // Do some work
+ return ctx
+});
+
+Application.Run();
+```
+
+### Create a job handler with custom resource requirements
+
+```csharp
+using Nitric.Sdk.Resource;
+using System.Collections.Generic;
+using Application = Nitric.Sdk.Nitric;
+
+var analyze = Application.Job>("analyze");
+
+analyze.Handler(async (ctx) =>
+{
+ // Do some work
+ return ctx;
+}, new JobResourceRequirements(cpus: 1, memory: 1024, gpus: 1));
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/batch/job-submit.mdx b/docs/reference/csharp/batch/job-submit.mdx
new file mode 100644
index 000000000..7e03ed3f4
--- /dev/null
+++ b/docs/reference/csharp/batch/job-submit.mdx
@@ -0,0 +1,48 @@
+---
+description: "Reference for Nitric's .NET library - Submit a batch job request with custom resource requirements"
+---
+
+# .NET - Job.Submit()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about Batch
+ Services in Nitric start with the [Batch docs](/batch).
+
+
+Jobs may be submitted from Nitric `services` or other `batches` using the `Submit` method on the job reference. When submitting a job you can provide a payload that will be passed to the job handler function.
+
+```csharp
+using Nitric.Sdk.Resource;
+using System.Collections.Generic;
+using Application = Nitric.Sdk.Nitric;
+
+var analyze = Application.Job>("analyze").Allow(JobPermission.Submit);
+
+await analyze.Submit(new Dictionary() { { "message", "message contents" } });
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The data that will be sent to the submit
+
+
+
+## Examples
+
+### Submit a job request
+
+```csharp
+using Nitric.Sdk.Resource;
+using System.Collections.Generic;
+using Application = Nitric.Sdk.Nitric;
+
+var analyze = Application.Job>("analyze").Allow(JobPermission.Submit);
+
+await analyze.Submit(new Dictionary() { { "message", "message contents" } });
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/batch/job.mdx b/docs/reference/csharp/batch/job.mdx
new file mode 100644
index 000000000..757a4de27
--- /dev/null
+++ b/docs/reference/csharp/batch/job.mdx
@@ -0,0 +1,55 @@
+---
+description: "Reference for Nitric's .NET library - Create Batch Jobs"
+---
+
+# .NET - Job()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about Batch
+ Services in Nitric start with the [Batch docs](/batch).
+
+
+Creates a new Batch Job.
+
+```csharp
+using System.Collections.Generic;
+using Application = Nitric.Sdk.Nitric;
+
+var analyze = Application.Job>("analyze");
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The unique name of this Batch Job within the app. Subsequent calls to `Job`
+ with the same name will return the same object.
+
+
+
+## Examples
+
+### Create a Job
+
+```csharp
+using System.Collections.Generic;
+using Application = Nitric.Sdk.Nitric;
+
+var analyze = Application.Job>("analyze");
+
+Application.Run();
+```
+
+### Create a Job with permissions to submit jobs
+
+```csharp
+using Nitric.Sdk.Resource;
+using System.Collections.Generic;
+using Application = Nitric.Sdk.Nitric;
+
+var analyze = Application.Job>("analyze").Allow(JobPermission.Submit);
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/index.mdx b/docs/reference/csharp/index.mdx
new file mode 100644
index 000000000..e80e032f3
--- /dev/null
+++ b/docs/reference/csharp/index.mdx
@@ -0,0 +1,39 @@
+---
+description: "Reference for Nitric's .NET library - Using Nitric with .NET"
+---
+
+# Nitric\'s .NET SDK
+
+This SDK reference provides documentation for the functions and methods in Nitric\'s .NET library.
+
+The library provides the ability to define and interact with cloud resources, as well as build application logic like functions/handlers.
+
+
+ This is reference documentation for the Nitric .NET SDK. If you're just
+ learning Nitric, we recommend starting with the
+ [Quickstart](/get-started/quickstart) guide.
+
+
+## Installation
+
+If you used a Nitric starter template for .NET to scaffold your project, then the `Nitric.Sdk` package will already be included in the dependencies in your `.csproj` file. Using starter templates is the recommended installation option since it ensures the other files and configuration needed are also set up.
+
+However, you can also install the SDK.
+
+```bash
+dotnet add package Nitric.Sdk
+```
+
+## Custom runtime
+
+To successfully run and deploy .NET applications using the Nitric framework, it is necessary to use a custom runtime Dockerfile. This Dockerfile ensures that your .NET application is built and executed within an appropriate environment, taking into account all dependencies and configurations required by Nitric.
+
+### Default Dockerfile
+
+For your convenience, Nitric provides a default Dockerfile specifically tailored for .NET applications. This default Dockerfile is included with the [.NET starter template](https://github.com/nitrictech/examples/tree/main/v1/dotnet-starter) available through the Nitric CLI. By using this template, you can quickly set up your development environment and focus on building your application without worrying about Docker configuration.
+
+This Dockerfile provides a solid starting point for deploying .NET applications with Nitric. Feel free to customize it according to your application's needs.
+
+## Source
+
+The source for the SDK is available on [GitHub](https://github.com/nitrictech/dotnet-sdk).
diff --git a/docs/reference/csharp/keyvalue/keyvalue-delete.mdx b/docs/reference/csharp/keyvalue/keyvalue-delete.mdx
new file mode 100644
index 000000000..61e433dfb
--- /dev/null
+++ b/docs/reference/csharp/keyvalue/keyvalue-delete.mdx
@@ -0,0 +1,58 @@
+---
+description: "Reference for Nitric's .NET library - Delete key from a key value store."
+---
+
+# .NET - KV.Delete()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Key/Value Stores in Nitric start with the [Key/Value Store docs](/keyvalue).
+
+
+Delete key from a key value store.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name;
+ public int Age;
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Delete);
+
+profiles.Delete("profile-1a2b3c");
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The key that references the key value pair that should be deleted.
+
+
+
+## Examples
+
+### Delete a key
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name;
+ public int Age;
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Delete);
+
+profiles.Delete("profile-1a2b3c");
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/keyvalue/keyvalue-get.mdx b/docs/reference/csharp/keyvalue/keyvalue-get.mdx
new file mode 100644
index 000000000..b9cf98cca
--- /dev/null
+++ b/docs/reference/csharp/keyvalue/keyvalue-get.mdx
@@ -0,0 +1,58 @@
+---
+description: "Reference for Nitric's .NET library - Get a value from a key value store."
+---
+
+# .NET - KV.Get()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Key/Value Stores in Nitric start with the [Key/Value Store docs](/keyvalue).
+
+
+Get a value from a key value store.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name;
+ public int Age;
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Get);
+
+var profile = profiles.Get("profile-1a2b3c");
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The key that references the key value pair that should be retrieved.
+
+
+
+## Examples
+
+### Get a key value pair
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name;
+ public int Age;
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Get);
+
+var profile = profiles.Get("profile-1a2b3c");
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/keyvalue/keyvalue-keys.mdx b/docs/reference/csharp/keyvalue/keyvalue-keys.mdx
new file mode 100644
index 000000000..a6623da87
--- /dev/null
+++ b/docs/reference/csharp/keyvalue/keyvalue-keys.mdx
@@ -0,0 +1,95 @@
+---
+description: "Reference for Nitric's .NET library - Retrieve all or some of the keys from a value store."
+---
+
+# .NET - KV.Keys()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Key/Value Stores in Nitric start with the [Key/Value Store docs](/keyvalue).
+
+
+Return an async iterable of keys in the store.
+
+```csharp
+using System;
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name;
+ public int Age;
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Set, KeyValueStorePermission.Get, KeyValueStorePermission.Delete);
+
+var keys = profiles.Keys();
+
+while (await keys.MoveNext())
+{
+ Console.WriteLine(keys.Current);
+}
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The prefix to filter keys by, if not provided all keys will be returned.
+
+
+
+## Examples
+
+### Get all keys from a key value store
+
+```csharp
+using System;
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name;
+ public int Age;
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Set, KeyValueStorePermission.Get, KeyValueStorePermission.Delete);
+
+var keys = profiles.Keys();
+
+while (await keys.MoveNext())
+{
+ Console.WriteLine(keys.Current);
+}
+
+Application.Run();
+```
+
+### Get keys filtered by prefix from a key value store
+
+```csharp
+using System;
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name;
+ public int Age;
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Set, KeyValueStorePermission.Get, KeyValueStorePermission.Delete);
+
+var keys = profiles.Keys("profile-");
+
+while (await keys.MoveNext())
+{
+ Console.WriteLine(keys.Current);
+}
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/keyvalue/keyvalue-set.mdx b/docs/reference/csharp/keyvalue/keyvalue-set.mdx
new file mode 100644
index 000000000..e0478f501
--- /dev/null
+++ b/docs/reference/csharp/keyvalue/keyvalue-set.mdx
@@ -0,0 +1,61 @@
+---
+description: "Reference for Nitric's .NET library - Store a key value pair in a key value store."
+---
+
+# .NET - KV.Set()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Key/Value Stores in Nitric start with the [Key/Value Store docs](/keyvalue).
+
+
+Store a key value pair in a key value store.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name { get; set; }
+ public int Age { get; set; }
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Set);
+
+profiles.Set("profile-1a2b3c", new Profile() { Name = "John Smith", Age = 21 });
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The key that references value.
+
+
+ A json serializable object that is stored as the value.
+
+
+
+## Examples
+
+### Set a key value pair
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name { get; set; }
+ public int Age { get; set; }
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Set);
+
+profiles.Set("profile-1a2b3c", new Profile() { Name = "John Smith", Age = 21 });
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/keyvalue/keyvalue.mdx b/docs/reference/csharp/keyvalue/keyvalue.mdx
new file mode 100644
index 000000000..c30838703
--- /dev/null
+++ b/docs/reference/csharp/keyvalue/keyvalue.mdx
@@ -0,0 +1,163 @@
+---
+description: "Reference for Nitric's .NET library - Creates a new key value store to get, set, and delete key value pairs."
+---
+
+# .NET - KV()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Key/Value Stores in Nitric start with the [Key/Value Store docs](/keyvalue).
+
+
+Creates a new key value store to get, set, and delete key value pairs.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name;
+ public int Age;
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Set, KeyValueStorePermission.Get, KeyValueStorePermission.Delete);
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The unique name of this key value store within the service. Subsequent calls
+ to `kv` with the same name will return the same object.
+
+
+
+## Access
+
+All Nitric resources provide access permissions you can use to specify the level of access your service needs to the resource. See here for details about infrastructure [security](/get-started/foundations/infrastructure/security).
+
+### Available permissions:
+
+---
+
+**KeyValueStorePermission.Get**
+
+This permission allows your service to get values from the key value store.
+
+---
+
+**KeyValueStorePermission.Set**
+
+This permission allows your service to set key value pairs in the key value store.
+
+---
+
+**KeyValueStorePermission.Delete**
+
+This permission allows your service to delete key value pairs in the key value store.
+
+---
+
+## Examples
+
+### Create a key value store
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name;
+ public int Age;
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Set, KeyValueStorePermission.Get, KeyValueStorePermission.Delete);
+
+Application.Run();
+```
+
+### Get value from a key value store
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name;
+ public int Age;
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Get);
+
+var profile = profiles.Get("profile-1a2b3c");
+
+Application.Run();
+```
+
+### Set a key in a key value store
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name { get; set; }
+ public int Age { get; set; }
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Set);
+
+profiles.Set("profile-1a2b3c", new Profile() { Name = "John Smith", Age = 21 });
+
+Application.Run();
+```
+
+### Delete a key from a key value store
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name;
+ public int Age;
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Delete);
+
+profiles.Delete("profile-1a2b3c");
+
+Application.Run();
+```
+
+### Get all keys from a key value store
+
+```csharp
+using System;
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class Profile
+{
+ public string Name;
+ public int Age;
+}
+
+var profiles = Application.KV("profiles").Allow(KeyValueStorePermission.Set, KeyValueStorePermission.Get, KeyValueStorePermission.Delete);
+
+var keys = profiles.Keys();
+
+while (await keys.MoveNext())
+{
+ Console.WriteLine(keys.Current);
+}
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/queues/queue-dequeue.mdx b/docs/reference/csharp/queues/queue-dequeue.mdx
new file mode 100644
index 000000000..802c80d35
--- /dev/null
+++ b/docs/reference/csharp/queues/queue-dequeue.mdx
@@ -0,0 +1,101 @@
+---
+description: "Reference for Nitric's .NET library - Receive tasks from a queue."
+---
+
+# .NET - Queue.Dequeue()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about Queues
+ in Nitric start with the [Async Messaging docs](/messaging#queues).
+
+
+Receive tasks from a queue.
+
+```csharp
+using System;
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class UserRequest
+{
+ public string UserId { get; set; }
+ public string Message { get; set; }
+}
+
+var batchQueue = Application.Queue("batch").Allow(QueuePermission.Dequeue);
+
+var tasks = batchQueue.Dequeue();
+
+tasks.ForEach(task => {
+ // Work on a task...
+ Console.WriteLine($"Request from user {task.Message.UserId}: {task.Message.Message}");
+
+ // Complete the task
+ task.Complete();
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The maximum number of tasks to receive from the queue. Defaults to 1.
+
+
+
+## Notes
+
+### Completing tasks
+
+Since the process is async, the queue doesn't know when a task has been completed. So failed function/containers don't result in lost tasks, tasks are not removed from a queue when they're received.
+
+Instead, tasks are hidden and receivers are granted a temporary lease for each task they receive.
+
+When complete, the receiver must tell the queue the task was completed successfully, which will remove it from the queue and stop it being reprocessed.
+
+
+ Failing to complete a task before the lease expires will result in it being
+ re-queued.
+
+
+To notify the queue that a task was completed call the `Complete()` method on the task reference.
+
+### Receive depth
+
+When calling `Receive()` a depth parameter can be provided, e.g. `Receive(5)`. This will _attempt_ to receive up to 5 tasks from the queue.
+
+However, if the queue is empty or less than 5 tasks are available on the queue, then the max available will be returned.
+
+This means calls to receive will return between 0 and _depth_ tasks.
+
+## Examples
+
+### Receive tasks from a queue
+
+```csharp
+using System;
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class UserRequest
+{
+ public string UserId { get; set; }
+ public string Message { get; set; }
+}
+
+var batchQueue = Application.Queue("batch").Allow(QueuePermission.Dequeue);
+
+var tasks = batchQueue.Dequeue();
+
+tasks.ForEach(task => {
+ // Work on a task...
+ Console.WriteLine($"Request from user {task.Message.UserId}: {task.Message.Message}");
+
+ // Complete the task
+ task.Complete();
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/queues/queue-enqueue.mdx b/docs/reference/csharp/queues/queue-enqueue.mdx
new file mode 100644
index 000000000..197ccd20e
--- /dev/null
+++ b/docs/reference/csharp/queues/queue-enqueue.mdx
@@ -0,0 +1,104 @@
+---
+description: "Reference for Nitric's .NET library - Send tasks to a queue."
+---
+
+# .NET - Queue.Enqueue()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about Queues
+ in Nitric start with the [Async Messaging docs](/messaging#queues).
+
+
+Send tasks to a queue.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class UserRequest
+{
+ public string UserId { get; set; }
+ public string Message { get; set; }
+}
+
+var batchQueue = Application.Queue("batch").Allow(QueuePermission.Enqueue);
+
+batchQueue.Enqueue(new UserRequest
+{
+ UserId = "1234",
+ Message = "Hello!"
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The task or an array of tasks to send to the queue.
+
+
+
+## Examples
+
+### Enqueue a task onto a queue
+
+```csharp
+using System.Collections.Generic;
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class UserRequest
+{
+ public string UserId { get; set; }
+ public string Message { get; set; }
+}
+
+var batchQueue = Application.Queue("batch").Allow(QueuePermission.Enqueue);
+
+batchQueue.Enqueue(new UserRequest
+{
+ UserId = "user_1234",
+ Message = "Hello!"
+});
+
+Application.Run();
+```
+
+### Enqueue multiple tasks onto a queue
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var batchQueue = Application.Queue("batch").Allow(QueuePermission.Enqueue);
+
+batchQueue.Enqueue(
+ new UserRequest
+ {
+ UserId = "user_1",
+ Message = "Batch Task 1"
+ }, new UserRequest
+ {
+ UserId = "user_2",
+ Message = "Batch Task 2"
+ }
+);
+
+Application.Run();
+```
+
+### Dealing with failures
+
+In rare cases when sending tasks to a queue some tasks might fail to be sent. The response from `send()` will include an array of any tasks that failed to send. You can process this array to retry or log the error.
+
+```csharp
+var failedTasks = await batchQueue.Enqueue(tasks);
+
+failedTasks.ForEach(failedTask => {
+ Console.WriteLine(failedTask.ID);
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/queues/queue.mdx b/docs/reference/csharp/queues/queue.mdx
new file mode 100644
index 000000000..fb2bddcd8
--- /dev/null
+++ b/docs/reference/csharp/queues/queue.mdx
@@ -0,0 +1,103 @@
+---
+description: "Reference for Nitric's .NET library - Creates a new Queue to send and receive asynchronous tasks."
+---
+
+# .NET - Queue()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about Queues
+ in Nitric start with the [Async Messaging docs](/messaging#queues).
+
+
+Creates a new Queue to send and receive asynchronous tasks.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class UserRequest
+{
+ public string UserId { get; set; }
+ public string Message { get; set; }
+}
+
+var batchQueue = Application.Queue("batchQueue").Allow(QueuePermission.Enqueue);
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The unique name of this Queue within the app. Subsequent calls to `queue`
+ with the same name will return the same object.
+
+
+
+## Access
+
+All Nitric resources provide access permissions you can use to specify the level of access your code needs to the resource. See here for details about infrastructure [security](/get-started/foundations/infrastructure/security).
+
+### Available permissions:
+
+---
+
+**QueuePermission.Enqueue**
+
+This permission allows your code to enqueue new tasks to the queue.
+
+---
+
+**QueuePermission.Dequeue**
+
+This permission allows your code to dequeue tasks from the queue.
+
+---
+
+### Notes
+
+In most instances, code should either enqueue to or dequeue from a queue, usually not both.
+
+## Examples
+
+### Create a Queue
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class UserRequest
+{
+ public string UserId { get; set; }
+ public string Message { get; set; }
+}
+
+var batchQueue = Application.Queue("batchQueue");
+
+Application.Run();
+```
+
+### Dequeue tasks from a queue
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class UserRequest
+{
+ public string UserId { get; set; }
+ public string Message { get; set; }
+}
+
+var batchQueue = Application.Queue("batchQueue").With(QueuePermission.Dequeue);
+
+var tasks = batchQueue.Dequeue();
+
+Application.Run();
+```
+
+### See also
+
+- [Queue.Dequeue()](./queue-dequeue)
+- [Queue.Enqueue()](./queue-enqueue)
diff --git a/docs/reference/csharp/schedule/schedule-cron.mdx b/docs/reference/csharp/schedule/schedule-cron.mdx
new file mode 100644
index 000000000..ef3f82cf1
--- /dev/null
+++ b/docs/reference/csharp/schedule/schedule-cron.mdx
@@ -0,0 +1,54 @@
+---
+description: "Reference for Nitric's .NET library - Sets the cron expression and one or many handlers to be triggered."
+---
+
+# .NET - Schedule.Cron()
+
+Sets the cron expressions that determines when the schedule triggers and a callback to be triggered.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+Application.Schedule("send-reminder").Cron("0 1 1 * *", async (ctx) => {
+ // do some processing
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The expression that sets when the schedule will be triggered. This value
+ should be a standard 5 value Unix cron expression, e.g., '0 1 1 * *'.
+
+
+ One or more callback functions to use as the handler which will run on the
+ defined frequency.
+
+
+
+## Examples
+
+### Create a Schedule
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+// every 15 minutes
+Application.Schedule("check for updates").Cron("0/15 * * * *", async (ctx) => {
+ Console.WriteLine("checking for updates");
+});
+
+// at 1:00 am on the 1st of every month
+Application.Schedules("delete stale data").Cron("0 1 1 * *", async (ctx) => {
+ Console.WriteLine("clearing stale data");
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/schedule/schedule-every.mdx b/docs/reference/csharp/schedule/schedule-every.mdx
new file mode 100644
index 000000000..183b445c4
--- /dev/null
+++ b/docs/reference/csharp/schedule/schedule-every.mdx
@@ -0,0 +1,92 @@
+---
+description: "Reference for Nitric's .NET library - Sets the frequency and one or many handlers to be triggered."
+---
+
+# .NET - Schedule.Every()
+
+Sets the frequency and one or many handlers to be triggered.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+Application.Schedule("send-reminder").Every("3 hours", async (ctx) =>
+{
+ // do some processing
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The rate to run the schedule, e.g. '7 days'. All rates accept a number and a
+ frequency. Valid frequencies are 'days', 'hours' or 'minutes'.
+
+
+ One or more middleware functions to use as the handler which will run on
+ defined frequency.
+
+
+
+## Examples
+
+### Create a Schedule to run every 3 minutes
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+Application.Schedule("send-reminder").Every("3 minutes", async (ctx) =>
+{
+ // do some processing
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Create a Schedule with multiple middleware/handlers
+
+```csharp title:Middlewares.cs
+using System;
+using System.Threading.Tasks;
+using Nitric.Sdk.Service;
+
+namespace Common;
+
+class Middlewares
+{
+ // Create a middleware to handle report generation
+ public static async Task GenerateReport(IntervalContext ctx, Func> next)
+ {
+ Console.WriteLine("generate report");
+ // Code to generate a report
+ return await next(ctx);
+ }
+
+ // Create a middleware to handle notifications
+ public static async Task SendNotification(IntervalContext ctx, Func> next)
+ {
+ Console.WriteLine("sending notification");
+
+ // Code to send a notification
+ return await next(ctx);
+ }
+}
+```
+
+```csharp title:Application.cs
+using Application = Nitric.Sdk.Nitric;
+using Common;
+
+// Create a schedule that runs every 7 days
+Application.Schedule("send-reminder").Every("7 days", Middlewares.GenerateReport, Middlewares.SendNotification);
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/schedule/schedule.mdx b/docs/reference/csharp/schedule/schedule.mdx
new file mode 100644
index 000000000..04aa2e272
--- /dev/null
+++ b/docs/reference/csharp/schedule/schedule.mdx
@@ -0,0 +1,74 @@
+---
+description: "Reference for Nitric's .NET library - Creates a new Schedule to run a function on a defined frequency."
+---
+
+# .NET - Schedule()
+
+Creates a new Schedule to run a function on a defined frequency.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+Application.Schedule("send-reminder").Every("3 hours", async (ctx) =>
+{
+ // do some processing
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The unique name of this Schedule within the app. Subsequent calls to
+ `Schedule` with the same name will return the same object.
+
+
+
+## Examples
+
+### Create a Schedule
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+// Create a schedule that runs every 3 minutes
+Application.Schedule("send-reminder").Every("3 minutes", async (ctx) =>
+{
+ // do some processing
+ return ctx;
+});
+
+// Create a schedule that runs every 3 hours
+Application.Schedule("send-reminder").Every("3 hours", async (ctx) =>
+{
+ // do some processing
+ return ctx;
+});
+
+// Create a schedule that runs every 3 days
+Application.Schedule("send-reminder").Every("3 days", async (ctx) =>
+{
+ // do some processing
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Create a Schedule using Cron expression
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+// Create a schedule that runs every 3 minutes
+Application.Schedule("send-reminder").Cron("3 * * * *", async (ctx) =>
+{
+ // do some processing
+ return ctx;
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/secrets/secret-latest.mdx b/docs/reference/csharp/secrets/secret-latest.mdx
new file mode 100644
index 000000000..8767818b8
--- /dev/null
+++ b/docs/reference/csharp/secrets/secret-latest.mdx
@@ -0,0 +1,61 @@
+---
+description: "Reference for Nitric's .NET library - Returns a reference to the latest version of a secret, regardless of that version's ID."
+---
+
+# .NET - Secret.Latest()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Secrets in Nitric start with the [Secrets docs](/secrets).
+
+
+Returns a reference to the `latest` version of a secret, regardless of that version's ID.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("apikey").Allow(SecretPermission.Access);
+
+var latestVersion = keyRef.Latest();
+
+Application.Run();
+```
+
+## Notes
+
+`Latest()` is most useful when you always want the most recent secret values from the secrets manager. Database credentials and API keys are good examples of secrets where the latest value is usually what you want.
+
+For symmetric encryption, you'll need to retrieve the version of the secret used to _encrypt_ a value when you try to _decrypt_ it again. In those cases `Latest()` isn't a good choice, use [version()](./secret-version) instead.
+
+## Examples
+
+### Get a reference to the latest secret version
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("apikey").Allow(SecretPermission.Access);
+
+var latestVersion = keyRef.Latest();
+
+Application.Run();
+```
+
+### Access the latest value of a secret
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("apikey").Allow(SecretPermission.Access);
+
+var latestVersion = keyRef.Latest().Access();
+
+Application.Run();
+```
+
+
+ See [Secret.Version().Access()](./secret-version-access) for more details.
+
diff --git a/docs/reference/csharp/secrets/secret-put.mdx b/docs/reference/csharp/secrets/secret-put.mdx
new file mode 100644
index 000000000..dcd6cb13d
--- /dev/null
+++ b/docs/reference/csharp/secrets/secret-put.mdx
@@ -0,0 +1,67 @@
+---
+description: "Reference for Nitric's .NET library - Store a new secret value"
+---
+
+# .NET - Secret.Put()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Secrets in Nitric start with the [Secrets docs](/secrets).
+
+
+Store a new secret value, creating a new [version](./secret-version) to store the value.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("apikey").Allow(SecretPermission.Put);
+
+keyRef.Put("6c3199a3-094e-4797-bfc9-9ee2a7839286");
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The new secret value to store in the secrets manager.
+
+
+
+### Notes
+
+A new secret version is always created when calling `Put()`, the versions will automatically be provided a unique id. This behavior is dependent on the underlying secrets manager.
+
+## Examples
+
+### Store a new secret value
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("apikey").Allow(SecretPermission.Put);
+
+keyRef.Put("6c3199a3-094e-4797-bfc9-9ee2a7839286");
+
+Application.Run();
+```
+
+### Get the id of a new secret version
+
+Calling `Put()` returns a promise to a reference to the new secret version. Storing the ID of the new version can be useful if you need to retrieve that specific value again in future using [Version.Access()](./secret-version-access)
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("apikey").Allow(SecretPermission.Put);
+
+var newapikeyVersionRef = keyRef.Put("6c3199a3-094e-4797-bfc9-9ee2a7839286");
+
+var versionId = newapikeyVersionRef.Id;
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/secrets/secret-version-access.mdx b/docs/reference/csharp/secrets/secret-version-access.mdx
new file mode 100644
index 000000000..524835629
--- /dev/null
+++ b/docs/reference/csharp/secrets/secret-version-access.mdx
@@ -0,0 +1,57 @@
+---
+description: "Reference for Nitric's .NET library - Retrieves the value from a version of a secret."
+---
+
+# .NET - Secret.Version.Access()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Secrets in Nitric start with the [Secrets docs](/secrets).
+
+
+Retrieves the value from a version of a secret.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("apikey").Allow(SecretPermission.Access);
+
+var keyValue = keyRef.Latest().Access();
+
+keyValue.Value;
+
+Application.Run();
+```
+
+## Examples
+
+### Access the latest version of a secret
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("apikey").Allow(SecretPermission.Access);
+
+var keyValue = keyRef.Latest().Access();
+
+keyValue.Value;
+
+Application.Run();
+```
+
+### Access a specific version of a secret
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("apikey").Allow(SecretPermission.Access);
+
+var keyValue = keyRef.Version("the-version-id").Access();
+
+keyValue.Value;
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/secrets/secret-version.mdx b/docs/reference/csharp/secrets/secret-version.mdx
new file mode 100644
index 000000000..72926de70
--- /dev/null
+++ b/docs/reference/csharp/secrets/secret-version.mdx
@@ -0,0 +1,65 @@
+---
+description: "Reference for Nitric's .NET library - Returns a reference to a known version of a secret."
+---
+
+# .NET - Secret.Version()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Secrets in Nitric start with the [Secrets docs](/secrets).
+
+
+Returns a reference to a known version of a secret.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("encryptionKey").With(SecretPermission.Accessing);
+
+var keyVersionRef = keyRef.Version("the-version-id");
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The version ID. This value is returned from [secret.Put()](./secret-put).
+
+
+
+## Examples
+
+### Return a reference to a known secret version
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("encryptionKey").With(SecretPermission.Accessing);
+
+var keyVersionRef = keyRef.Version("the-version-id");
+
+Application.Run();
+```
+
+### Access the value of a known secret version
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("encryptionKey").With(SecretPermission.Accessing);
+
+var keyVersionRef = keyRef.Version("the-version-id").Access();
+
+var keyValue = keyVersionRef.Value;
+
+Application.Run();
+```
+
+### See also
+
+- [Secret.Version.Access()](./secret-version-access)
diff --git a/docs/reference/csharp/secrets/secret.mdx b/docs/reference/csharp/secrets/secret.mdx
new file mode 100644
index 000000000..5ab5efc43
--- /dev/null
+++ b/docs/reference/csharp/secrets/secret.mdx
@@ -0,0 +1,69 @@
+---
+description: "Reference for Nitric's .NET library - Creates a reference to a secret in the secrets manager."
+---
+
+# .NET - Secret()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Secrets in Nitric start with the [Secrets docs](/secrets).
+
+
+Creates a reference to a secret in the secrets manager.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("apikey").Allow(SecretPermission.Access);
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The unique name of this secret within the secrets manager.
+
+
+
+## Access
+
+All Nitric resources provide access permissions you can use to specify the level of access your code needs to the resource. See here for details about infrastructure [security](/get-started/foundations/infrastructure/security).
+
+### Available permissions:
+
+---
+
+**SecretPermission.Put**
+
+This permission allows your code to set a new latest value for a secret.
+
+---
+
+**SecretPermission.Access**
+
+This permission allows your code to retrieve secret values.
+
+---
+
+## Examples
+
+### Create a reference to a secret
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var keyRef = Application.Secret("apikey").Allow(SecretPermission.Access);
+
+Application.Run();
+```
+
+### See also
+
+- [Secret.Put()](./secret-put)
+- [Secret.Version()](./secret-version)
+- [Secret.Latest()](./secret-latest)
+- [Secret.Version.Access()](./secret-version-access)
diff --git a/docs/reference/csharp/sql/sql-connection-string.mdx b/docs/reference/csharp/sql/sql-connection-string.mdx
new file mode 100644
index 000000000..2375d504e
--- /dev/null
+++ b/docs/reference/csharp/sql/sql-connection-string.mdx
@@ -0,0 +1,36 @@
+---
+description: "Reference for Nitric's .NET library - Returns the connection string for a SQL database at runtime."
+---
+
+# .NET - Sql.ConnectionString()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about SQL
+ Databases in Nitric start with the [SQL docs](/sql).
+
+
+Returns the connection string for a SQL database at runtime.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var db = Application.Sql("my-database", "dockerfile://migrations.dockerfile");
+
+var connStr = db.ConnectionString();
+
+Application.Run();
+```
+
+## Examples
+
+### Return a connection string
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var db = Application.Sql("my-database", "dockerfile://migrations.dockerfile");
+
+var connStr = db.ConnectionString();
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/sql/sql.mdx b/docs/reference/csharp/sql/sql.mdx
new file mode 100644
index 000000000..d1185c209
--- /dev/null
+++ b/docs/reference/csharp/sql/sql.mdx
@@ -0,0 +1,68 @@
+---
+description: "Reference for Nitric's .NET library - Creates a reference to a SQL database."
+---
+
+# .NET - Sql()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about SQL
+ Databases in Nitric start with the [SQL docs](/sql).
+
+
+Creates a reference to a SQL database.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var db = Application.Sql("my-database");
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The unique name of this database within the project.
+
+
+ Points to the location of migration files, prefixed with `file://`, or a
+ migration dockerfile, prefixed with `dockerfile://`.
+
+
+
+## Examples
+
+### Create a reference to a database
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var db = Application.Sql("my-database");
+
+Application.Run();
+```
+
+### With a migrations directory
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var db = Application.Sql("my-database", "file://migrations/my-database");
+
+Application.Run();
+```
+
+### With a migrations dockerfile
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var db = Application.Sql("my-database", "dockerfile://migrations.dockerfile");
+
+Application.Run();
+```
+
+### See also
+
+- [Sql.ConnectionString()](./sql-connection-string)
diff --git a/docs/reference/csharp/storage/bucket-file-delete.mdx b/docs/reference/csharp/storage/bucket-file-delete.mdx
new file mode 100644
index 000000000..1d75cf4e6
--- /dev/null
+++ b/docs/reference/csharp/storage/bucket-file-delete.mdx
@@ -0,0 +1,42 @@
+---
+description: "Reference for Nitric's .NET library - Delete a file from a bucket."
+---
+
+# .NET - Bucket.File.Delete()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Buckets and Storage in Nitric start with the [Storage docs](/storage).
+
+
+Delete a file from a bucket.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Delete);
+
+var logo = assets.File("images/logo.png");
+
+logo.Delete();
+
+Application.Run();
+```
+
+## Examples
+
+### Delete a file
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Delete);
+
+var logo = assets.File("images/logo.png");
+
+logo.Delete();
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/storage/bucket-file-downloadurl.mdx b/docs/reference/csharp/storage/bucket-file-downloadurl.mdx
new file mode 100644
index 000000000..3e4fa68b9
--- /dev/null
+++ b/docs/reference/csharp/storage/bucket-file-downloadurl.mdx
@@ -0,0 +1,74 @@
+---
+description: "Reference for Nitric's .NET library - Get a download url for a file from a bucket."
+---
+
+# .NET - Bucket.File.GetDownloadUrl()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Buckets and Storage in Nitric start with the [Storage docs](/storage).
+
+
+Create a download url for a file within a bucket.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Read);
+
+var logo = assets.File("images/logo.png");
+
+// Create a read-only signed url reference for downloading
+var downloadUrl = logo.GetDownloadUrl();
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ Seconds until link expiry. Defaults to `600`, Maximum of `604800` (7 days).
+
+
+
+## Examples
+
+### Create a readable link that is valid for the next 5 minutes
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Read);
+
+var logo = assets.File("images/logo.png");
+
+// Create a read-only signed url reference for downloading
+var downloadUrl = logo.GetDownloadUrl();
+
+Application.Run();
+```
+
+### Redirect response to an image url
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var images = Application.Bucket("images").Allow(BucketPermission.Read);
+var mainApi = Application.Api("main");
+
+mainApi.Get("/images/:id", context => {
+ var id = context.Req.PathParams["id"];
+ var signedUrl = images.File(id).GetDownloadUrl();
+
+ context.Res.Status = 303;
+ context.Res.Headers["Location"] = new string[] { signedUrl };
+
+ return context;
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/storage/bucket-file-read.mdx b/docs/reference/csharp/storage/bucket-file-read.mdx
new file mode 100644
index 000000000..98b036e61
--- /dev/null
+++ b/docs/reference/csharp/storage/bucket-file-read.mdx
@@ -0,0 +1,42 @@
+---
+description: "Reference for Nitric's .NET library - Read the contents of a file from a bucket."
+---
+
+# .NET - Bucket.File.Read()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Buckets and Storage in Nitric start with the [Storage docs](/storage).
+
+
+Read the contents of a file from a bucket.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Read);
+
+var logo = assets.File("images/logo.png");
+
+var logoData = logo.Read();
+
+Application.Run();
+```
+
+## Examples
+
+### Read a file
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Read);
+
+var logo = assets.File("images/logo.png");
+
+var logoData = logo.Read();
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/storage/bucket-file-uploadurl.mdx b/docs/reference/csharp/storage/bucket-file-uploadurl.mdx
new file mode 100644
index 000000000..8487603e7
--- /dev/null
+++ b/docs/reference/csharp/storage/bucket-file-uploadurl.mdx
@@ -0,0 +1,52 @@
+---
+description: "Reference for Nitric's .NET library - Get a upload url for a file from a bucket."
+---
+
+# .NET - Bucket.File.GeUploadUrl()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Buckets and Storage in Nitric start with the [Storage docs](/storage).
+
+
+Create a upload url for a file within a bucket.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Write);
+
+var logo = assets.File("images/logo.png");
+
+// Create a read-only signed url reference for uploading
+var uploadUrl = logo.GetUploadUrl();
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ Seconds until link expiry. Defaults to `600`, Maximum of `604800` (7 days).
+
+
+
+## Examples
+
+### Create a temporary file upload link for a user
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Write);
+
+var logo = assets.File("images/logo.png");
+
+// Create a read-only signed url reference for uploading
+var uploadUrl = logo.GetUploadUrl();
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/storage/bucket-file-write.mdx b/docs/reference/csharp/storage/bucket-file-write.mdx
new file mode 100644
index 000000000..4f8ba68bc
--- /dev/null
+++ b/docs/reference/csharp/storage/bucket-file-write.mdx
@@ -0,0 +1,50 @@
+---
+description: "Reference for Nitric's .NET library - Write a file to a bucket."
+---
+
+# .NET - Bucket.File.Write()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Buckets and Storage in Nitric start with the [Storage docs](/storage).
+
+
+Write a file to a bucket.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Read);
+
+var logo = assets.File("images/logo.png");
+
+logo.Write(someImageData);
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The data to write to the file.
+
+
+
+## Examples
+
+### Write a file
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Read);
+
+var logo = assets.File("images/logo.png");
+
+logo.Write(someImageData);
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/storage/bucket-file.mdx b/docs/reference/csharp/storage/bucket-file.mdx
new file mode 100644
index 000000000..daa6c230a
--- /dev/null
+++ b/docs/reference/csharp/storage/bucket-file.mdx
@@ -0,0 +1,43 @@
+---
+description: "Reference for Nitric's .NET library - Create a reference to a file within a bucket."
+---
+
+# .NET - Bucket.File()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Buckets and Storage in Nitric start with the [Storage docs](/storage).
+
+
+Create a reference to a file within a bucket.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Read);
+
+var logo = assets.File("images/logo.png");
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The unique name/reference to the file.
+
+
+
+## Notes
+
+The file does not need to exist, only a reference to that file is being created.
+
+## Available Operations
+
+- [File.Read()](./bucket-file-read)
+- [File.Write()](./bucket-file-write)
+- [File.Delete()](./bucket-file-delete)
+- [File.GetDownloadUrl()](./bucket-file-downloadurl)
+- [File.GetUploadUrl()](./bucket-file-uploadurl)
diff --git a/docs/reference/csharp/storage/bucket-files.mdx b/docs/reference/csharp/storage/bucket-files.mdx
new file mode 100644
index 000000000..fc9c8d0ce
--- /dev/null
+++ b/docs/reference/csharp/storage/bucket-files.mdx
@@ -0,0 +1,44 @@
+---
+description: "Reference for Nitric's .NET library - Get a list of file references for files that exist in the bucket."
+---
+
+# .NET - Bucket.Files()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Buckets and Storage in Nitric start with the [Storage docs](/storage).
+
+
+Get a list of file references for files that exist in the bucket.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Read);
+
+var files = assets.Files();
+
+Application.Run();
+```
+
+## Examples
+
+Deleting all files in a bucket
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Read);
+
+var files = assets.Files();
+
+files.ForEach(file => file.Delete());
+
+Application.Run();
+```
+
+## Notes
+
+This method returns a list of [File](./bucket-file) references that exist on the bucket.
diff --git a/docs/reference/csharp/storage/bucket-on.mdx b/docs/reference/csharp/storage/bucket-on.mdx
new file mode 100644
index 000000000..66c3b7399
--- /dev/null
+++ b/docs/reference/csharp/storage/bucket-on.mdx
@@ -0,0 +1,92 @@
+---
+description: "Reference for Nitric's .NET library - Create a new bucket notification trigger"
+---
+
+# .NET - Bucket.On()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Buckets and Storage in Nitric start with the [Storage docs](/storage).
+
+
+Create a new bucket notification trigger when certain files are created or deleted.
+
+```csharp
+using System;
+using Nitric.Sdk.Resource;
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets");
+
+var accessibleAssets = Application.Bucket("assets").Allow(BucketPermission.Read);
+
+// The request will contain the name of the file `Key` and the type of event `NotificationType`
+assets.On(BlobEventType.Delete, "*", async (ctx) => {
+ Console.WriteLine("A file named " + ctx.Req.Key + "was deleted");
+
+ return ctx;
+});
+
+assets.On(BlobEventType.Write, "/images/cat", async (ctx) => {
+ Console.WriteLine("A cat image was written");
+
+ return ctx;
+});
+
+// If `.On()` is called with a permissioned bucket, a file reference will also be provided with the request
+accessibleAssets.On(BlobEventType.Write, "/images/dog", async (ctx) => {
+ var dogImage = accessibleAssets.File(ctx.Req.Key).Read();
+
+ Console.WriteLine(dogImage.ToString());
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The unique name/reference to the file.
+
+
+ The notification type for a triggered event, either on a file write or a
+ file delete.
+
+
+ The file prefix filter that must match for a triggered event. If multiple
+ filters overlap across notifications then an error will be thrown when
+ registering the resource.
+
+
+ The middleware (code) to be triggered when a bucket event is triggered.
+
+
+
+## Available Trigger Types
+
+`BlobEventType.Write`
+
+Triggered when a file in the bucket is created using: `file.Write()`
+
+`BlobEventType.Delete`
+
+Triggered when a file in the bucket is deleted using: `file.Delete()`
+
+## Cloud Trigger Types
+
+| Permission | AWS | GCP | Azure |
+| ----------------------------- | ------------------- | --------------- | ----------------------------- |
+| BucketNotificationType.Write | s3:ObjectCreated:\* | OBJECT_FINALIZE | Microsoft.Storage.BlobCreated |
+| BucketNotificationType.Delete | s3:ObjectRemoved:\* | OBJECT_DELETE | Microsoft.Storage.BlobDeleted |
diff --git a/docs/reference/csharp/storage/bucket.mdx b/docs/reference/csharp/storage/bucket.mdx
new file mode 100644
index 000000000..9e7bf77d1
--- /dev/null
+++ b/docs/reference/csharp/storage/bucket.mdx
@@ -0,0 +1,67 @@
+---
+description: "Reference for Nitric's .NET library - Create a new bucket for storing and retrieving files."
+---
+
+# .NET - Bucket()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Buckets and Storage in Nitric start with the [Storage docs](/storage).
+
+
+Create a new bucket for storing and retrieving files.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+var assets = Application.Bucket("assets").Allow(BucketPermission.Read, BucketPermission.Write, BucketPermission.Delete);
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The unique name of this bucket within the app. Subsequent calls to `Bucket`
+ with the same name will return the same object.
+
+
+
+## Access
+
+All Nitric resources provide access permissions you can use to specify the level of access your code needs to the resource. See here for details about infrastructure [security](/get-started/foundations/infrastructure/security).
+
+### Available permissions:
+
+---
+
+**BucketPermission.Read**
+
+This permission allows your function to read files from the bucket
+
+---
+
+**BucketPermission.Write**
+
+This permission allows your function to write files to the bucket
+
+---
+
+**BucketPermission.Delete**
+
+This permission allows your function to delete files from the bucket
+
+---
+
+## Working with files
+
+See the following for examples on working with files in a bucket:
+
+- [File()](./bucket-file)
+- [File().Read()](./bucket-file-read)
+- [File().Write()](./bucket-file-write)
+- [File().Delete()](./bucket-file-delete)
+- [File.GetDownloadUrl()](./bucket-file-downloadurl)
+- [File.GetUploadUrl()](./bucket-file-uploadurl)
diff --git a/docs/reference/csharp/topic/topic-publish.mdx b/docs/reference/csharp/topic/topic-publish.mdx
new file mode 100644
index 000000000..fa7e8fb3f
--- /dev/null
+++ b/docs/reference/csharp/topic/topic-publish.mdx
@@ -0,0 +1,61 @@
+---
+description: "Reference for Nitric's .NET library - Publish new events to the topic."
+---
+
+# .NET - Topic.Publish()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about Topics
+ and Pub/Sub in Nitric start with the [Async Messaging
+ docs](/messaging#topics).
+
+
+Publish an event (push based message) to a topic.
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class EventUpdate
+{
+ public string Message { get; set; }
+}
+
+var updates = Application.Topic("updates").Allow(TopicPermission.Publish);
+
+updates.Publish(new EventUpdate { Message = "payload sent" });
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The event to publish to the topic
+
+
+
+## Examples
+
+### Publish a topic
+
+```csharp
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class EventUpdate
+{
+ public string Message { get; set; }
+}
+
+var updates = Application.Topic("updates").Allow(TopicPermission.Publish);
+
+updates.Publish(new EventUpdate { Message = "payload sent" });
+
+Application.Run();
+```
+
+## Notes
+
+- A function may subscribe to OR publish to a topic but not both.
diff --git a/docs/reference/csharp/topic/topic-subscribe.mdx b/docs/reference/csharp/topic/topic-subscribe.mdx
new file mode 100644
index 000000000..c5c3498f0
--- /dev/null
+++ b/docs/reference/csharp/topic/topic-subscribe.mdx
@@ -0,0 +1,104 @@
+---
+description: "Reference for Nitric's .NET library - Subscribe a handler to a topic and receive new events for processing."
+---
+
+# .NET - Topic.Subscribe()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about Topics
+ and Pub/Sub in Nitric start with the [Async Messaging
+ docs](/messaging#topics).
+
+
+Subscribe a handler to a topic and receive new events for processing.
+
+```csharp
+using System;
+using Application = Nitric.Sdk.Nitric;
+
+class EventUpdate
+{
+ public string Message { get; set; }
+}
+
+var updates = Application.Topic("updates");
+
+updates.Subscribe(async (ctx) => {
+ Console.WriteLine(ctx.Req.Message);
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The middleware (code) to be triggered by the topic.
+
+
+
+## Examples
+
+### Subscribe to a topic
+
+```csharp
+using System;
+using Application = Nitric.Sdk.Nitric;
+
+class EventUpdate
+{
+ public string Message { get; set; }
+}
+
+var updates = Application.Topic("updates");
+
+updates.Subscribe(async (ctx) => {
+ Console.WriteLine(ctx.Req.Message);
+
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Subscibe to a topic with chained middleware
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+class EventUpdate
+{
+ public string Message { get; set; }
+}
+
+var updates = Application.Topic("updates");
+
+
+updates.Subscribe(async (ctx, next) =>
+ {
+ // Validate request
+ if (invalidRequest(ctx))
+ {
+ return ctx;
+ }
+ return next(ctx);
+ }, async (ctx, next) => {
+ // Handle request
+ return next(ctx);
+ }
+);
+
+Application.Run();
+```
+
+## Notes
+
+- A function may only subscribe to a topic once, if multiple subscribers are required, create them in different functions.
+- A function may subscribe to OR publish to a topic but not both
diff --git a/docs/reference/csharp/topic/topic.mdx b/docs/reference/csharp/topic/topic.mdx
new file mode 100644
index 000000000..f6c92b71c
--- /dev/null
+++ b/docs/reference/csharp/topic/topic.mdx
@@ -0,0 +1,56 @@
+---
+description: "Reference for Nitric's .NET library - Creates a new Topic."
+---
+
+# .NET - Topic()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about Topics
+ and Pub/Sub in Nitric start with the [Async Messaging
+ docs](/messaging#topics).
+
+
+Creates a new Topic.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+class EventUpdate
+{
+ public string Message { get; set; }
+}
+
+var updates = Application.Topic("updates");
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The name of the topic to create.
+
+
+
+## Examples
+
+### Create a new topic
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+class EventUpdate
+{
+ public string Message { get; set; }
+}
+
+var updates = Application.Topic("updates");
+
+Application.Run();
+```
+
+## See also
+
+- [Topic.Subscribe()](./topic-subscribe)
+- [Topic.Publish()](./topic-publish)
diff --git a/docs/reference/csharp/websocket/connection-close.mdx b/docs/reference/csharp/websocket/connection-close.mdx
new file mode 100644
index 000000000..a24d9fab0
--- /dev/null
+++ b/docs/reference/csharp/websocket/connection-close.mdx
@@ -0,0 +1,52 @@
+---
+description: "Reference for Nitric's .NET library - Close a connection to a websocket"
+---
+
+# .NET - Connection.CloseConnection()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Websockets in Nitric start with the [Websockets docs](/websockets).
+
+
+Closes a connection to a websocket
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var websocket = Application.Websocket("public");
+
+websocket.Connection("D28BA458-BFF4-404A").CloseConnection();
+
+Application.Run();
+```
+
+## Examples
+
+### Close a connection to the websocket on message
+
+```csharp
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+class WebsocketMessage
+{
+ public string Status { get; set; }
+}
+
+var websocket = Application.Websocket("public");
+
+// Broadcast message to all the registered websocket connections
+websocket.On(WebsocketEventType.Message, async (ctx) => {
+ var message = ctx.Req.Message();
+
+ if (message.Status == "close")
+ {
+ websocket.Connection(ctx.Req.ConnectionId).CloseConnection();
+ }
+
+ return ctx;
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/websocket/connection-send.mdx b/docs/reference/csharp/websocket/connection-send.mdx
new file mode 100644
index 000000000..c9f38f69f
--- /dev/null
+++ b/docs/reference/csharp/websocket/connection-send.mdx
@@ -0,0 +1,83 @@
+---
+description: "Reference for Nitric's .NET library - Send a message to the websocket"
+---
+
+# .NET - Websocket.SendMessage()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Websockets in Nitric start with the [Websockets docs](/websockets).
+
+
+Send a message from the websocket to a connection.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var websocket = Application.Websocket("public");
+
+websocket.Connection("D28BA458-BFF4-404A").SendMessage("Hello World");
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The message that should be sent to the connection.
+
+
+
+## Examples
+
+### Broadcasting a message to all connections.
+
+
+ Do not send messages to a connection during it's `connect` callback, if you
+ need to acknowledge connection, do so by using a [topic](../topic/topic)
+
+
+```csharp
+using Nitric.Sdk.Service;
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class OpenConnection
+{
+ public string Id { get; set; }
+}
+
+var websocket = Application.Websocket("public");
+
+var connections = Application.KV("connections").Allow(
+ KeyValueStorePermission.Set, KeyValueStorePermission.Get, KeyValueStorePermission.Delete
+);
+
+websocket.On(WebsocketEventType.Connected, async (ctx) =>
+{
+ connections.Set(ctx.Req.ConnectionId, new OpenConnection { Id = ctx.Req.ConnectionId });
+ return ctx;
+});
+
+websocket.On(WebsocketEventType.Disconnected, async (ctx) =>
+{
+ connections.Delete(ctx.Req.ConnectionId);
+ return ctx;
+});
+
+websocket.On(WebsocketEventType.Message, async (ctx) =>
+{
+ var keys = connections.Keys();
+
+ while (keys.MoveNext())
+ {
+ var message = ctx.Req.Message();
+ websocket.Connection(keys.Current).SendMessage(message);
+ }
+
+ return ctx;
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/websocket/websocket-connection.mdx b/docs/reference/csharp/websocket/websocket-connection.mdx
new file mode 100644
index 000000000..6f79b4c6b
--- /dev/null
+++ b/docs/reference/csharp/websocket/websocket-connection.mdx
@@ -0,0 +1,35 @@
+---
+description: "Reference for Nitric's .NET library - Get a reference to a websocket connection"
+---
+
+# .NET - Websocket.Connection()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Websockets in Nitric start with the [Websockets docs](/websockets).
+
+
+Get a reference to a websocket connection
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var websocket = Application.Websocket("public");
+
+websocket.Connection("D28BA458-BFF4-404A");
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The ID of the connection.
+
+
+
+### See also
+
+- [Connection().Send()](./connection-send)
+- [Connection().Close()](./connection-close)
diff --git a/docs/reference/csharp/websocket/websocket-on.mdx b/docs/reference/csharp/websocket/websocket-on.mdx
new file mode 100644
index 000000000..f3785d622
--- /dev/null
+++ b/docs/reference/csharp/websocket/websocket-on.mdx
@@ -0,0 +1,140 @@
+---
+description: "Reference for Nitric's .NET library - Register a handler for connections, disconnections, or messages for the websocket."
+---
+
+# .NET - Websocket.On()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Websockets in Nitric start with the [Websockets docs](/websockets).
+
+
+Register a handler for connections, disconnections, or messages for the websocket.
+
+```csharp
+using Nitric.Sdk.Service;
+using Application = Nitric.Sdk.Nitric;
+
+var websocket = Application.Websocket("public");
+
+websocket.On(WebsocketEventType.Connected, ctx => {
+ // handle connections
+ return ctx;
+});
+
+websocket.On(WebsocketEventType.Disconnected, ctx => {
+ // handle disconnections
+ return ctx;
+});
+
+websocket.On(WebsocketEventType.Message, ctx => {
+ // handle message
+ return ctx;
+});
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The type of websocket event to listen for. Can be `Connected`,
+ `Disconnected`, or `Message`.
+
+
+ The middleware function to use as the handler for Websocket events.
+
+
+
+## Examples
+
+### Register a handler for message events
+
+Messages can be read as literal strings using `ctx.Req.Message()`.
+
+```csharp
+websocket.On(WebsocketEventType.Message, async (ctx) => {
+ var message = ctx.Req.Message();
+
+ Console.WriteLine($"New Message from {ctx.Req.ConnectionId}: {message}");
+
+ return ctx;
+});
+```
+
+Or they can be serialized to a class type using `ctx.Req.Message()`.
+
+```csharp
+class EventUpdate
+{
+ public float Status { get; set; }
+ public string Content { get; set; }
+}
+
+websocket.On(WebsocketEventType.Message, async (ctx) => {
+ var message = ctx.Req.Message();
+
+ Console.WriteLine($"Status: {message.Status}, Message: {message.Content}")
+
+ return ctx;
+});
+```
+
+### Manage Websocket connections
+
+To store Websocket connections you can use a Nitric collection.
+
+```csharp
+using Nitric.Sdk.Service;
+using Nitric.Sdk.Resource;
+using Application = Nitric.Sdk.Nitric;
+
+class OpenConnection
+{
+ public string Id { get; set; }
+}
+
+var websocket = Application.Websocket("public");
+
+var connections = Application.KV("connections").Allow(
+ KeyValueStorePermission.Set, KeyValueStorePermission.Get, KeyValueStorePermission.Delete
+);
+
+websocket.On(WebsocketEventType.Connected, async (ctx) =>
+{
+ connections.Set(ctx.Req.ConnectionId, new OpenConnection { Id = ctx.Req.ConnectionId });
+ return ctx;
+});
+
+websocket.On(WebsocketEventType.Disconnected, async (ctx) =>
+{
+ connections.Delete(ctx.Req.ConnectionId);
+ return ctx;
+});
+
+Application.Run();
+```
+
+### Chain functions as a single method handler
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+using Nitric.Sdk.Service;
+
+var websocket = Application.Websocket("public");
+
+websocket.On(WebsocketEventType.Message, async (ctx, next) =>
+{
+ // Validate Request
+ Console.WriteLine("Validate Request");
+ return await next(ctx);
+}, async (ctx, next) =>
+{
+ // Handle Request
+ Console.WriteLine("Handle Request");
+ return await next(ctx);
+});
+
+Application.Run();
+```
diff --git a/docs/reference/csharp/websocket/websocket.mdx b/docs/reference/csharp/websocket/websocket.mdx
new file mode 100644
index 000000000..6de31e739
--- /dev/null
+++ b/docs/reference/csharp/websocket/websocket.mdx
@@ -0,0 +1,48 @@
+---
+description: "Reference for Nitric's .NET library - Create Websockets with the Nitric Go SDK"
+---
+
+# .NET - Websocket()
+
+
+ This is reference documentation for the Nitric .NET SDK. To learn about
+ Websockets in Nitric start with the [Websockets docs](/websockets).
+
+
+Creates a new Websocket.
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var websocket = Application.Websocket("public");
+
+Application.Run();
+```
+
+## Parameters
+
+
+
+ The unique name of this Websocket within the app. Subsequent calls to
+ `Websocket` with the same name will return the same object.
+
+
+
+## Examples
+
+### Create a Websocket
+
+```csharp
+using Application = Nitric.Sdk.Nitric;
+
+var websocket = Application.Websocket("public");
+
+Application.Run();
+```
+
+### See also
+
+- [Websocket().On()](./websocket-on)
+- [Websocket().Connection()](./websocket-connection)
+- [Websocket().Connection().Send()](./connection-send)
+- [Websocket().Connection().Close()](./connection-close)
diff --git a/src/config/index.ts b/src/config/index.ts
index 2d3cfebb3..4f8d126ba 100644
--- a/src/config/index.ts
+++ b/src/config/index.ts
@@ -20,6 +20,7 @@ import { PyReference } from './reference/python'
import { DartReference } from './reference/dart'
import { GoReference } from './reference/go'
import { FaSitemap } from 'react-icons/fa'
+import { CSharpReference } from './reference/csharp'
export const navigation: NavEntry[] = [
{
@@ -446,6 +447,7 @@ export const navigation: NavEntry[] = [
PyReference,
GoReference,
DartReference,
+ CSharpReference,
],
},
{
diff --git a/src/config/reference/csharp.ts b/src/config/reference/csharp.ts
new file mode 100644
index 000000000..0568fc57a
--- /dev/null
+++ b/src/config/reference/csharp.ts
@@ -0,0 +1,198 @@
+import { FaMicrosoft } from 'react-icons/fa6'
+import { NavGroup } from '../types'
+
+export const CSharpReference: NavGroup = {
+ title: 'CSharp',
+ icon: FaMicrosoft,
+ items: [
+ { title: 'Overview', href: '/reference/csharp', breadcrumbRoot: true },
+ {
+ title: 'APIs',
+ items: [
+ { title: 'api()', href: '/reference/csharp/api/api' },
+ { title: 'api.get()', href: '/reference/csharp/api/api-get' },
+ { title: 'api.post()', href: '/reference/csharp/api/api-post' },
+ { title: 'api.put()', href: '/reference/csharp/api/api-put' },
+ { title: 'api.delete()', href: '/reference/csharp/api/api-delete' },
+ { title: 'api.patch()', href: '/reference/csharp/api/api-patch' },
+ { title: 'api.route()', href: '/reference/csharp/api/api-route' },
+ {
+ title: 'api.route.all()',
+ href: '/reference/csharp/api/api-route-all',
+ },
+ {
+ title: 'api.route.get()',
+ href: '/reference/csharp/api/api-route-get',
+ },
+ {
+ title: 'api.route.post()',
+ href: '/reference/csharp/api/api-route-post',
+ },
+ {
+ title: 'api.route.put()',
+ href: '/reference/csharp/api/api-route-put',
+ },
+ {
+ title: 'api.route.delete()',
+ href: '/reference/csharp/api/api-route-delete',
+ },
+ {
+ title: 'api.route.patch()',
+ href: '/reference/csharp/api/api-route-patch',
+ },
+ ],
+ },
+ {
+ title: 'Batch',
+ items: [
+ { title: 'job()', href: '/reference/csharp/batch/job' },
+ { title: 'job.handler()', href: '/reference/csharp/batch/job-handler' },
+ { title: 'job.submit()', href: '/reference/csharp/batch/job-submit' },
+ ],
+ },
+ {
+ title: 'Key Value Stores',
+ items: [
+ { title: 'kv()', href: '/reference/csharp/keyvalue/keyvalue' },
+ { title: 'kv.get()', href: '/reference/csharp/keyvalue/keyvalue-get' },
+ { title: 'kv.set()', href: '/reference/csharp/keyvalue/keyvalue-set' },
+ {
+ title: 'kv.delete()',
+ href: '/reference/csharp/keyvalue/keyvalue-delete',
+ },
+ {
+ title: 'kv.keys()',
+ href: '/reference/csharp/keyvalue/keyvalue-keys',
+ },
+ ],
+ },
+ {
+ title: 'Topics',
+ items: [
+ { title: 'topic()', href: '/reference/csharp/topic/topic' },
+ {
+ title: 'topic.publish()',
+ href: '/reference/csharp/topic/topic-publish',
+ },
+ {
+ title: 'topic.subscribe()',
+ href: '/reference/csharp/topic/topic-subscribe',
+ },
+ ],
+ },
+ {
+ title: 'Queues',
+ items: [
+ { title: 'queue()', href: '/reference/csharp/queues/queue' },
+ {
+ title: 'queue.enqueue()',
+ href: '/reference/csharp/queues/queue-enqueue',
+ },
+ {
+ title: 'queue.dequeue()',
+ href: '/reference/csharp/queues/queue-dequeue',
+ },
+ ],
+ },
+ {
+ title: 'Secrets',
+ items: [
+ { title: 'secret()', href: '/reference/csharp/secrets/secret' },
+ { title: 'secret.put()', href: '/reference/csharp/secrets/secret-put' },
+ {
+ title: 'secret.version()',
+ href: '/reference/csharp/secrets/secret-version',
+ },
+ {
+ title: 'secret.latest()',
+ href: '/reference/csharp/secrets/secret-latest',
+ },
+ {
+ title: 'secret.version.access()',
+ href: '/reference/csharp/secrets/secret-version-access',
+ },
+ ],
+ },
+ {
+ title: 'Storage',
+ items: [
+ { title: 'bucket()', href: '/reference/csharp/storage/bucket' },
+ { title: 'bucket.on()', href: '/reference/csharp/storage/bucket-on' },
+ {
+ title: 'bucket.file()',
+ href: '/reference/csharp/storage/bucket-file',
+ },
+ {
+ title: 'bucket.files()',
+ href: '/reference/csharp/storage/bucket-files',
+ },
+ {
+ title: 'file.read()',
+ href: '/reference/csharp/storage/bucket-file-read',
+ },
+ {
+ title: 'file.write()',
+ href: '/reference/csharp/storage/bucket-file-write',
+ },
+ {
+ title: 'file.delete()',
+ href: '/reference/csharp/storage/bucket-file-delete',
+ },
+ {
+ title: 'file.getDownloadUrl()',
+ href: '/reference/csharp/storage/bucket-file-downloadurl',
+ },
+ {
+ title: 'file.getUploadUrl()',
+ href: '/reference/csharp/storage/bucket-file-uploadurl',
+ },
+ ],
+ },
+ {
+ title: 'SQL',
+ items: [
+ { title: 'sql()', href: '/reference/csharp/sql/sql' },
+ {
+ title: 'sql.connectionString()',
+ href: '/reference/csharp/sql/sql-connection-string',
+ },
+ ],
+ },
+ {
+ title: 'Schedules',
+ items: [
+ { title: 'schedule()', href: '/reference/csharp/schedule/schedule' },
+ {
+ title: 'schedule.every()',
+ href: '/reference/csharp/schedule/schedule-every',
+ },
+ {
+ title: 'schedule.cron()',
+ href: '/reference/csharp/schedule/schedule-cron',
+ },
+ ],
+ },
+ {
+ title: 'Websockets',
+ items: [
+ { title: 'websocket()', href: '/reference/csharp/websocket/websocket' },
+ {
+ title: 'websocket.on()',
+ href: '/reference/csharp/websocket/websocket-on',
+ },
+ {
+ title: 'websocket.connection()',
+ href: '/reference/csharp/websocket/websocket-connection',
+ },
+ {
+ title: 'connection.send()',
+ href: '/reference/csharp/websocket/connection-send',
+ },
+ {
+ title: 'connection.close()',
+ href: '/reference/csharp/websocket/connection-close',
+ },
+ ],
+ },
+ ],
+}