{"id":28414665,"url":"https://github.com/fauna/dotnet-sample-app","last_synced_at":"2026-02-15T23:02:37.422Z","repository":{"id":264057362,"uuid":"858917837","full_name":"fauna/dotnet-sample-app","owner":"fauna","description":"Learn Fauna database fundamentals with Fauna Query Language (FQL) v10 and the .NET driver.","archived":false,"fork":false,"pushed_at":"2025-01-28T14:58:57.000Z","size":77,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-06-03T19:17:39.935Z","etag":null,"topics":["samples"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fauna.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-17T18:56:01.000Z","updated_at":"2025-01-28T14:58:58.000Z","dependencies_parsed_at":"2024-11-21T19:27:38.053Z","dependency_job_id":"a8c35c3e-42ac-4e41-b1c2-78629f3676d6","html_url":"https://github.com/fauna/dotnet-sample-app","commit_stats":null,"previous_names":["fauna/dotnet-sample-app"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fauna/dotnet-sample-app","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fauna%2Fdotnet-sample-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fauna%2Fdotnet-sample-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fauna%2Fdotnet-sample-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fauna%2Fdotnet-sample-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fauna","download_url":"https://codeload.github.com/fauna/dotnet-sample-app/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fauna%2Fdotnet-sample-app/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261818820,"owners_count":23214371,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["samples"],"created_at":"2025-06-03T09:18:57.153Z","updated_at":"2026-02-15T23:02:32.400Z","avatar_url":"https://github.com/fauna.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fauna .NET sample app\n\n## Overview\n\nThis sample app shows how to use [Fauna](https://fauna.com) in a production application.\n\nThe app uses .NET and the [Fauna v10 .NET\ndriver](https://github.com/fauna/fauna-dotnet) to create HTTP API endpoints for an\ne-commerce store. You can use the app's API endpoints to manage products,\ncustomers, and orders for the store.\n\nThe app uses Fauna schemas and queries to:\n\n- Read and write data with strong consistency.\n\n- Define and handle relationships between resources, such as linking orders\n  to products and customers.\n\n- Validate data changes against business logic.\n\nThe app's source code includes comments that highlight Fauna best practices.\n\n\n## Highlights\n\nThe sample app uses the following Fauna features:\n\n- **[Document type\n  enforcement](https://docs.fauna.com/fauna/current/learn/schema/#type-enforcement):**\n  Collection schemas enforce a structure for the app's documents. Fauna rejects\n  document writes that don't conform to the schema, ensuring data consistency.\n  [Zero-downtime\n  migrations](https://docs.fauna.com/fauna/current/learn/schema/#schema-migrations)\n  let you safely change the schemas at any time.\n\n- **[Relationships](https://docs.fauna.com/fauna/current/learn/query/relationships/):**\n  Normalized references link documents across collections. The app's queries use\n  [projection](https://docs.fauna.com/fauna/current/reference/fql/projection/)\n  to dynamically retrieve linked documents, even when deeply nested. No complex\n  joins, aggregations, or duplication needed.\n\n- **[Computed\n  fields](https://docs.fauna.com/fauna/current/learn/schema/#computed-fields):**\n  Computed fields dynamically calculate their values at query time. For example,\n  each customer's `orders` field uses a query to fetch a set of filtered orders.\n  Similarly, each order's `total` is calculated at query time based on linked\n  product prices and quantity.\n\n- **[Constraints](https://docs.fauna.com/fauna/current/learn/schema/#unique-constraints):**\n  The app uses constraints to ensure field values are valid. For example, the\n  app uses unique constraints to ensure each customer has a unique email address\n  and each product has a unique name. Similarly, check constraints ensure each\n  customer has only one cart at a time and that product prices are not negative.\n\n- **[User-defined functions\n  (UDFs)](https://docs.fauna.com/fauna/current/learn/data-model/user-defined-functions/):**\n  The app uses UDFs to store business logic as reusable queries. For example,\n  the app uses a `checkout()` UDF to process order updates. `checkout()` calls\n  another UDF, `validateOrderStatusTransition()`, to validate `status`\n  transitions for orders.\n\n\n## Requirements\n\nTo run the app, you'll need:\n\n- A [Fauna account](https://dashboard.fauna.com/register). You can sign up for a\n  free account at https://dashboard.fauna.com/register.\n\n- .NET 8.0 or later.\n\n- [Fauna CLI v4 beta](https://docs.fauna.com/fauna/current/build/cli/v4/) or later.\n    - [Node.js](https://nodejs.org/en/download/) v20.18 or later.\n      - [Node.js](https://nodejs.org/en/download/) v22 or later recommended.\n\n  To install the CLI, run:\n\n    ```sh\n    npm install -g fauna-shell\n    ```\n\n## Setup\n\n1. Clone the repo and navigate to the `dotnet-sample-app` directory:\n\n    ```sh\n    git clone git@github.com:fauna/dotnet-sample-app.git\n    cd dotnet-sample-app\n    ```\n\n2. If you haven't already, log in to Fauna using the Fauna CLI:\n\n    ```sh\n    fauna login\n    ```\n\n3. Use the Fauna CLI to create the `EcommerceDotnet` database:\n\n    ```sh\n    # Replace 'us' with your preferred region group:\n    # 'us' (United States), 'eu' (Europe), or `global` (available to Pro accounts and above).\n    fauna database create \\\n      --name EcommerceDotnet \\\n      --database us\n    ```\n\n4.  Push the `.fsl` files in the `schema` directory to the `EcommerceDotnet`\n    database:\n\n    ```sh\n    # Replace 'us' with your region group identifier.\n    fauna schema push \\\n      --database us/EcommerceDotnet\n    ```\n\n    When prompted, accept and stage the schema.\n\n5.  Check the status of the staged schema:\n\n    ```sh\n    fauna schema status \\\n      --database us/EcommerceDotnet\n    ```\n\n6.  When the status is `ready`, commit the staged schema to the database:\n\n    ```sh\n    fauna schema commit \\\n      --database us/EcommerceDotnet\n    ```\n\n    The commit applies the staged schema to the database. The commit creates the\n    collections and user-defined functions (UDFs) defined in the `.fsl` files of the\n    `schema` directory.\n\n7. Create a key with the `admin` role for the `EcommerceDotnet` database:\n\n    ```sh\n    fauna query \"Key.create({ role: 'admin' })\" \\\n      --database us/EcommerceDotnet\n    ```\n\n    Copy the returned `secret`. The app can use the key's secret to authenticate\n    requests to the database.\n\n8.  Make a copy of the `.env.example` file and name the copy `.env`. For example:\n\n    ```sh\n    cp .env.example .env\n    ```\n\n9.  In `.env`, set the `FAUNA_SECRET` environment variable to the secret you\n    copied earlier:\n\n    ```\n    ...\n    FAUNA_SECRET=fn...\n    ...\n    ```\n\n\n## Run the app\n\nThe app runs an HTTP API server. From the `DotNetSampleApp` directory, run:\n\n```sh\nexport $(grep -v '^#' .env | xargs) \u0026\u0026 \\\nFAUNA_SECRET=$FAUNA_SECRET dotnet run\n```\n\nOnce started, the local server is available at http://localhost:5049.\n\n### Docker\n\nYou can also run the app in a Docker container. From the root directory, run:\n\n```sh\ndocker build -t dotnet-sample-app .\nexport $(grep -v '^#' .env | xargs) \u0026\u0026 \\\ndocker run -p 5049:8080 \\\n  -e ASPNETCORE_ENVIRONMENT=Development \\\n  -e FAUNA_SECRET=$FAUNA_SECRET \\\n  dotnet-sample-app\n```\n\nOnce started, the local server is available at http://localhost:5049.\n\n## Sample data\n\nThe app includes seed data that's populated when you make a successful request to any API endpoint.\n\n## HTTP API endpoints\n\nThe app's HTTP API endpoints are defined in the `DotNetSampleApp/Controllers` directory.\n\nAn OpenAPI spec and Swagger UI docs for the endpoints are available at:\n\n* OpenAPI spec: http://localhost:5049/swagger/v1/swagger.json\n* Swagger UI: http://localhost:5049/swagger/index.html\n\n### Make API requests\n\nYou can use the endpoints to make API requests that read and write data from\nthe `EcommerceDotnet` database.\n\nFor example, with the local server running in a separate terminal tab, run the\nfollowing curl request to the `POST /products` endpoint. The request creates a\n`Product` collection document in the `EcommerceDotnet` database.\n\n```sh\ncurl -v \\\n  http://localhost:5049/products \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"The Old Man and the Sea\",\n    \"price\": 899,\n    \"description\": \"A book by Ernest Hemingway\",\n    \"stock\": 10,\n    \"category\": \"books\"\n  }' | jq .\n```\n\n## Expand the app\n\nYou can further expand the app by adding fields and endpoints.\n\nAs an example, the following steps adds a computed `totalPurchaseAmt` field to\nCustomer documents and related API responses:\n\n1. If the app server is running, stop the server by pressing Ctrl+C.\n\n2. In `schema/collections.fsl`, add the following `totalPurchaseAmt` computed\n  field definition to the `Customer` collection:\n\n    ```diff\n    collection Customer {\n      ...\n      // Use a computed field to get the set of Orders for a customer.\n      compute orders: Set\u003cOrder\u003e = (customer =\u003e Order.byCustomer(customer))\n\n    + // Use a computed field to calculate the customer's cumulative purchase total.\n    + // The field sums purchase `total` values from the customer's linked Order documents.\n    + compute totalPurchaseAmt: Number = (customer =\u003e customer.orders.fold(0, (sum, order) =\u003e {\n    +   let order: Any = order\n    +   sum + order.total\n    + }))\n      ...\n    }\n    ...\n    ```\n\n    Save `schema/collections.fsl`.\n\n3. In `DotNetSampleApp/Controllers/QuerySnippets.cs`, add the `totalPurchaseAmt` field to the\n   `CustomerResponse` method's projection:\n\n    ```diff\n    ...\n    customer {\n        id,\n        name,\n        email,\n    +   address,\n    +   totalPurchaseAmt\n    }\n    ...\n    ```\n\n4.  Push the updated schema to the `EcommerceDotnet` database:\n\n    ```sh\n    # Authenticated using the FAUNA_SECRET env var.\n    fauna schema push\n    ```\n\n    When prompted, accept and stage the schema.\n\n5.  Check the status of the staged schema:\n\n    ```sh\n    fauna schema status\n    ```\n\n6.  When the status is `ready`, commit the staged schema changes to the\n    database:\n\n    ```sh\n    fauna schema commit\n    ```\n\n7. In `DotNetSampleApp/Models/Customer.cs`, add the\n   `totalPurchaseAmt` field to the `Customer` class:\n\n    ```diff\n    public class Customer\n    {\n        /// \u003csummary\u003e\n        /// Document ID\n        /// \u003c/summary\u003e\n        [Id]\n        public string? Id { get; init; }\n\n        ...\n\n        /// \u003csummary\u003e\n        /// Address\n        /// \u003c/summary\u003e\n        [Field]\n        public required Address Address { get; init; }\n\n    +   /// \u003csummary\u003e\n    +   /// Total Purchase Amount\n    +   /// \u003c/summary\u003e\n    +   [Field]\n    +   public required int TotalPurchaseAmt { get; init; }\n    }\n    ```\n\n    Save `DotNetSampleApp/Models/Customer.cs`.\n\n   Customer-related endpoints use this template to project Customer\n   document fields in responses.\n\n8. Start the app server:\n\n    ```sh\n    export $(grep -v '^#' .env | xargs) \u0026\u0026 \\\n    FAUNA_SECRET=$FAUNA_SECRET dotnet run\n    ```\n\n    If using Docker, run:\n\n    ```sh\n    docker build -t dotnet-sample-app .\n    export $(grep -v '^#' .env | xargs) \u0026\u0026 \\\n    docker run -p 5049:8080 \\\n      -e ASPNETCORE_ENVIRONMENT=Development \\\n      -e FAUNA_SECRET=$FAUNA_SECRET \\\n      dotnet-sample-app\n    ```\n\n9. With the local server running in a separate terminal tab, run the\n   following curl request to the `POST /customers` endpoint:\n\n    ```sh\n    curl -v http://localhost:5049/customers/999 | jq .\n    ```\n\n    The response includes the computed `totalPurchaseAmt` field:\n\n    ```json\n    {\n      \"id\": \"999\",\n      \"name\": \"Valued Customer\",\n      \"email\": \"fake@fauna.com\",\n      \"address\": {\n        \"street\": \"123 Main St\",\n        \"city\": \"San Francisco\",\n        \"state\": \"CA\",\n        \"postalCode\": \"12345\",\n        \"country\": \"United States\"\n      },\n      \"totalPurchaseAmt\": 36000\n    }\n    ```\n## Development\n\n### Local Testing\n1. Install the v3 version of the Fauna CLI: `npm install -g fauna-shell@3`\n2. Start Fauna in a container: `docker run --rm --name fauna -p 8443:8443 -p 8084:8084 fauna/faunadb`\n3. Configure the schema: `./setup-local.sh`\n4. Run tests: `dotnet test`\n\n### dotnet run with local Fauna\n1. Start Fauna in a container: `docker run --rm --name fauna -p 8443:8443 -p 8084:8084 fauna/faunadb`\n2. Configure the schema: `./setup-local.sh`\n2. Copy the secret returned from running `./setup-local.sh`\n2. `cd DotNetSampleApp`\n3. `FAUNA_SECRET=\"\u003cSECRET\u003e\" FAUNA_ENDPOINT=\"http://localhost:8443\" dotnet run`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffauna%2Fdotnet-sample-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffauna%2Fdotnet-sample-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffauna%2Fdotnet-sample-app/lists"}