Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .cursor/rules/cloudinary.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
description: Cloudinary CloudinaryDotNet — agent guide
alwaysApply: true
---

Read and follow `AGENTS.md` in the repository root. It is the single
authoritative guide for this package: build/test commands, conventions,
gotchas, and when to use this SDK versus a sibling Cloudinary package.
5 changes: 5 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Cloudinary CloudinaryDotNet — instructions for AI coding agents

Read `AGENTS.md` in the repository root and follow it. It is the single
authoritative guide for this package: build/test commands, conventions,
gotchas, and when to use this SDK versus a sibling Cloudinary package.
77 changes: 77 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# AGENTS.md — CloudinaryDotNet

## What this package is (one line)
Official server-side Cloudinary .NET SDK: upload assets, build transformation/delivery URLs, and call the Admin API from a C#/.NET backend that holds your `ApiSecret`.

## When to use this / when NOT to use this
- **Use this when:** you are in a server-side .NET runtime (ASP.NET Core, Web API, worker service, console job) and need to upload assets, generate signed delivery URLs, or administer assets via the Admin API — work that must keep the `ApiSecret` private.
- **Do NOT use this when:** you only need to render delivery URLs in a **browser/frontend bundle** (that ships the secret to clients) — use `@cloudinary/url-gen` in JavaScript instead; or you want an autonomous/no-code agent path — use the Cloudinary MCP server.
- **Sibling packages:** `account-provisioning-dotnet` = the dedicated Provisioning API SDK for creating users, sub-accounts, and API keys (not this package). `@cloudinary/url-gen` = browser-side URL builder. Rule of thumb: code on a **server** → this package; code in a **browser** → not this package.

## Setup
```
PM> Install-Package CloudinaryDotNet
```
Or via the CLI:
```bash
dotnet add package CloudinaryDotNet
```
Required configuration / credentials. The parameterless constructor reads `CLOUDINARY_URL`:
```bash
export CLOUDINARY_URL=cloudinary://API_KEY:API_SECRET@CLOUD_NAME
```

## Minimal runnable example
```csharp
using CloudinaryDotNet;
using CloudinaryDotNet.Actions;

var cloudinary = new Cloudinary(); // reads CLOUDINARY_URL

var uploadResult = cloudinary.Upload(new ImageUploadParams
{
File = new FileDescription(@"c:\mypicture.jpg")
});

var url = cloudinary.Api.UrlImgUp
.Transform(new Transformation().Width(100).Height(150).Crop("fill"))
.BuildUrl("sample.jpg");
```

## Build / test commands (run these after editing)
Solution file is `CloudinaryDotnet.sln`; target frameworks are `netstandard1.3;netstandard2.0;net452`.
```bash
dotnet restore CloudinaryDotnet.sln
dotnet build CloudinaryDotnet.sln -c Release

# Unit tests — no network/credentials required:
dotnet test ./CloudinaryDotNet.Tests/CloudinaryDotNet.Tests.csproj -c Release

# Integration tests — require LIVE Cloudinary credentials (see gotcha below):
dotnet test ./CloudinaryDotNet.IntegrationTests/CloudinaryDotNet.IntegrationTests.csproj -c Release

# Pack a NuGet (build.ps1 wraps this):
dotnet pack -c Release -o lib
```
(CI runs on AppVeyor (`appveyor.yml`), which runs the same two `dotnet test` projects — no separate `dotnet format`/lint step. The commands above drop the AppVeyor-only `--logger:Appveyor` / `--test-adapter-path:.` flags.)

## Conventions & gotchas
- **Integration tests need a live account.** `CloudinaryDotNet.IntegrationTests` reads credentials from `CloudinaryDotNet.IntegrationTests/appsettings.json`. Copy `appsettings.json.sample` to `appsettings.json` and fill in `CloudName`/`ApiKey`/`ApiSecret` (CI provisions a throwaway sub-account via `before_build.ps1`). Without valid credentials these tests fail/hang — run `CloudinaryDotNet.Tests` (unit) for fast, offline feedback.
- **Run unit tests for normal edits;** only run integration tests when you change request building, signing, or API surface.
- **Server-side only.** The `ApiSecret` must never reach a browser bundle — that constraint is the reason this SDK exists. Do not add frontend/client-bundle code paths here.
- **Multi-target build.** Changes must compile against `netstandard1.3`, `netstandard2.0`, and `net452`; avoid APIs unavailable on the lowest target.
- **Public API surface:** consume types from `CloudinaryDotNet` and `CloudinaryDotNet.Actions` (as in the example); keep new public surface consistent with these namespaces.

