| Package | Version | Downloads |
|---|---|---|
WopiHost.Abstractions |
||
WopiHost.Core |
||
WopiHost.Discovery |
||
WopiHost.FileSystemProvider |
||
WopiHost.MemoryLockProvider |
||
WopiHost.Url |
This project is a sample implementation of a WOPI host. Basically, it allows developers to integrate custom datasources with Office Online Server (formerly Office Web Apps) or any other WOPI client by implementing a bunch of interfaces.
The WopiHost project is built using a modular architecture that separates concerns and allows for flexible implementations. Here's how the modules work together:
graph TB
subgraph "Sample Applications"
SampleApps["**Sample Applications**<br/>๐ **WopiHost.Web**<br/>๐งช **WopiHost.Validator**<br/>๐ **WopiHost Sample**"]
end
subgraph "WOPI Client"
OOS["**Office Online Server**<br/>Microsoft 365 for the Web"]
end
subgraph "WopiHost Backend API"
WopiHost["**WopiHost**<br/>Host Application"]
Core["**WopiHost.Core**<br/>Controllers & Implementation"]
subgraph "Core Libraries"
Abstractions["**WopiHost.Abstractions**<br/>Core Interfaces"]
Discovery["**WopiHost.Discovery**<br/>Client Capabilities"]
Url["**WopiHost.Url**<br/>URL Generation"]
end
subgraph "Providers"
FileSystem["**WopiHost.FileSystemProvider**<br/>File System Storage"]
MemoryLock["**WopiHost.MemoryLockProvider**<br/>In-Memory Locking"]
CustomStorage["**Custom Storage**<br/>Cloud, Database, etc."]
CustomLock["**Custom Locking**<br/>Distributed Locking"]
end
end
%% Sample apps embed WOPI client
SampleApps --> OOS
%% WOPI client depends on WopiHost backend
OOS --> WopiHost
%% WopiHost host app uses Core implementation
WopiHost --> Core
%% Core dependencies
Core --> Abstractions
Core --> Discovery
%% Library dependencies
Discovery --> Abstractions
Url --> Discovery
Url --> Abstractions
%% Provider implementations
FileSystem --> Abstractions
MemoryLock --> Abstractions
CustomStorage --> Abstractions
CustomLock --> Abstractions
%% Core uses providers
Core --> FileSystem
Core --> MemoryLock
Core --> CustomStorage
Core --> CustomLock
%% Styling
classDef sampleApp fill:#e1f5fe,stroke:#01579b,stroke-width:2px
classDef wopiClient fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef hostApp fill:#f3e5f5,stroke:#4a148c,stroke-width:2px
classDef coreModule fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px
classDef libraryModule fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px
classDef providerModule fill:#fce4ec,stroke:#880e4f,stroke-width:2px
class SampleApps sampleApp
class OOS wopiClient
class WopiHost hostApp
class Core coreModule
class Abstractions,Discovery,Url libraryModule
class FileSystem,MemoryLock,CustomStorage,CustomLock providerModule
-
Sample Applications: The
/samplefolder contains complete applications that embed the WOPI client:- WopiHost.Web: A web application with file management UI that embeds Office Online Server
- WopiHost.Validator: A testing tool for WOPI protocol validation
- WopiHost Sample: A basic WOPI host implementation
-
WOPI Client Integration: The sample applications embed Office Online Server or Microsoft 365 for the Web as a WOPI client component.
-
WopiHost Backend API: The WOPI client depends on the WopiHost backend API (NuGet packages) to serve files:
- WopiHost.Core: Implements the WOPI REST API endpoints, handles authentication, authorization, and orchestrates all operations
- WopiHost.Abstractions: Defines the core interfaces for storage, security, and locking functionality
- WopiHost.Discovery: Queries the WOPI client to understand its capabilities
- WopiHost.Url: Generates proper WOPI URLs based on discovered capabilities
-
Storage & Lock Providers: The WOPI client uses these providers to access and manage files:
- WopiHost.FileSystemProvider: File system storage implementation
- WopiHost.MemoryLockProvider: In-memory locking implementation
- Custom Providers: You can implement your own storage and locking providers
-
Your Own Applications: You can create your own applications by embedding the WOPI client and referencing the WopiHost NuGet packages.
This modular design allows you to:
- Use the sample applications as starting points for your own WOPI-enabled applications
- Embed the WOPI client in your own applications
- Reference individual WopiHost packages to customize the backend API
- Implement custom providers for your specific storage or infrastructure needs
- Test easily with the included validator and sample implementations
- Modular Architecture: Complete separation of concerns with 6 dedicated NuGet packages (Abstractions, Core, Discovery, Url, FileSystemProvider, MemoryLockProvider) allowing selective integration
- WOPI Discovery Integration: Dynamic capability detection that queries Office Online Server to determine supported file types and actions, with intelligent URL template resolution and caching
- Advanced Cobalt Support: Optional MS-FSSHTTP protocol integration for enhanced performance and compatibility with Office Web Apps 2013+ features
- Flexible Storage Abstraction: Complete decoupling from file system with clean interfaces supporting any storage backend (cloud, database, custom APIs) through
IWopiStorageProvider - .NET Aspire Integration: Modern cloud-native development experience with service orchestration, OpenTelemetry observability, and containerization support
- Comprehensive WOPI Compliance: Full implementation of the current WOPI specification including file operations, container operations (basic), and ecosystem support (basic)
- Enterprise-Ready Security: Built-in WOPI proof validation, origin checking, and extensible authentication/authorization with JWT token support
- Production-Ready Features: Health checks, in-memory caching, and sample applications for testing and validation
- .NET 8 SDK, .NET 9 SDK, or .NET 10 SDK
- Recommended: VS Code or Visual Studio 2022
The WopiHost app targets net8.0, net9.0, and net10.0.
If you need a version that targets an older version of .NET, check out the releases:
If you get errors saying that Microsoft.CobaltCore.*.nupkg can't be found, then just remove the reference or see the chapter Cobalt below.
This project includes a .NET Aspire orchestration for easy development and deployment. .NET Aspire provides a comprehensive developer experience for building cloud-native applications with .NET.
- .NET 10 SDK (required for the AppHost project)
- Docker Desktop (for containerization support)
- Recommended: Visual Studio 2022 with the .NET Aspire workload, or VS Code with the C# Dev Kit extension
-
Clone the repository:
git clone https://github.com/petrsvihlik/WopiHost.git cd WopiHost -
Run the Aspire AppHost:
dotnet run --project infra/WopiHost.AppHost
This will start all three components of the application:
- WopiHost (Backend service) -
http://localhost:5000- API endpoints for WOPI operations
- Swagger UI available at
/scalar
- WopiHost.Web (Frontend) -
http://localhost:6000(HTTP) /https://localhost:6001(HTTPS)- Web interface for file management and WOPI client integration
- WopiHost.Validator (Testing tool) -
http://localhost:7000- WOPI protocol validation and testing interface
- WopiHost (Backend service) -
-
Access the Aspire Dashboard: When you run the AppHost, .NET Aspire will automatically open the Aspire dashboard in your browser. The dashboard provides:
- Real-time application status and health monitoring
- Structured logging and trace visualization
- Resource management and configuration
- Inter-service communication monitoring
Using .NET Aspire with WopiHost provides several advantages:
- Service Orchestration: Automatically manages dependencies between WopiHost, Web frontend, and Validator
- Configuration Management: Centralized configuration through the AppHost
- Observability: Built-in logging, metrics, and distributed tracing
- Development Experience: Simplified local development with automatic service discovery
- Production Ready: Easy deployment to cloud environments with container support
The Aspire configuration can be customized in infra/WopiHost.AppHost/Program.cs. The current setup includes:
- Service references and dependencies
- Port assignments for each service
- External endpoint configuration for web access
- Health monitoring and readiness checks
You can also customize application settings through:
infra/WopiHost.AppHost/appsettings.jsoninfra/WopiHost.AppHost/appsettings.Development.json
If you prefer to run the projects individually without Aspire:
# Terminal 1 - Backend
dotnet run --project sample/WopiHost
# Terminal 2 - Frontend
dotnet run --project sample/WopiHost.Web
# Terminal 3 - Validator (optional)
dotnet run --project sample/WopiHost.ValidatorThe .NET Aspire orchestration (described above) is the recommended approach for development and modern cloud-native deployments. It provides the best developer experience with automatic service discovery, configuration management, and observability.
For production deployments on Windows Server with IIS:
-
Publish the application:
dotnet publish sample/WopiHost -c Release -o ./publish
-
Create web.config for IIS:
<?xml version="1.0" encoding="utf-8"?> <configuration> <location path="." inheritInChildApplications="false"> <system.webServer> <handlers> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" /> </handlers> <aspNetCore processPath="dotnet" arguments=".\WopiHost.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" /> </system.webServer> </location> </configuration>
-
Configure IIS:
- Create a new Application Pool targeting .NET CLR Version "No Managed Code"
- Create a new website pointing to the published folder
- Ensure the Application Pool identity has read/execute permissions
- Install the ASP.NET Core Hosting Bundle on the server
-
Configure WOPI settings in
appsettings.jsonfor your production environment:{ "Wopi": { "ClientUrl": "https://your-office-online-server.com", "StorageProviderAssemblyName": "WopiHost.FileSystemProvider", "StorageProvider": { "RootPath": "C:\\WopiHost\\Documents" }, "LockProviderAssemblyName": "WopiHost.MemoryLockProvider" } }
To enable HTTPS for production deployments:
-
Configure SSL certificates in your hosting environment
-
Update appsettings.json:
{ "Kestrel": { "Endpoints": { "Https": { "Url": "https://localhost:5001", "Certificate": { "Path": "path/to/certificate.pfx", "Password": "certificate-password" } } } } } -
Enable HTTPS redirection in Program.cs:
// Uncomment this line in your Program.cs app.UseHttpsRedirection();
-
For IIS with HTTPS:
- Configure SSL binding in IIS Manager
- Ensure the certificate is properly installed and trusted
- Update WOPI client URLs to use HTTPS
For development and testing:
# Set environment variables
export ASPNETCORE_ENVIRONMENT=Development
export ASPNETCORE_URLS=http://localhost:5000
# Run the application
dotnet run --project sample/WopiHostTroubleshooting dotnet run:
- Ensure all configuration files are present in the project directory
- Check that
appsettings.jsoncontains valid WOPI configuration - Use
--verbosity detailedfor detailed error information:dotnet run --project sample/WopiHost --verbosity detailed
- Verify the WOPI client URL is accessible and properly configured
- Check that the storage provider path exists and is accessible
For containerized deployments:
-
Create a Dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /src COPY ["sample/WopiHost/WopiHost.csproj", "sample/WopiHost/"] RUN dotnet restore "sample/WopiHost/WopiHost.csproj" COPY . . WORKDIR "/src/sample/WopiHost" RUN dotnet build "WopiHost.csproj" -c Release -o /app/build FROM build AS publish RUN dotnet publish "WopiHost.csproj" -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "WopiHost.dll"]
-
Build and run:
docker build -t wopihost . docker run -p 5000:80 wopihost
See Samples for all samples.
Running the application only makes sense with a WOPI client as its counterpart. WopiHost is compatible with the following clients:
Note that WopiHost will always be compatible only with the latest version of OOS because Microsoft also supports only the latest version.
The deployment of OOS/OWA requires the server to be part of a domain. If your server is not part of any domain (e.g. you're running it in a VM sandbox) it can be overcome by promoting your machine to a Domain Controller.
To test your OWA server follow the instructions here.
To remove the OWA instance use Remove-OfficeWebAppsMachine.
You can use WopiHost to integrate with Microsoft 365 for the web which will require:
- onboarding - apply for CSPP
- extending the provided interfaces to support the required features by Microsoft; we provide a sample implementation of the interfaces that pass the interactive WOPI-Validator tests
- Test Microsoft 365 for the web integration
In the past (in Office Web Apps 2013), some HTTP actions required the support of MS-FSSHTTP protocol (also known as "cobalt"). This is no longer true with Office Online Server 2016. However, if the WOPI client discovers (via SupportsCobalt property) that the WOPI host supports cobalt, it'll take advantage of it as it's more efficient.
If you need or want your project to use Cobalt, you'll need to create a NuGet package called Microsoft.CobaltCore.nupkg containing Microsoft.CobaltCore.dll. This DLL is part of Office Web Apps 2013 / Office Online Server 2016, and its license doesn't allow public distribution and therefore, it's not part of this repository. Please always make sure your OWA/OOS server and the user connecting to it have valid licenses before you start using it.
TODO
WopiHost is designed with extensibility in mind. Each NuGet package provides specific interfaces and implementations that you can extend or replace to meet your requirements.
- WopiHost.Abstractions - Core interfaces for storage, security, and locking
- WopiHost.FileSystemProvider - File system-based storage implementation with examples for cloud storage, database integration, and document management systems
- WopiHost.MemoryLockProvider - In-memory locking for single-instance deployments
- WopiHost.Abstractions -
IWopiLockProviderinterface for custom distributed locking implementations
- WopiHost.Core - WOPI server implementation with extensible controllers, middleware, and security handlers
- WopiHost.Discovery - WOPI client capability discovery with custom provider support
- WopiHost.Url - URL generation and template resolution
// Implement IWopiStorageProvider for your cloud storage
public class AzureBlobStorageProvider : IWopiStorageProvider, IWopiWritableStorageProvider
{
// See WopiHost.Abstractions README for complete implementation
}// Implement IWopiSecurityHandler for your authentication system
public class CustomSecurityHandler : IWopiSecurityHandler
{
// See WopiHost.Abstractions README for complete implementation
}// Implement IWopiLockProvider for distributed locking
public class RedisLockProvider : IWopiLockProvider
{
// See WopiHost.Abstractions README for complete implementation
}Customize WOPI responses by registering for events in your WopiHostOptions:
builder.Services.Configure<WopiHostOptions>(options =>
{
options.OnCheckFileInfo = async context =>
{
var fileInfo = await GetDefaultFileInfo(context);
// Add custom properties
fileInfo.CustomProperty = "CustomValue";
return fileInfo;
};
options.OnCheckContainerInfo = async context =>
{
var containerInfo = await GetDefaultContainerInfo(context);
// Add custom security properties
containerInfo.CustomSecurityProperty = "CustomSecurityValue";
return containerInfo;
};
});Each WopiHost package includes comprehensive documentation with:
- Hero scenarios showing real-world usage patterns
- API reference with complete interface documentation
- Configuration examples for various deployment scenarios
- Integration patterns for enterprise systems
- Performance considerations and best practices
๐ View all package documentation โ
| Extension Type | Package | Documentation | Key Interfaces |
|---|---|---|---|
| Storage | WopiHost.Abstractions | Core storage interfaces | IWopiStorageProvider, IWopiWritableStorageProvider |
| File System | WopiHost.FileSystemProvider | File system implementation | WopiFileSystemProvider, WopiSecurityHandler |
| Locking | WopiHost.MemoryLockProvider | In-memory locking | IWopiLockProvider, MemoryLockProvider |
| Core Server | WopiHost.Core | WOPI server implementation | Controllers, middleware, security |
| Discovery | WopiHost.Discovery | Client capability discovery | IDiscoverer, IDiscoveryFileProvider |
| URL Generation | WopiHost.Url | WOPI URL generation | WopiUrlBuilder, WopiUrlSettings |
| Cobalt Protocol | WopiHost.Cobalt | MS-FSSHTTP support | ICobaltSessionManager, CobaltSession |
| Use Case | Recommended Packages | Documentation |
|---|---|---|
| Cloud Storage Integration | Abstractions + Custom Implementation | Storage Examples |
| Database-Backed Documents | Abstractions + Custom Implementation | Database Examples |
| Enterprise Security | Core + Custom Security Handler | Security Examples |
| Distributed Locking | Abstractions + Custom Lock Provider | Lock Examples |
| Multi-Tenant Host | Core + Custom Providers | Multi-Tenant Examples |
| High-Performance Editing | Cobalt + Core | Cobalt Examples |
| Local Development | FileSystemProvider + MemoryLockProvider | Quick Start |
| Pattern | Description | Packages | Examples |
|---|---|---|---|
| Custom Storage | Implement your own storage backend | Abstractions | Cloud Storage, Database Storage |
| Custom Security | Implement your own authentication/authorization | Abstractions, Core | Security Handler, Authorization |
| Custom Locking | Implement distributed or custom locking | Abstractions | Distributed Locking |
| Custom Discovery | Implement custom WOPI discovery | Discovery | Custom Provider |
| Custom URL Generation | Implement custom URL templates | Url | URL Builder |
| Custom Controllers | Extend or replace WOPI controllers | Core | Custom Controllers |
| Custom Middleware | Add custom middleware to WOPI pipeline | Core | Custom Middleware |
There is plenty of space for improvements in the overall architecture, implementation of the [MS-*] protocols, or just finishing the TODOs in the code. A lot of refactoring still needs to be done and also the code style has to be unified. So please feel free to help me out with it :)
- Check out open issues
https://learn.microsoft.com/dotnet/standard/design-guidelines/
- LICENSE.txt - License for my part of the project
- ORIGINAL_WORK_LICENSE.txt - License for Marx Yu's part of the project. This project is based on Marx Yu's project.
- NOTICE.txt - additional notes to how the licenses are applied
- Official WOPI Documentation
- Official WOPI REST API Reference
- WOPI Host and url paths
- Office Online integration via WOPI Host by Richard diZerega + video

