Dotnet

作者 appwriteab3c90b37c95無授權條款10 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫7 週前更新

Appwrite .NET SDK skill. Use when building server-side C# or .NET applications with Appwrite, including ASP.NET and Blazor integrations. Covers user management, database/table CRUD, file storage, and functions via API keys.

AI 產生的概覽

使用 Appwrite SDK 建置伺服端 C#/.NET 應用程式的參考,涵蓋使用者、資料表、儲存、團隊、函式與 SSR 驗證。

功能
提供使用 Appwrite .NET SDK 的 C# 程式碼範例與說明:用戶端設定、使用者管理、資料表與資料列的增刪改查及查詢輔助方法、檔案儲存、團隊與成員、無伺服器函式,以及適用於 ASP.NET 與 Blazor 的 SSR 驗證。也說明了字串欄位型別、錯誤處理以及權限與角色字串。產出為參考文件與程式碼片段,而非產生的檔案。
適用情境
適用於撰寫或審查整合 Appwrite 的伺服端 C# 或 .NET 程式碼,包括 ASP.NET 與 Blazor 伺服器端轉譯的驗證流程。也適合在選擇欄位型別、建構查詢或設定資料列與檔案權限時參考。
執行需求
不附帶指令碼,僅為說明文件。使用範例需要 .NET SDK 與 Appwrite NuGet 套件、Appwrite 端點、專案 ID,以及 API 金鑰或工作階段 Cookie,並需要能連線至 Appwrite 執行個體的網路。

Appwrite .NET SDK

Installation

bash
dotnet add package Appwrite

Setting Up the Client

csharp
using Appwrite;using Appwrite.Services;using Appwrite.Models;
var client = new Client()    .SetEndpoint("https://<REGION>.cloud.appwrite.io/v1")    .SetProject(Environment.GetEnvironmentVariable("APPWRITE_PROJECT_ID"))    .SetKey(Environment.GetEnvironmentVariable("APPWRITE_API_KEY"));

Code Examples

User Management

csharp
var users = new Users(client);
// Create uservar user = await users.Create(ID.Unique(), "[email protected]", null, "password123", "User Name");
// List usersvar list = await users.List(new List<string> { Query.Limit(25) });
// Get uservar fetched = await users.Get("[USER_ID]");
// Delete userawait users.Delete("[USER_ID]");

Database Operations

Note: Use TablesDB (not the deprecated Databases class) for all new code. Only use Databases if the existing codebase already relies on it or the user explicitly requests it.

Tip: Prefer named arguments (e.g., databaseId: "...") for all SDK method calls. Only use positional arguments if the existing codebase already uses them or the user explicitly requests it.

csharp
var tablesDB = new TablesDB(client);
// Create databasevar db = await tablesDB.Create(ID.Unique(), "My Database");
// Create rowvar doc = await tablesDB.CreateRow("[DATABASE_ID]", "[TABLE_ID]", ID.Unique(),    new Dictionary<string, object> { { "title", "Hello World" } });
// Query rowsvar results = await tablesDB.ListRows("[DATABASE_ID]", "[TABLE_ID]",    new List<string> { Query.Equal("title", "Hello World"), Query.Limit(10) });
// Get rowvar row = await tablesDB.GetRow("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]");
// Update rowawait tablesDB.UpdateRow("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]",    new Dictionary<string, object> { { "title", "Updated" } });
// Delete rowawait tablesDB.DeleteRow("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]");
String Column Types

Note: The legacy string type is deprecated. Use explicit column types for all new columns.

TypeMax charactersIndexingStorage
varchar16,383Full index (if size ≤ 768)Inline in row
text16,383Prefix onlyOff-page
mediumtext4,194,303Prefix onlyOff-page
longtext1,073,741,823Prefix onlyOff-page
  • varchar is stored inline and counts towards the 64 KB row size limit. Prefer for short, indexed fields like names, slugs, or identifiers.
  • text, mediumtext, and longtext are stored off-page (only a 20-byte pointer lives in the row), so they don't consume the row size budget. size is not required for these types.
csharp
// Create table with explicit string column typesawait tablesDB.CreateTable("[DATABASE_ID]", ID.Unique(), "articles",    new List<object> {        new { key = "title",    type = "varchar",    size = 255, required = true  },  // inline, fully indexable        new { key = "summary",  type = "text",                   required = false },  // off-page, prefix index only        new { key = "body",     type = "mediumtext",             required = false },  // up to ~4 M chars        new { key = "raw_data", type = "longtext",               required = false },  // up to ~1 B chars    });

Query Methods