## Canonical docs (leave the repo for depth)
- .NET SDK guide: https://cloudinary.com/documentation/dotnet_integration
- Asset administration (Admin API): https://cloudinary.com/documentation/dotnet_asset_administration
- Transformation & REST API reference: https://cloudinary.com/documentation/cloudinary_references
- MCP server (agent/no-code path): https://github.com/cloudinary/mcp-servers

## Agent / MCP note
If the task is exposed via the Cloudinary MCP servers, prefer the MCP tool for autonomous task execution and use this SDK for generated backend code. See cloudinary/mcp-servers.

## Commit / PR conventions
- Ensure unit tests pass locally before opening a PR; CI must pass (it runs both unit and integration test projects).
- Use the repo `.github/pull_request_template.md` (it has a "what does this PR address" + tests-included + checklist form); see `CONTRIBUTING.md`.
- No formal commit-message convention (e.g. Conventional Commits) is documented. `CONTRIBUTING.md` only asks that a commit log "describe what changed and why," and that you squash commits into a single commit when appropriate.
34 changes: 34 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
@AGENTS.md

# CLAUDE.md — CloudinaryDotNet

## What this repo is

Official server-side Cloudinary .NET SDK. Handles upload, transformation/delivery URL building, and Admin API calls from a C#/.NET backend that holds the `ApiSecret`.

## Key constraints

- **Server-side only.** The `ApiSecret` must never reach a browser bundle. Do not add client-side code paths.
- **Multi-target build.** Code must compile against `netstandard1.3`, `netstandard2.0`, and `net452`. Avoid APIs unavailable on the lowest target.
- **Two separate test projects.** `CloudinaryDotNet.Tests` (unit — no credentials, fast) and `CloudinaryDotNet.IntegrationTests` (live account required). Run unit tests for normal edits; integration tests only when changing request building, signing, or API surface.
- **Integration tests need credentials.** Copy `CloudinaryDotNet.IntegrationTests/appsettings.json.sample` → `appsettings.json` and fill in `CloudName`/`ApiKey`/`ApiSecret` before running them. Without valid credentials these tests fail or hang.
- **Solution file is `CloudinaryDotnet.sln`** (lowercase 'n' in the filename).
- **Public namespaces:** `CloudinaryDotNet` and `CloudinaryDotNet.Actions`. Keep new public surface consistent with these.

## Verified build / test commands

```bash
dotnet restore CloudinaryDotnet.sln
dotnet build CloudinaryDotnet.sln -c Release

# Unit tests — no network or credentials required:
dotnet test ./CloudinaryDotNet.Tests/CloudinaryDotNet.Tests.csproj -c Release

# Integration tests — require live Cloudinary credentials:
dotnet test ./CloudinaryDotNet.IntegrationTests/CloudinaryDotNet.IntegrationTests.csproj -c Release

# Pack a NuGet:
dotnet pack -c Release -o lib
```

