Skip to content

The most advanced .NET implementation of the WOPI protocol. Enables integration with WOPI clients such as Office Online Server.

License

Notifications You must be signed in to change notification settings

petrsvihlik/WopiHost

Repository files navigation

Logo WopiHost

Build & Test codecov Code Coverage Maintainability Maintainability CodeFactor FOSSA Status .NET Core

Package Version Downloads
WopiHost.Abstractions NuGet NuGet
WopiHost.Core NuGet NuGet
WopiHost.Discovery NuGet NuGet
WopiHost.FileSystemProvider NuGet NuGet
WopiHost.MemoryLockProvider NuGet NuGet
WopiHost.Url NuGet NuGet

Introduction

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.

Architecture

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
Loading

How It Works

  1. Sample Applications: The /sample folder 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
  2. WOPI Client Integration: The sample applications embed Office Online Server or Microsoft 365 for the Web as a WOPI client component.

  3. 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
  4. 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
  5. 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

Key Differentiators

  • 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

Usage

Prerequisites

Building the app

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.

Running with .NET Aspire

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.

Prerequisites for .NET Aspire

Running the application with .NET Aspire

  1. Clone the repository:

    git clone https://github.com/petrsvihlik/WopiHost.git
    cd WopiHost
  2. 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
  3. 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

image

Aspire Benefits

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

Configuration

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.json
  • infra/WopiHost.AppHost/appsettings.Development.json

Alternative: Running individual projects

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.Validator

Hosting Options

.NET Aspire (Recommended)

The .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.

Alternative Hosting Methods

IIS Hosting

For production deployments on Windows Server with IIS:

  1. Publish the application:

    dotnet publish sample/WopiHost -c Release -o ./publish
  2. 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>
  3. 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
  4. Configure WOPI settings in appsettings.json for your production environment:

    {
      "Wopi": {
        "ClientUrl": "https://your-office-online-server.com",
        "StorageProviderAssemblyName": "WopiHost.FileSystemProvider",
        "StorageProvider": {
          "RootPath": "C:\\WopiHost\\Documents"
        },
        "LockProviderAssemblyName": "WopiHost.MemoryLockProvider"
      }
    }

HTTPS Configuration

To enable HTTPS for production deployments:

  1. Configure SSL certificates in your hosting environment

  2. Update appsettings.json:

    {
      "Kestrel": {
        "Endpoints": {
          "Https": {
            "Url": "https://localhost:5001",
            "Certificate": {
              "Path": "path/to/certificate.pfx",
              "Password": "certificate-password"
            }
          }
        }
      }
    }
  3. Enable HTTPS redirection in Program.cs:

    // Uncomment this line in your Program.cs
    app.UseHttpsRedirection();
  4. 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

Command Line (dotnet run)

For development and testing:

# Set environment variables
export ASPNETCORE_ENVIRONMENT=Development
export ASPNETCORE_URLS=http://localhost:5000

# Run the application
dotnet run --project sample/WopiHost

Troubleshooting dotnet run:

  • Ensure all configuration files are present in the project directory
  • Check that appsettings.json contains valid WOPI configuration
  • Use --verbosity detailed for 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

Docker Hosting

For containerized deployments:

  1. 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"]
  2. Build and run:

    docker build -t wopihost .
    docker run -p 5000:80 wopihost

Samples

See Samples for all samples.

Compatible WOPI Clients

Running the application only makes sense with a WOPI client as its counterpart. WopiHost is compatible with the following clients:

Office Online Server 2016

deployment guidelines

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.

Microsoft 365 for the Web

You can use WopiHost to integrate with Microsoft 365 for the web which will require:

Cobalt

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.

Using in your web project

TODO

Extending WopiHost

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.

Core Extension Points

Storage Providers

Lock Management

Core Functionality

  • 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

Quick Start Examples

Custom Cloud Storage

// Implement IWopiStorageProvider for your cloud storage
public class AzureBlobStorageProvider : IWopiStorageProvider, IWopiWritableStorageProvider
{
    // See WopiHost.Abstractions README for complete implementation
}

Custom Security Handler

// Implement IWopiSecurityHandler for your authentication system
public class CustomSecurityHandler : IWopiSecurityHandler
{
    // See WopiHost.Abstractions README for complete implementation
}

Custom Lock Provider

// Implement IWopiLockProvider for distributed locking
public class RedisLockProvider : IWopiLockProvider
{
    // See WopiHost.Abstractions README for complete implementation
}

Advanced Customization

CheckFileInfo & CheckContainerInfo Events

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;
    };
});

Package-Specific Documentation

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 โ†’

Extending Documentation Index

By Extension Type

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

By Use Case

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

By Integration Pattern

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

Known issues / TODOs

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 :)

Contributing

https://learn.microsoft.com/dotnet/standard/design-guidelines/

License

Useful resources

Building WOPI Host

MS-FSSHTTP (Cobalt)

Building WOPI Client

FOSSA Status

About

The most advanced .NET implementation of the WOPI protocol. Enables integration with WOPI clients such as Office Online Server.

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Sponsor this project

  •  

Contributors 10

Languages