csharp
// FilteringQuery.Equal("field", "value")             // == (or pass array for IN)Query.NotEqual("field", "value")          // !=Query.LessThan("field", 100)             // <Query.LessThanEqual("field", 100)        // <=Query.GreaterThan("field", 100)          // >Query.GreaterThanEqual("field", 100)     // >=Query.Between("field", 1, 100)           // 1 <= field <= 100Query.IsNull("field")                    // is nullQuery.IsNotNull("field")                 // is not nullQuery.StartsWith("field", "prefix")      // starts withQuery.EndsWith("field", "suffix")        // ends withQuery.Contains("field", "sub")           // containsQuery.Search("field", "keywords")        // full-text search (requires index)
// SortingQuery.OrderAsc("field")Query.OrderDesc("field")
// PaginationQuery.Limit(25)                          // max rows (default 25, max 100)Query.Offset(0)                          // skip N rowsQuery.CursorAfter("[ROW_ID]")            // cursor pagination (preferred)Query.CursorBefore("[ROW_ID]")
// Selection & LogicQuery.Select(new List<string> { "field1", "field2" })Query.Or(new List<string> { Query.Equal("a", 1), Query.Equal("b", 2) })   // ORQuery.And(new List<string> { Query.GreaterThan("age", 18), Query.LessThan("age", 65) })  // AND (default)

File Storage

csharp
var storage = new Storage(client);
// Upload filevar file = await storage.CreateFile("[BUCKET_ID]", ID.Unique(), InputFile.FromPath("/path/to/file.png"));
// List filesvar files = await storage.ListFiles("[BUCKET_ID]");
// Delete fileawait storage.DeleteFile("[BUCKET_ID]", "[FILE_ID]");
InputFile Factory Methods
csharp
using Appwrite.Models;
InputFile.FromPath("/path/to/file.png")                          // from filesystem pathInputFile.FromBytes(byteArray, "file.png", "image/png")          // from byte[]InputFile.FromStream(stream, "file.png", "image/png", size)      // from Stream (size required)

Teams

csharp
var teams = new Teams(client);
// Create teamvar team = await teams.Create(ID.Unique(), "Engineering");
// List teamsvar list = await teams.List();
// Create membership (invite user by email)var membership = await teams.CreateMembership(    teamId: "[TEAM_ID]",    roles: new List<string> { "editor" },    email: "[email protected]");
// List membershipsvar members = await teams.ListMemberships("[TEAM_ID]");
// Update membership rolesawait teams.UpdateMembership("[TEAM_ID]", "[MEMBERSHIP_ID]", new List<string> { "admin" });
// Delete teamawait teams.Delete("[TEAM_ID]");

Role-based access: Use Role.Team("[TEAM_ID]") for all team members or Role.Team("[TEAM_ID]", "editor") for a specific team role when setting permissions.

Serverless Functions

csharp
var functions = new Functions(client);
// Execute functionvar execution = await functions.CreateExecution("[FUNCTION_ID]", body: "{\"key\": \"value\"}");
// List executionsvar executions = await functions.ListExecutions("[FUNCTION_ID]");
Writing a Function Handler (.NET runtime)
csharp
// src/Main.cs — Appwrite Function entry pointusing System.Text.Json;
public async Task<RuntimeOutput> Main(RuntimeContext context){    // context.Req.Body        — raw body (string)    // context.Req.BodyJson    — parsed JSON (JsonElement)    // context.Req.Headers     — headers (Dictionary)    // context.Req.Method      — HTTP method    // context.Req.Path        — URL path    // context.Req.Query       — query params (Dictionary)
    context.Log($"Processing: {context.Req.Method} {context.Req.Path}");
    if (context.Req.Method == "GET")        return context.Res.Json(new { message = "Hello from Appwrite Function!" });
    return context.Res.Json(new { success = true });      // JSON    // context.Res.Text("Hello");                         // plain text    // context.Res.Empty();                               // 204    // context.Res.Redirect("https://...");               // 302}

Server-Side Rendering (SSR) Authentication

SSR apps using .NET frameworks (ASP.NET, Blazor Server, etc.) use the server SDK to handle auth. You need two clients:

  • Admin client — uses an API key, creates sessions, bypasses rate limits (reusable singleton)
  • Session client — uses a session cookie, acts on behalf of a user (create per-request, never share)
csharp
using Appwrite;using Appwrite.Services;
// Admin client (reusable)var adminClient = new Client()    .SetEndpoint("https://<REGION>.cloud.appwrite.io/v1")    .SetProject("[PROJECT_ID]")    .SetKey(Environment.GetEnvironmentVariable("APPWRITE_API_KEY"));
// Session client (create per-request)var sessionClient = new Client()    .SetEndpoint("https://<REGION>.cloud.appwrite.io/v1")    .SetProject("[PROJECT_ID]");
var session = Request.Cookies["a_session_[PROJECT_ID]"];if (session != null){    sessionClient.SetSession(session);}
Email/Password Login (ASP.NET Minimal API)
csharp
app.MapPost("/login", async (HttpContext ctx, LoginRequest body) =>{    var account = new Account(adminClient);    var session = await account.CreateEmailPasswordSession(body.Email, body.Password);
    // Cookie name must be a_session_<PROJECT_ID>    ctx.Response.Cookies.Append("a_session_[PROJECT_ID]", session.Secret, new CookieOptions    {        HttpOnly = true,        Secure = true,        SameSite = SameSiteMode.Strict,        Path = "/",    });
    return Results.Ok(new { success = true });});
Authenticated Requests
csharp
app.MapGet("/user", async (HttpContext ctx) =>{    var session = ctx.Request.Cookies["a_session_[PROJECT_ID]"];    if (session == null) return Results.Unauthorized();
    var sessionClient = new Client()        .SetEndpoint("https://<REGION>.cloud.appwrite.io/v1")        .SetProject("[PROJECT_ID]")        .SetSession(session);
    var account = new Account(sessionClient);    var user = await account.Get();    return Results.Ok(user);});
OAuth2 SSR Flow
csharp
// Step 1: Redirect to OAuth providerapp.MapGet("/oauth", async () =>{    var account = new Account(adminClient);    var redirectUrl = await account.CreateOAuth2Token(        provider: OAuthProvider.Github,        success: "https://example.com/oauth/success",        failure: "https://example.com/oauth/failure"    );    return Results.Redirect(redirectUrl);});
// Step 2: Handle callback — exchange token for sessionapp.MapGet("/oauth/success", async (HttpContext ctx, string userId, string secret) =>{    var account = new Account(adminClient);    var session = await account.CreateSession(userId, secret);
    ctx.Response.Cookies.Append("a_session_[PROJECT_ID]", session.Secret, new CookieOptions    {        HttpOnly = true, Secure = true, SameSite = SameSiteMode.Strict, Path = "/",    });
    return Results.Ok(new { success = true });});