CI runs on AppVeyor (`appveyor.yml`) — same two `dotnet test` projects, no separate lint step.
164 changes: 88 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,118 +1,130 @@
[![Build status](https://ci.appveyor.com/api/projects/status/vdx8o03ethg5opt4?svg=true)](https://ci.appveyor.com/project/Cloudinary/cloudinarydotnet)
[![NuGet Badge](https://img.shields.io/nuget/v/CloudinaryDotNet)](https://www.nuget.org/packages/CloudinaryDotNet/)
![NuGet Downloads](https://img.shields.io/nuget/dt/CloudinaryDotNet)
# Cloudinary .NET SDK

Cloudinary .NET SDK
==================
## About
The Cloudinary .NET SDK allows you to quickly and easily integrate your application with Cloudinary.
Effortlessly optimize, transform, upload and manage your cloud's assets.
[![Build status](https://ci.appveyor.com/api/projects/status/vdx8o03ethg5opt4?svg=true)](https://ci.appveyor.com/project/Cloudinary/cloudinarydotnet)
[![NuGet version](https://img.shields.io/nuget/v/CloudinaryDotNet)](https://www.nuget.org/packages/CloudinaryDotNet/)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)

The `CloudinaryDotNet` package is the server-side Cloudinary SDK for .NET. Use it on a server or in a build step to upload assets, build transformation and delivery URLs, and call the Admin API. It holds your API secret, so it handles the operations that can't run in a browser: signed uploads, signed delivery URLs, and asset administration. The package multi-targets .NET Standard 1.3, .NET Standard 2.0, and .NET Framework 4.5.2 — any consumer on .NET Standard 2.0 or later (.NET Core 2.x/3.x, .NET 5-9, .NET Framework 4.6.1+) resolves the `netstandard2.0` build. The current release is 1.29.2.

#### Note
This Readme provides basic installation and usage information.
For the complete documentation, see the [.NET SDK Guide](https://cloudinary.com/documentation/dotnet_integration).
## Installation

## Table of Contents
- [Key Features](#key-features)
- [Version Support](#Version-Support)
- [Installation](#installation)
- [Usage](#usage)
- [Setup](#Setup)
- [Transform and Optimize Assets](#Transform-and-Optimize-Assets)
Using the .NET CLI:

```bash
dotnet add package CloudinaryDotNet
```

## Key Features
- [Transform](https://cloudinary.com/documentation/dotnet_video_manipulation#video_transformation_examples) and
[optimize](https://cloudinary.com/documentation/dotnet_image_manipulation#image_optimizations) assets.
- Generate [image](https://cloudinary.com/documentation/dotnet_image_manipulation#deliver_and_transform_images) and
[video](https://cloudinary.com/documentation/dotnet_video_manipulation#dotnet_video_transformation_code_examples) tags.
- [Asset Management](https://cloudinary.com/documentation/dotnet_asset_administration).
- [Secure URLs](https://cloudinary.com/documentation/video_manipulation_and_delivery#generating_secure_https_urls_using_sdks).
Or the Package Manager console:

```powershell
Install-Package CloudinaryDotNet
```

## Configuration

## Version Support
Create a `Cloudinary` instance and give it your credentials. The parameterless constructor reads them automatically from the `CLOUDINARY_URL` environment variable:

| SDK Version | .NET Framework 4.5.2 - 4.8 | .NET Standard 1.3 and up | .NET Core | .NET 5 - 9 |
|-------------|----------------------------|--------------------------|-----------|------------|
| 1.x | ✔ | ✔ | ✔ | ✔ |
```bash
CLOUDINARY_URL=cloudinary://<API_KEY>:<API_SECRET>@<CLOUD_NAME>
```

## Installation
CloudinaryDotNet is available as NuGet package [CloudinaryDotNet](https://nuget.org/packages/CloudinaryDotNet)
```csharp
using CloudinaryDotNet;

Install using Package Manager:
// Credentials come from CLOUDINARY_URL in the environment.
var cloudinary = new Cloudinary();
```
PM> Install-Package CloudinaryDotNet

To set them in code instead, pass an `Account`:

```csharp
using CloudinaryDotNet;

var cloudinary = new Cloudinary(new Account("my_cloud_name", "my_key", "my_secret"));
```

# Usage
Keep the API secret on the server. Don't put it in client-side code or commit it to version control.

## Quick examples

### Upload a file with the .NET SDK

`Upload` takes an `ImageUploadParams` whose `File` is a `FileDescription` pointing at a local path or a remote URL. It returns an `ImageUploadResult` with `PublicId` and `SecureUrl`:

### Setup
```csharp
using CloudinaryDotNet;
using CloudinaryDotNet.Actions;

// Credentials come from CLOUDINARY_URL in the environment.
var cloudinary = new Cloudinary();
```

### Transform and Optimize Assets
- [See full documentation](https://cloudinary.com/documentation/dotnet_image_manipulation).
var result = cloudinary.Upload(new ImageUploadParams
{
File = new FileDescription(@"c:\my_image.jpg"),
PublicId = "cms/hero", // optional: where the asset lives in your media library
});

```csharp
var url = cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(100).Height(150).Crop("fill")).BuildUrl("sample.jpg")
Console.WriteLine(result.PublicId);
Console.WriteLine(result.SecureUrl); // the https delivery URL
```

### Upload
- [See full documentation](https://cloudinary.com/documentation/dotnet_image_and_video_upload).
- [Learn more about configuring your uploads with upload presets](https://cloudinary.com/documentation/upload_presets).
`UploadAsync(uploadParams)` returns the same `ImageUploadResult` as a `Task`.

### Transform and optimize a delivery URL

`Api.UrlImgUp` builds a URL synchronously — no network call. This resizes to a 100x150 fill crop and lets Cloudinary pick the format and quality for the requesting browser (`f_auto`, `q_auto`). Building a URL needs no API secret, so this instance is constructed with a cloud name only:

```csharp
var uploadParams = new ImageUploadParams()
{
File = new FileDescription(@"c:\mypicture.jpg")
};
using CloudinaryDotNet;

var uploadResult = cloudinary.Upload(uploadParams);
```
var cloudinary = new Cloudinary(new Account("demo"));

### Code Samples
var url = cloudinary.Api.UrlImgUp
.Secure(true)
.Transform(new Transformation()
.Width(100).Height(150).Crop("fill")
.FetchFormat("auto").Quality("auto"))
.BuildUrl("sample.jpg");
// https://res.cloudinary.com/demo/image/upload/c_fill,f_auto,h_150,q_auto,w_100/sample.jpg
```

You can find our simple and ready-to-use samples projects, along with documentations in the [samples folder](https://github.com/cloudinary/CloudinaryDotNet/tree/master/samples).
### Retrieve asset details

Please consult with the [README file](https://github.com/cloudinary/CloudinaryDotNet/blob/master/samples/README.md), for usage and explanations.
`GetResource` takes a public ID and returns the asset's metadata, including its format, dimensions, and `SecureUrl`:

```csharp
using CloudinaryDotNet;
using CloudinaryDotNet.Actions;

### Security options
- [See full documentation](https://cloudinary.com/documentation/solution_overview#security).
// Credentials come from CLOUDINARY_URL in the environment.
var cloudinary = new Cloudinary();

## Contributions
- Ensure tests run locally
- Open a PR and ensure Travis tests pass
GetResourceResult asset = cloudinary.GetResource("sample");
Console.WriteLine($"{asset.Format} {asset.Width}x{asset.Height} {asset.SecureUrl}");
```

`GetResourceAsync("sample")` returns the same `GetResourceResult` as a `Task`.

## Get Help
If you run into an issue or have a question, you can either:
- Issues related to the SDK: [Open a GitHub issue](https://github.com/cloudinary/CloudinaryDotNet/issues).
- Issues related to your account: [Open a support ticket](https://cloudinary.com/contact)
## For AI agents

`CloudinaryDotNet` is the .NET server-side SDK. Choose it for backend upload, asset administration, and signed URL or tag generation, where the API secret stays private. For other Cloudinary tasks, choose a different package:

## About Cloudinary
Cloudinary is a powerful media API for websites and mobile apps alike, Cloudinary enables developers to efficiently
manage, transform, optimize, and deliver images and videos through multiple CDNs. Ultimately, viewers enjoy responsive
and personalized visual-media experiences—irrespective of the viewing device.
| Task | Package |
|---|---|
| Provision users, product environments, and API keys in .NET | [`Cloudinary.Account.Provisioning`](https://github.com/cloudinary/account-provisioning-dotnet) |
| Build delivery URLs in the browser | [`@cloudinary/url-gen`](https://github.com/cloudinary/js-url-gen) |
| Render React, Angular, or Vue components | [`@cloudinary/react` / `@cloudinary/ng` / `@cloudinary/vue`](https://github.com/cloudinary/frontend-frameworks) |
| Run Cloudinary operations as agent tools | [Cloudinary MCP servers](https://github.com/cloudinary/mcp-servers) |

Every upload and admin method has an `async` variant (`UploadAsync`, `GetResourceAsync`, `Search().ExecuteAsync()`). Public types live in the `CloudinaryDotNet` and `CloudinaryDotNet.Actions` namespaces.

## Additional Resources
- [Cloudinary Transformation and REST API References](https://cloudinary.com/documentation/cloudinary_references): Comprehensive references, including syntax and examples for all SDKs.
- [MediaJams.dev](https://mediajams.dev/): Bite-size use-case tutorials written by and for Cloudinary Developers
- [DevJams](https://www.youtube.com/playlist?list=PL8dVGjLA2oMr09amgERARsZyrOz_sPvqw): Cloudinary developer podcasts on YouTube.
- [Cloudinary Academy](https://training.cloudinary.com/): Free self-paced courses, instructor-led virtual courses, and on-site courses.
- [Code Explorers and Feature Demos](https://cloudinary.com/documentation/code_explorers_demos_index): A one-stop shop for all code explorers, Postman collections, and feature demos found in the docs.
- [Cloudinary Roadmap](https://cloudinary.com/roadmap): Your chance to follow, vote, or suggest what Cloudinary should develop next.
- [Cloudinary Facebook Community](https://www.facebook.com/groups/CloudinaryCommunity): Learn from and offer help to other Cloudinary developers.
- [Cloudinary Account Registration](https://cloudinary.com/users/register/free): Free Cloudinary account registration.
- [Cloudinary Website](https://cloudinary.com): Learn about Cloudinary's products, partners, customers, pricing, and more.
## Links

- [.NET SDK guide](https://cloudinary.com/documentation/dotnet_integration)
- [Upload](https://cloudinary.com/documentation/dotnet_image_and_video_upload)
- [Asset administration (Admin API)](https://cloudinary.com/documentation/dotnet_asset_administration)
- [Transformation and API references](https://cloudinary.com/documentation/cloudinary_references)
- [Documentation llms.txt index](https://cloudinary.com/documentation/llms.txt)
- [Package on NuGet](https://www.nuget.org/packages/CloudinaryDotNet/)

## Licence
Released under the MIT license.