![]() |
VOOZH | about |
dotnet add package Rystem.Content.Abstractions --version 10.0.8
NuGet\Install-Package Rystem.Content.Abstractions -Version 10.0.8
<PackageReference Include="Rystem.Content.Abstractions" Version="10.0.8" />
<PackageVersion Include="Rystem.Content.Abstractions" Version="10.0.8" />Directory.Packages.props
<PackageReference Include="Rystem.Content.Abstractions" />Project file
paket add Rystem.Content.Abstractions --version 10.0.8
#r "nuget: Rystem.Content.Abstractions, 10.0.8"
#:package Rystem.Content.Abstractions@10.0.8
#addin nuget:?package=Rystem.Content.Abstractions&version=10.0.8Install as a Cake Addin
#tool nuget:?package=Rystem.Content.Abstractions&version=10.0.8Install as a Cake Tool
Rystem.Content.Abstractions contains the shared content API, the registration builder, and the cross-provider migration service.
It does not implement storage by itself. Real storage arrives through provider packages such as Blob, File Share, SharePoint, or InMemory.
dotnet add package Rystem.Content.Abstractions
This package defines:
IContentRepositoryIContentRepositoryBuilderContentRepositoryOptionsContentRepositoryResultContentRepositoryDownloadResultContentInformationTypeIContentMigrationAt DI level, AddContentRepository() currently registers:
IContentMigration as TransientProvider registrations are added later through With...Integration(...) extension methods.
The core model is intentionally small:
IContentRepository is the only storage contractAddContentRepository() returns an IContentRepositoryBuilderIFactory<IContentRepository>In the current source tree and tests, named resolution is done with IFactory<IContentRepository>, not an IContentRepositoryFactory abstraction.
IContentRepositoryBuilder exposes three registration shapes:
| Method | Use when | Default lifetime |
|---|---|---|
WithIntegration<TRepository>(name, lifetime) |
repository has no options object | Transient |
WithIntegration<TRepository, TOptions>(options, name, lifetime) |
repository needs synchronous options wiring | Transient |
WithIntegrationAsync<TRepository, TOptions, TConnection>(options, name, lifetime) |
repository setup is asynchronous and builds a connection wrapper | Transient |
The built-in Blob, File, and SharePoint providers sit on top of WithIntegrationAsync(...). The InMemory provider uses WithIntegration(...) and overrides the lifetime to Singleton.
The provider-specific WithBlobStorageIntegration(...), WithFileStorageIntegration(...), WithSharepointIntegration(...), and WithInMemoryIntegration(...) extensions are defined by the provider packages, not by this package itself.
var repositories = services.AddContentRepository();
repositories.WithInMemoryIntegration("inmemory");
When you need a provider with async setup:
var repositories = services.AddContentRepository();
await repositories.WithBlobStorageIntegrationAsync(options =>
{
options.ContainerName = "supertest";
options.ConnectionString = configuration["ConnectionString:Storage"];
}, "blobstorage");
The content tests resolve repositories like this:
public sealed class ContentService
{
private readonly IContentRepository _contentRepository;
public ContentService(IFactory<IContentRepository> factory)
=> _contentRepository = factory.Create("blobstorage");
}
IContentRepository contract| Method | Return type | Purpose |
|---|---|---|
ListAsync(prefix, downloadContent, informationRetrieve) |
IAsyncEnumerable<ContentRepositoryDownloadResult> |
Enumerate files with optional prefix filtering |
DownloadAsync(path, informationRetrieve) |
Task<ContentRepositoryDownloadResult?> |
Download bytes and optional metadata |
GetPropertiesAsync(path, informationRetrieve) |
Task<ContentRepositoryResult?> |
Read metadata without downloading bytes |
UploadAsync(path, data, options, overwrite) |
ValueTask<bool> |
Create or replace a file |
SetPropertiesAsync(path, options) |
ValueTask<bool> |
Update headers, metadata, or tags |
DeleteAsync(path) |
ValueTask<bool> |
Delete a file |
ExistAsync(path) |
ValueTask<bool> |
Check whether a file exists |
Important caveat: overwrite is part of the shared interface, but not every provider enforces it the same way.
ContentRepositoryOptionsvar options = new ContentRepositoryOptions
{
HttpHeaders = new ContentRepositoryHttpHeaders
{
ContentType = "image/png",
CacheControl = "max-age=3600",
ContentDisposition = "attachment; filename=image.png"
},
Metadata = new Dictionary<string, string>
{
["author"] = "alice"
},
Tags = new Dictionary<string, string>
{
["version"] = "1"
}
};
ContentInformationType| Value | Meaning |
|---|---|
None |
no extra metadata |
HttpHeaders |
include content headers |
Metadata |
include metadata dictionary |
Tags |
include tags when supported |
All |
HttpHeaders | Metadata | Tags |
| Type | Properties |
|---|---|
ContentRepositoryResult |
Path, Uri, Options |
ContentRepositoryDownloadResult |
everything in ContentRepositoryResult plus Data |
Path and Uri are provider-defined. Do not assume they have identical semantics across Blob, File Share, SharePoint, and InMemory.
IContentMigration copies content between named providers.
This example matches the usage style in src/Content/Rystem.Content.Tests/Rystem.Content.UnitTest/Integrations/AllStorageTest.cs.
ContentMigrationResult result = await contentMigration.MigrateAsync(
sourceName: "inmemory",
destinationName: "filestorage",
settings: options =>
{
options.Prefix = "Test/Folder1/";
options.OverwriteIfExists = true;
options.Predicate = item => item.Path?.Contains("fileName6") != true;
options.ModifyDestinationPath = path => path.Replace("Folder2", "Folder3");
});
Available settings:
| Property | Default | Meaning |
|---|---|---|
Prefix |
null |
restrict source enumeration |
Predicate |
null |
skip items that do not match |
OverwriteIfExists |
false |
pass overwrite intent to destination upload |
OnErrorContinue |
true |
keep going after per-file errors |
ModifyDestinationPath |
null |
rewrite the output path |
The current implementation is a straightforward copy loop:
IFactory<IContentRepository>ListAsync(..., downloadContent: false, ContentInformationType.None)ContentInformationType.AllImportant caveats from the source:
NotMigratedPaths exists on ContentMigrationResult, but the current implementation never fills itfalse, the result currently lands in NotContentPathsIf you want your own backend, implement IContentRepository and register it through the builder.
internal sealed class MyContentRepository : IContentRepository
{
public IAsyncEnumerable<ContentRepositoryDownloadResult> ListAsync(
string? prefix = null,
bool downloadContent = false,
ContentInformationType informationRetrieve = ContentInformationType.None,
CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public Task<ContentRepositoryDownloadResult?> DownloadAsync(
string path,
ContentInformationType informationRetrieve = ContentInformationType.None,
CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public Task<ContentRepositoryResult?> GetPropertiesAsync(
string path,
ContentInformationType informationRetrieve = ContentInformationType.All,
CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public ValueTask<bool> UploadAsync(
string path,
byte[] data,
ContentRepositoryOptions? options = null,
bool overwrite = true,
CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public ValueTask<bool> SetPropertiesAsync(
string path,
ContentRepositoryOptions? options = null,
CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public ValueTask<bool> DeleteAsync(string path, CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public ValueTask<bool> ExistAsync(string path, CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
}
Then register it:
services
.AddContentRepository()
.WithIntegration<MyContentRepository>("custom");
Rystem.Content.Infrastructure.Storage.BlobRystem.Content.Infrastructure.Storage.FileRystem.Content.Infrastructure.M365.SharepointRystem.Content.Infrastructure.InMemoryUse this package when you want the contract and migration layer; add a provider package when you want real storage.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 4 NuGet packages that depend on Rystem.Content.Abstractions:
| Package | Downloads |
|---|---|
|
Rystem.Content.Infrastructure.M365.Sharepoint
Rystem.Content helps you to integrate with azure services or to create an abstraction layer among your infrastructure and your business. |
|
|
Rystem.Content.Infrastructure.Storage.Blob
Rystem.Content helps you to integrate with azure services or to create an abstraction layer among your infrastructure and your business. |
|
|
Rystem.Content.Infrastructure.InMemory
Rystem.Content helps you to integrate with azure services or to create an abstraction layer among your infrastructure and your business. |
|
|
Rystem.Content.Infrastructure.Storage.File
Rystem.Content helps you to integrate with azure services or to create an abstraction layer among your infrastructure and your business. |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.0.8 | 5,584 | 5/13/2026 |
| 10.0.7 | 219 | 3/26/2026 |
| 10.0.6 | 433,712 | 3/3/2026 |
| 10.0.5 | 231 | 2/22/2026 |
| 10.0.4 | 242 | 2/9/2026 |
| 10.0.3 | 148,007 | 1/28/2026 |
| 10.0.1 | 209,207 | 11/12/2025 |
| 9.1.3 | 472 | 9/2/2025 |
| 9.1.2 | 764,577 | 5/29/2025 |
| 9.1.1 | 97,929 | 5/2/2025 |
| 9.0.32 | 186,791 | 4/15/2025 |
| 9.0.31 | 5,907 | 4/2/2025 |
| 9.0.30 | 88,960 | 3/26/2025 |
| 9.0.29 | 9,091 | 3/18/2025 |
| 9.0.28 | 327 | 3/17/2025 |
| 9.0.27 | 335 | 3/16/2025 |
| 9.0.26 | 352 | 3/13/2025 |
| 9.0.25 | 52,218 | 3/9/2025 |
| 9.0.23 | 302 | 3/9/2025 |
| 9.0.21 | 434 | 3/6/2025 |