Cookie security: Always use HttpOnly, Secure, and SameSite = SameSiteMode.Strict to prevent XSS. The cookie name must be a_session_<PROJECT_ID>.

Forwarding user agent: Call sessionClient.SetForwardedUserAgent(ctx.Request.Headers["User-Agent"]) to record the end-user's browser info for debugging and security.

Error Handling

csharp
using Appwrite;
try{    var row = await tablesDB.GetRow("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]");}catch (AppwriteException e){    Console.WriteLine(e.Message);    // human-readable message    Console.WriteLine(e.Code);       // HTTP status code (int)    Console.WriteLine(e.Type);       // error type (e.g. "document_not_found")    Console.WriteLine(e.Response);   // full response body}

Common error codes:

CodeMeaning
401Unauthorized — missing or invalid session/API key
403Forbidden — insufficient permissions
404Not found — resource does not exist
409Conflict — duplicate ID or unique constraint
429Rate limited — too many requests

Permissions & Roles (Critical)

Appwrite uses permission strings to control access to resources. Each permission pairs an action (read, update, delete, create, or write which grants create + update + delete) with a role target. By default, no user has access unless permissions are explicitly set at the row/file level or inherited from the table/bucket settings. Permissions are arrays of strings built with the Permission and Role helpers.

csharp
using Appwrite;// Permission and Role are included in the main namespace

Database Row with Permissions

csharp
var doc = await tablesDB.CreateRow("[DATABASE_ID]", "[TABLE_ID]", ID.Unique(),    new Dictionary<string, object> { { "title", "Hello World" } },    new List<string>    {        Permission.Read(Role.User("[USER_ID]")),     // specific user can read        Permission.Update(Role.User("[USER_ID]")),   // specific user can update        Permission.Read(Role.Team("[TEAM_ID]")),     // all team members can read        Permission.Read(Role.Any()),                 // anyone (including guests) can read    });

File Upload with Permissions

csharp
var file = await storage.CreateFile("[BUCKET_ID]", ID.Unique(),    InputFile.FromPath("/path/to/file.png"),    new List<string>    {        Permission.Read(Role.Any()),        Permission.Update(Role.User("[USER_ID]")),        Permission.Delete(Role.User("[USER_ID]")),    });

When to set permissions: Set row/file-level permissions when you need per-resource access control. If all rows in a table share the same rules, configure permissions at the table/bucket level and leave row permissions empty.

Common mistakes:

  • Forgetting permissions — the resource becomes inaccessible to all users (including the creator)
  • Role.Any() with write/update/delete — allows any user, including unauthenticated guests, to modify or remove the resource
  • Permission.Read(Role.Any()) on sensitive data — makes the resource publicly readable

來源與署名

來源:appwrite/claude-plugin位於skills/dotnet提交ab3c90b

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架