I-Synergy.Framework.AspNetCore.MultiTenancy 2025.11211.11307-preview

Prefix Reserved
This is a prerelease version of I-Synergy.Framework.AspNetCore.MultiTenancy.
There is a newer version of this package available.
See the version list below for details.
dotnet add package I-Synergy.Framework.AspNetCore.MultiTenancy --version 2025.11211.11307-preview
                    
NuGet\Install-Package I-Synergy.Framework.AspNetCore.MultiTenancy -Version 2025.11211.11307-preview
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="I-Synergy.Framework.AspNetCore.MultiTenancy" Version="2025.11211.11307-preview" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="I-Synergy.Framework.AspNetCore.MultiTenancy" Version="2025.11211.11307-preview" />
                    
Directory.Packages.props
<PackageReference Include="I-Synergy.Framework.AspNetCore.MultiTenancy" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add I-Synergy.Framework.AspNetCore.MultiTenancy --version 2025.11211.11307-preview
                    
#r "nuget: I-Synergy.Framework.AspNetCore.MultiTenancy, 2025.11211.11307-preview"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package I-Synergy.Framework.AspNetCore.MultiTenancy@2025.11211.11307-preview
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=I-Synergy.Framework.AspNetCore.MultiTenancy&version=2025.11211.11307-preview&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=I-Synergy.Framework.AspNetCore.MultiTenancy&version=2025.11211.11307-preview&prerelease
                    
Install as a Cake Tool

I-Synergy Framework AspNetCore Multi-Tenancy

Multi-tenant architecture support for ASP.NET Core applications. This package provides tenant resolution from HTTP context, tenant service for managing tenant-specific operations, and integration with OpenIddict claims for secure multi-tenant applications.

NuGet License .NET

Features

  • Tenant resolution from HTTP context and claims
  • Tenant service for accessing current tenant information
  • OpenIddict claims integration for secure tenant identification
  • HttpContext accessor for tenant management across request scope
  • User and tenant isolation with automatic group assignment
  • Programmatic tenant setting for testing and background jobs
  • Thread-safe tenant access throughout the application
  • Support for client roles in multi-tenant scenarios

Installation

Install the package via NuGet:

dotnet add package I-Synergy.Framework.AspNetCore.MultiTenancy

Quick Start

1. Configure Multi-Tenancy Services

In your Program.cs:

using ISynergy.Framework.AspNetCore.MultiTenancy.Extensions;

var builder = WebApplication.CreateBuilder(args);

// Add multi-tenancy support
builder.Services.AddMultiTenancyIntegration();

builder.Services.AddControllers();

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();
app.Run();

2. Using the Tenant Service

Access tenant information in your controllers and services:

using ISynergy.Framework.Core.Abstractions.Services;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
[Authorize]
public class OrdersController : ControllerBase
{
    private readonly ITenantService _tenantService;
    private readonly IOrderRepository _orderRepository;

    public OrdersController(
        ITenantService tenantService,
        IOrderRepository orderRepository)
    {
        _tenantService = tenantService;
        _orderRepository = orderRepository;
    }

    [HttpGet]
    public async Task<IActionResult> GetOrders()
    {
        // Automatically filter by current tenant
        var tenantId = _tenantService.TenantId;
        var orders = await _orderRepository.GetByTenantAsync(tenantId);

        return Ok(orders);
    }

    [HttpPost]
    public async Task<IActionResult> CreateOrder([FromBody] CreateOrderRequest request)
    {
        var order = new Order
        {
            TenantId = _tenantService.TenantId,
            CreatedBy = _tenantService.UserName,
            // ... other properties
        };

        await _orderRepository.CreateAsync(order);

        return CreatedAtAction(nameof(GetOrder), new { id = order.Id }, order);
    }

    [HttpGet("{id}")]
    public async Task<IActionResult> GetOrder(int id)
    {
        var order = await _orderRepository.GetByIdAsync(id);

        // Verify tenant ownership
        if (order == null || order.TenantId != _tenantService.TenantId)
            return NotFound();

        return Ok(order);
    }
}

3. Setting Tenant Programmatically

For testing or background jobs, set the tenant context manually:

using ISynergy.Framework.Core.Abstractions.Services;

public class BackgroundJobService
{
    private readonly ITenantService _tenantService;

    public BackgroundJobService(ITenantService tenantService)
    {
        _tenantService = tenantService;
    }

    public async Task ProcessTenantDataAsync(Guid tenantId, string username)
    {
        // Set tenant context for this operation
        _tenantService.SetTenant(tenantId, username);

        // Now all operations will use this tenant context
        await ProcessDataAsync();
    }

    public async Task ProcessWithMinimalContextAsync(Guid tenantId)
    {
        // Set only tenant ID (no username)
        _tenantService.SetTenant(tenantId);

        await ProcessDataAsync();
    }
}

Core Components

Services

ISynergy.Framework.AspNetCore.MultiTenancy.Services/
└── TenantService                 # Tenant resolution and management

Extensions

ISynergy.Framework.AspNetCore.MultiTenancy.Extensions/
├── ServiceCollectionExtensions   # DI configuration
└── HostApplicationBuilderExtensions  # Builder configuration

Advanced Features

Tenant-Aware Entity Framework

Automatically filter queries by tenant:

using ISynergy.Framework.Core.Abstractions.Services;
using Microsoft.EntityFrameworkCore;

public class ApplicationDbContext : DbContext
{
    private readonly ITenantService _tenantService;

    public ApplicationDbContext(
        DbContextOptions<ApplicationDbContext> options,
        ITenantService tenantService)
        : base(options)
    {
        _tenantService = tenantService;
    }

    public DbSet<Order> Orders { get; set; }
    public DbSet<Product> Products { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // Add global query filter for multi-tenancy
        modelBuilder.Entity<Order>()
            .HasQueryFilter(e => e.TenantId == _tenantService.TenantId);

        modelBuilder.Entity<Product>()
            .HasQueryFilter(e => e.TenantId == _tenantService.TenantId);
    }

    public override int SaveChanges()
    {
        ApplyTenantId();
        return base.SaveChanges();
    }

    public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        ApplyTenantId();
        return await base.SaveChangesAsync(cancellationToken);
    }

    private void ApplyTenantId()
    {
        var tenantId = _tenantService.TenantId;

        foreach (var entry in ChangeTracker.Entries<ITenantEntity>())
        {
            if (entry.State == EntityState.Added)
            {
                entry.Entity.TenantId = tenantId;
            }
        }
    }
}

// Tenant entity interface
public interface ITenantEntity
{
    Guid TenantId { get; set; }
}

// Example entity
public class Order : ITenantEntity
{
    public int Id { get; set; }
    public Guid TenantId { get; set; }
    public string OrderNumber { get; set; }
    public decimal Amount { get; set; }
}

Tenant Resolution Middleware

Create custom middleware for tenant resolution:

using ISynergy.Framework.Core.Abstractions.Services;

public class TenantResolutionMiddleware
{
    private readonly RequestDelegate _next;

    public TenantResolutionMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context, ITenantService tenantService)
    {
        // Option 1: From subdomain
        var host = context.Request.Host.Host;
        var subdomain = host.Split('.').FirstOrDefault();

        if (!string.IsNullOrEmpty(subdomain) && subdomain != "www")
        {
            var tenantId = await ResolveTenantFromSubdomainAsync(subdomain);
            if (tenantId.HasValue)
            {
                tenantService.SetTenant(tenantId.Value);
            }
        }

        // Option 2: From custom header
        if (context.Request.Headers.TryGetValue("X-Tenant-ID", out var tenantHeader))
        {
            if (Guid.TryParse(tenantHeader, out var tenantId))
            {
                tenantService.SetTenant(tenantId);
            }
        }

        // Option 3: Already set from claims by the framework
        // No action needed - TenantService reads from User claims

        await _next(context);
    }

    private async Task<Guid?> ResolveTenantFromSubdomainAsync(string subdomain)
    {
        // Lookup tenant by subdomain
        // Return tenant ID or null
        return Guid.Empty; // Placeholder
    }
}

// Register middleware
app.UseMiddleware<TenantResolutionMiddleware>();

Tenant-Specific Configuration

Manage tenant-specific settings:

using ISynergy.Framework.Core.Abstractions.Services;

public class TenantConfigurationService
{
    private readonly ITenantService _tenantService;
    private readonly IConfiguration _configuration;

    public TenantConfigurationService(
        ITenantService tenantService,
        IConfiguration configuration)
    {
        _tenantService = tenantService;
        _configuration = configuration;
    }

    public string GetTenantSetting(string key)
    {
        var tenantId = _tenantService.TenantId;
        var tenantKey = $"Tenants:{tenantId}:{key}";

        return _configuration[tenantKey] ?? _configuration[key];
    }

    public T GetTenantSetting<T>(string key, T defaultValue = default)
    {
        var value = GetTenantSetting(key);

        if (string.IsNullOrEmpty(value))
            return defaultValue;

        return (T)Convert.ChangeType(value, typeof(T));
    }
}

// appsettings.json
{
  "Tenants": {
    "123e4567-e89b-12d3-a456-426614174000": {
      "MaxUsers": 100,
      "StorageQuotaGB": 50,
      "Features": ["AdvancedReporting", "API"]
    },
    "987fcdeb-51a2-43f1-9876-543210fedcba": {
      "MaxUsers": 10,
      "StorageQuotaGB": 5,
      "Features": ["BasicReporting"]
    }
  }
}

Tenant Isolation Validation

Ensure tenant isolation in critical operations:

using ISynergy.Framework.Core.Abstractions.Services;

public class TenantIsolationValidator
{
    private readonly ITenantService _tenantService;

    public TenantIsolationValidator(ITenantService tenantService)
    {
        _tenantService = tenantService;
    }

    public void ValidateTenantAccess<T>(T entity) where T : ITenantEntity
    {
        if (entity.TenantId != _tenantService.TenantId)
        {
            throw new UnauthorizedAccessException(
                $"Access denied. Entity belongs to different tenant.");
        }
    }

    public void ValidateTenantAccess(Guid tenantId)
    {
        if (tenantId != _tenantService.TenantId)
        {
            throw new UnauthorizedAccessException(
                $"Access denied. Operation for different tenant.");
        }
    }
}

// Usage in service
public class OrderService
{
    private readonly ITenantService _tenantService;
    private readonly TenantIsolationValidator _validator;
    private readonly IOrderRepository _repository;

    public OrderService(
        ITenantService tenantService,
        TenantIsolationValidator validator,
        IOrderRepository repository)
    {
        _tenantService = tenantService;
        _validator = validator;
        _repository = repository;
    }

    public async Task DeleteOrderAsync(int orderId)
    {
        var order = await _repository.GetByIdAsync(orderId);

        if (order == null)
            throw new NotFoundException("Order not found");

        // Validate tenant isolation
        _validator.ValidateTenantAccess(order);

        await _repository.DeleteAsync(order);
    }
}

Usage Examples

Multi-Tenant SaaS Application

Complete example of a multi-tenant SaaS application:

using ISynergy.Framework.AspNetCore.MultiTenancy.Extensions;
using ISynergy.Framework.Core.Abstractions.Services;

var builder = WebApplication.CreateBuilder(args);

// Add multi-tenancy
builder.Services.AddMultiTenancyIntegration();

// Add authentication with OpenIddict
builder.Services.AddAuthentication("OpenIddict.Validation.AspNetCore")
    .AddOpenIddictValidation(options =>
    {
        options.SetIssuer("https://auth.example.com");
    });

builder.Services.AddControllers();

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();
app.Run();

// Customer Controller
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class CustomersController : ControllerBase
{
    private readonly ITenantService _tenantService;
    private readonly ICustomerRepository _customerRepository;

    public CustomersController(
        ITenantService tenantService,
        ICustomerRepository customerRepository)
    {
        _tenantService = tenantService;
        _customerRepository = customerRepository;
    }

    [HttpGet]
    public async Task<IActionResult> GetCustomers()
    {
        // Automatically scoped to current tenant
        var customers = await _customerRepository
            .GetAllAsync(_tenantService.TenantId);

        return Ok(customers);
    }

    [HttpPost]
    public async Task<IActionResult> CreateCustomer([FromBody] CreateCustomerRequest request)
    {
        var customer = new Customer
        {
            TenantId = _tenantService.TenantId,
            Name = request.Name,
            Email = request.Email,
            CreatedBy = _tenantService.UserName,
            CreatedAt = DateTime.UtcNow
        };

        await _customerRepository.CreateAsync(customer);

        return CreatedAtAction(nameof(GetCustomer), new { id = customer.Id }, customer);
    }

    [HttpGet("{id}")]
    public async Task<IActionResult> GetCustomer(int id)
    {
        var customer = await _customerRepository.GetByIdAsync(id);

        // Verify tenant ownership
        if (customer == null || customer.TenantId != _tenantService.TenantId)
            return NotFound();

        return Ok(customer);
    }

    [HttpPut("{id}")]
    public async Task<IActionResult> UpdateCustomer(int id, [FromBody] UpdateCustomerRequest request)
    {
        var customer = await _customerRepository.GetByIdAsync(id);

        if (customer == null || customer.TenantId != _tenantService.TenantId)
            return NotFound();

        customer.Name = request.Name;
        customer.Email = request.Email;
        customer.UpdatedBy = _tenantService.UserName;
        customer.UpdatedAt = DateTime.UtcNow;

        await _customerRepository.UpdateAsync(customer);

        return Ok(customer);
    }

    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteCustomer(int id)
    {
        var customer = await _customerRepository.GetByIdAsync(id);

        if (customer == null || customer.TenantId != _tenantService.TenantId)
            return NotFound();

        await _customerRepository.DeleteAsync(customer);

        return NoContent();
    }
}

Background Job with Tenant Context

Process tenant-specific background jobs:

using ISynergy.Framework.Core.Abstractions.Services;

public class TenantReportGenerator
{
    private readonly ITenantService _tenantService;
    private readonly IReportService _reportService;
    private readonly IEmailService _emailService;

    public TenantReportGenerator(
        ITenantService tenantService,
        IReportService reportService,
        IEmailService emailService)
    {
        _tenantService = tenantService;
        _reportService = reportService;
        _emailService = emailService;
    }

    public async Task GenerateMonthlyReportsAsync()
    {
        var tenants = await GetAllTenantsAsync();

        foreach (var tenant in tenants)
        {
            // Set tenant context for this iteration
            _tenantService.SetTenant(tenant.Id, "system");

            try
            {
                // Generate report (automatically scoped to tenant)
                var report = await _reportService.GenerateMonthlyReportAsync();

                // Send email to tenant administrators
                await _emailService.SendReportAsync(tenant.AdminEmail, report);
            }
            catch (Exception ex)
            {
                // Log error for this tenant
                Console.WriteLine($"Error generating report for tenant {tenant.Id}: {ex.Message}");
            }
        }
    }
}

Integration Testing with Tenant Context

Test multi-tenant features:

using ISynergy.Framework.Core.Abstractions.Services;
using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;

public class CustomerControllerTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly WebApplicationFactory<Program> _factory;

    public CustomerControllerTests(WebApplicationFactory<Program> factory)
    {
        _factory = factory;
    }

    [Fact]
    public async Task GetCustomers_ReturnOnlyTenantCustomers()
    {
        // Arrange
        var tenant1Id = Guid.NewGuid();
        var tenant2Id = Guid.NewGuid();

        var client = _factory.CreateClient();

        // Seed data for two tenants
        await SeedCustomersAsync(tenant1Id, 5);
        await SeedCustomersAsync(tenant2Id, 3);

        // Act - Request with tenant1 context
        var response = await client.GetAsync($"/api/customers");

        // Assert
        response.EnsureSuccessStatusCode();
        var customers = await response.Content.ReadFromJsonAsync<List<Customer>>();

        Assert.Equal(5, customers.Count);
        Assert.All(customers, c => Assert.Equal(tenant1Id, c.TenantId));
    }

    [Fact]
    public async Task CreateCustomer_AssignCurrentTenant()
    {
        // Arrange
        var tenantId = Guid.NewGuid();
        var client = _factory.CreateClient();

        // Act
        var response = await client.PostAsJsonAsync("/api/customers", new
        {
            Name = "Test Customer",
            Email = "test@example.com"
        });

        // Assert
        response.EnsureSuccessStatusCode();
        var customer = await response.Content.ReadFromJsonAsync<Customer>();

        Assert.Equal(tenantId, customer.TenantId);
    }
}

Best Practices

Use global query filters in Entity Framework to automatically scope queries to the current tenant.

Always validate tenant ownership before modifying or deleting entities to prevent cross-tenant data access.

Set the tenant context early in the request pipeline (authentication/authorization middleware) for consistent behavior.

Tenant Resolution

  • Resolve tenant from claims when using authentication
  • Use subdomain or custom headers for public APIs
  • Set tenant context in middleware for consistency
  • Cache tenant information to avoid repeated lookups
  • Handle missing or invalid tenant gracefully
  • Log tenant context for audit trails

Data Isolation

  • Use global query filters in Entity Framework
  • Always validate tenant ownership before operations
  • Implement tenant checks in repository layer
  • Use database schemas or separate databases for strict isolation
  • Audit cross-tenant access attempts
  • Test tenant isolation thoroughly

Security

  • Never trust tenant ID from client input
  • Always validate tenant from authenticated claims
  • Implement role-based access within tenants
  • Monitor suspicious cross-tenant access patterns
  • Use separate connection strings for high-security tenants
  • Encrypt tenant-specific sensitive data

Performance

  • Cache tenant configuration and settings
  • Use indexes on TenantId columns
  • Consider database-per-tenant for large tenants
  • Implement tenant-aware caching strategies
  • Monitor query performance across tenants
  • Optimize global query filters

Testing

Example unit tests for multi-tenancy:

using ISynergy.Framework.Core.Abstractions.Services;
using Microsoft.AspNetCore.Http;
using Moq;
using System.Security.Claims;
using Xunit;

public class TenantServiceTests
{
    [Fact]
    public void TenantId_WithValidClaim_ReturnsTenantId()
    {
        // Arrange
        var tenantId = Guid.NewGuid();
        var claims = new[]
        {
            new Claim(Claims.KeyId, tenantId.ToString())
        };
        var identity = new ClaimsIdentity(claims);
        var principal = new ClaimsPrincipal(identity);

        var httpContext = new DefaultHttpContext
        {
            User = principal
        };

        var httpContextAccessor = new Mock<IHttpContextAccessor>();
        httpContextAccessor.Setup(a => a.HttpContext).Returns(httpContext);

        var tenantService = new TenantService(httpContextAccessor.Object);

        // Act
        var result = tenantService.TenantId;

        // Assert
        Assert.Equal(tenantId, result);
    }

    [Fact]
    public void SetTenant_SetsClaimsPrincipal()
    {
        // Arrange
        var tenantId = Guid.NewGuid();
        var username = "testuser";

        var httpContext = new DefaultHttpContext();
        var httpContextAccessor = new Mock<IHttpContextAccessor>();
        httpContextAccessor.Setup(a => a.HttpContext).Returns(httpContext);

        var tenantService = new TenantService(httpContextAccessor.Object);

        // Act
        tenantService.SetTenant(tenantId, username);

        // Assert
        Assert.Equal(tenantId.ToString(), httpContext.User.FindFirst(Claims.KeyId)?.Value);
        Assert.Equal(username, httpContext.User.FindFirst(Claims.Username)?.Value);
    }
}

Dependencies

  • Microsoft.AspNetCore.Http - HTTP context abstractions
  • OpenIddict.Abstractions - OAuth 2.0/OpenID Connect claims
  • ISynergy.Framework.Core - Core framework utilities

Documentation

For more information about the I-Synergy Framework:

  • I-Synergy.Framework.Core - Core framework components
  • I-Synergy.Framework.AspNetCore - Base ASP.NET Core integration
  • I-Synergy.Framework.AspNetCore.Authentication - Authentication utilities
  • I-Synergy.Framework.EntityFramework - Entity Framework with tenant support
  • I-Synergy.Framework.AspNetCore.Monitoring - SignalR monitoring with tenant isolation

Support

For issues, questions, or contributions, please visit the GitHub repository.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2026.10116.10015-preview 29 1/15/2026
2026.10110.10203 94 1/10/2026
2026.10110.10121-preview 81 1/10/2026
2026.10109.12335-preview 84 1/9/2026
2026.10105.11358-preview 80 1/5/2026
2026.10105.11229-preview 83 1/5/2026
2025.11231.11750-preview 81 12/31/2025
2025.11225.12213 192 12/25/2025
2025.11225.12003-preview 174 12/25/2025
2025.11218.11301 282 12/18/2025
2025.11218.10050-preview 260 12/18/2025
2025.11211.11307-preview 409 12/11/2025
2025.11211.11225-preview 411 12/11/2025
2025.11210.10145-preview 428 12/10/2025
2025.11209.11459 452 12/9/2025
2025.11209.11422-preview 434 12/9/2025
2025.11207.11553-preview 207 12/7/2025
2025.11204.11448-preview 187 12/4/2025
2025.11130.12248 433 11/30/2025
2025.11130.12134-preview 340 11/30/2025
2025.11130.11725-preview 354 11/30/2025
2025.11130.11553-preview 343 11/30/2025
2025.11130.11515-preview 344 11/30/2025
2025.11130.11420.59-preview 340 11/30/2025
2025.11130.11323.56-preview 244 11/30/2025
2025.11129.10227.14-preview 103 11/29/2025
2025.11120.10114 426 11/20/2025
2025.11119.12324.6-preview 396 11/19/2025
2025.11119.10110 427 11/19/2025
2025.11118.12340.33-preview 394 11/18/2025
2025.11117.12349.4-preview 381 11/17/2025
2025.11117.11937.47-preview 383 11/17/2025
2025.11113.11532.29-preview 284 11/13/2025
2025.11113.10128.57-preview 275 11/13/2025
2025.11110.10306.55-preview 222 11/10/2025
2025.11109.10018.48-preview 138 11/8/2025
2025.11108.10119.29-preview 109 11/8/2025
2025.11106.10037.1-preview 186 11/6/2025
2025.11105.10254.54-preview 191 11/5/2025
2025.11105.10141.16-preview 195 11/5/2025
2025.11104.12308.54-preview 186 11/4/2025
2025.11104.10144.47-preview 189 11/4/2025
2025.11102.12003.8-preview 186 11/2/2025
2025.11102.11228.52-preview 156 11/2/2025
2025.11102.10309.42-preview 136 11/2/2025
2025.11029.11433.38-preview 192 10/29/2025
2025.11029.10201.38-preview 185 10/29/2025
2025.11027.11947.55-preview 187 10/27/2025
2025.11022.12207.12-preview 174 10/22/2025
2025.11019.12053.37-preview 172 10/19/2025
2025.11016.11750.24-preview 170 10/16/2025
2025.11015.10219.44-preview 176 10/15/2025
2025.11014.10245.12-preview 173 10/14/2025
2025.11012.10130.11-preview 111 10/12/2025
2025.11010.10052.52-preview 172 10/9/2025
2025.11001.12118.13-preview 179 10/1/2025
2025.10925.10144.25-preview 188 9/25/2025
2025.10921.11353.29-preview 210 9/21/2025
2025.10913.11841.29-preview 155 9/13/2025
2025.10912.12351.59-preview 92 9/12/2025
2025.10912.10210.52-preview 175 9/12/2025
2025.10911.10131.43-preview 169 9/10/2025
2025.10910.12340.34-preview 189 9/10/2025
2025.10910.11327.15-preview 182 9/10/2025
2025.10910.11206.45-preview 179 9/10/2025
2025.10910.10230.58-preview 179 9/10/2025
2025.10908.12343.47-preview 185 9/8/2025
2025.10904.12337.35-preview 199 9/4/2025
2025.10904.12245.51-preview 200 9/4/2025
2025.10904.11425.5-preview 194 9/4/2025
2025.10904.10323.39-preview 196 9/4/2025
2025.10826.11425.3-preview 245 8/26/2025
2025.10825.12350.9-preview 194 8/25/2025
2025.10810.10248-preview 145 8/10/2025
2025.10809.10146.35-preview 180 8/9/2025
2025.10806.12031.49-preview 250 8/6/2025
2025.10806.11955.54-preview 232 8/6/2025
2025.10806.11433.24-preview 262 8/6/2025
2025.10709.10105.39-preview 190 7/8/2025
2025.10707.12320.3-preview 189 7/7/2025
2025.10706.11957.9-preview 189 7/6/2025
2025.10702.11752.47-preview 180 7/2/2025
2025.10702.11256.17-preview 178 7/2/2025
2025.10702.11119.10-preview 169 7/2/2025
2025.10702.10000.31-preview 186 7/1/2025
2025.10701.11524.1-preview 170 7/1/2025
2025.10701.11310.13-preview 172 7/1/2025
2025.10630.12022.58-preview 181 6/30/2025
2025.10612.12134.8-preview 341 6/12/2025
2025.10611.12313.53-preview 335 6/11/2025
2025.10603.10159.54-preview 197 6/3/2025
2025.10602.11908.9-preview 180 6/2/2025
2025.10601.10124.29-preview 141 5/31/2025
2025.10531.12235.29-preview 141 5/31/2025
2025.10530.10121.50-preview 189 5/29/2025
2025.10527.12202.4-preview 184 5/27/2025
2025.10526.12034.25-preview 187 5/26/2025
2025.10521.11828.30-preview 191 5/21/2025
2025.10520.11715.6-preview 184 5/20/2025
2025.10520.11515.16-preview 188 5/20/2025
2025.10518.12303.43-preview 182 5/18/2025
2025.10518.11257.36-preview 197 5/18/2025
2025.10517.12347.27-preview 182 5/17/2025
2025.10517.12003.6-preview 166 5/17/2025
2025.10516.11720.13-preview 204 5/16/2025
2025.10514.12334.2-preview 308 5/14/2025
2025.10514.10015.27-preview 270 5/13/2025
2025.10511.11032.32-preview 183 5/11/2025
2025.10413.11530 332 4/13/2025
2025.10413.11434.33-preview 232 4/13/2025
2025.10413.10205.50-preview 189 4/13/2025
2025.10412.11526.4-preview 164 4/12/2025
2025.10412.10141 220 4/12/2025
2025.10411.11811.23-preview 168 4/11/2025
2025.10411.11645.1-preview 174 4/11/2025
2025.10410.11458.35-preview 238 4/10/2025
2025.10405.10143.28-preview 123 4/5/2025
2025.10403.12208.1-preview 218 4/3/2025
2025.10403.11954.16-preview 215 4/3/2025
2025.10401.11908.24-preview 201 4/1/2025
2025.10401.11559.45-preview 204 4/1/2025
2025.10331.12215.59-preview 184 3/31/2025
2025.10331.12130.34-preview 196 3/31/2025
2025.10331.10056.40-preview 221 3/30/2025
2025.10328.10150.21-preview 165 3/28/2025
2025.10323.11359-preview 324 3/23/2025
2025.10320.11800 287 3/20/2025
2025.10320.11616.45-preview 206 3/20/2025
2025.10320.10000 267 3/19/2025
2025.10319.12311.26-preview 199 3/19/2025
2025.10319.12238.6-preview 191 3/19/2025
2025.10319.12057.59-preview 222 3/19/2025
2025.10318.10055 273 3/18/2025
2025.10317.11728.13-preview 196 3/17/2025
2025.10317.11201.3-preview 195 3/17/2025
2025.10315.11523.14-preview 136 3/15/2025
2025.10305.12342 371 3/5/2025
2025.10305.12321.9-preview 251 3/5/2025
2025.10301.12313 234 3/1/2025
2025.10301.12129.38-preview 158 3/1/2025
2025.10221.10043.29-preview 146 2/21/2025
2025.1051.1246 218 2/20/2025
2025.1051.44.54-preview 133 2/20/2025
2025.1044.1 226 2/13/2025
2025.1044.0.2-preview 110 2/13/2025
2025.1043.0.2-preview 129 2/12/2025
2025.1041.0.1-preview 156 2/10/2025
2025.1038.1 232 2/7/2025
2025.1038.0.1-preview 145 2/7/2025
2025.1035.1 234 2/4/2025
2025.1035.0.1-preview 143 2/4/2025
2025.1034.1 215 2/3/2025
2025.1034.0.1-preview 136 2/3/2025
2025.1033.0.5-preview 147 2/2/2025
2025.1033.0.3-preview 142 2/2/2025
2025.1033.0.2-preview 128 2/2/2025
2025.1033.0.1-preview 151 2/2/2025
2025.1025.1 272 1/25/2025
2025.1025.0.1-preview 117 1/25/2025
2025.1021.1 222 1/21/2025
2025.1021.0.1-preview 151 1/21/2025
2025.1020.1 204 1/20/2025
2025.1020.0.3-preview 130 1/20/2025
2025.1020.0.1-preview 137 1/20/2025
2025.1018.0.7-preview 124 1/18/2025
2025.1018.0.5-preview 155 1/18/2025
2025.1018.0.4-preview 131 1/18/2025
2025.1017.0.2-preview 131 1/17/2025
2025.1017.0.1-preview 131 1/17/2025
2025.1016.0.1-preview 125 1/16/2025
2025.1010.1 224 1/10/2025
2025.1010.0.1-preview 122 1/9/2025
2025.1009.0.3-preview 142 1/9/2025
2025.1007.1 234 1/7/2025
2025.1007.0.5-preview 168 1/7/2025
2025.1007.0.3-preview 134 1/7/2025
2025.1006.1 231 1/7/2025
2025.1005.1 243 1/5/2025
2025.1005.0.2-preview 119 1/5/2025
2025.1004.1 233 1/4/2025
2024.1366.1 219 12/31/2024
2024.1366.0.2-preview 166 12/31/2024
2024.1366.0.1-preview 154 12/31/2024
2024.1365.0.2-preview 152 12/30/2024
2024.1365.0.1-preview 134 12/30/2024
2024.1361.0.2-preview 146 12/26/2024
2024.1353.0.1-preview 136 12/18/2024
2024.1352.0.3-preview 171 12/17/2024
2024.1352.0.2-preview 176 12/17/2024
2024.1352.0.1-preview 140 12/17/2024
2024.1351.1 239 12/16/2024
2024.1351.0.3-preview 135 12/16/2024
2024.1350.1 229 12/15/2024
2024.1343.1 226 12/8/2024
2024.1339.1 223 12/4/2024
2024.1336.1 221 12/1/2024
2024.1332.1 240 11/27/2024
2024.1330.1 241 11/25/2024
2024.1328.1 226 11/23/2024
2024.1325.1 266 11/20/2024
2024.1323.1 259 11/18/2024
2024.1316.1 178 11/11/2024
2024.1307.1 188 11/2/2024
2024.1300.1 200 10/26/2024
2024.1294.1 205 10/20/2024
2024.1290.1 207 10/16/2024
2024.1283.1 242 10/8/2024
2024.1282.1 208 10/8/2024
2024.1278.1 229 10/4/2024
2024.1277.1 220 10/3/2024
2024.1275.2 245 10/1/2024
2024.1275.1 233 10/1/2024
2024.1274.1 212 9/30/2024
2024.1263.1 236 9/19/2024
2024.1261.1 295 9/17/2024
2024.1258.1 254 9/13/2024
2024.1257.1 230 9/13/2024
2024.1256.1 244 9/12/2024
2024.1254.1 235 9/10/2024
2024.1250.1 246 9/6/2024
2024.1249.1 240 9/5/2024
2024.1246.1 249 9/2/2024
2024.1245.1 223 9/1/2024
2024.1237.1 258 8/24/2024
2024.1235.0.1-preview 178 8/23/2024
2024.1230.1 246 8/18/2024
2024.1229.1 256 8/16/2024
2024.1228.1 263 8/15/2024
2024.1222.1 306 8/8/2024
2024.1221.1 231 8/7/2024
2024.1221.0.2-preview 150 8/8/2024
2024.1221.0.1-preview 143 8/8/2024
2024.1220.1 212 8/7/2024
2024.1219.0.2-preview 134 8/6/2024
2024.1219.0.1-preview 142 8/6/2024
2024.1217.0.2-preview 107 8/4/2024
2024.1217.0.1-preview 139 8/4/2024
2024.1216.0.2-preview 122 8/3/2024
2024.1216.0.1-preview 104 8/3/2024
2024.1208.0.1-preview 144 7/26/2024
2024.1207.0.7-preview 176 7/25/2024
2024.1207.0.5-preview 123 7/25/2024
2024.1166.1 274 6/14/2024
2024.1165.1 252 6/13/2024
2024.1164.1 220 6/12/2024
2024.1162.1 230 6/10/2024
2024.1158.1 252 6/6/2024
2024.1156.1 234 6/4/2024
2024.1152.1 284 5/31/2024
2024.1151.1 257 5/29/2024
2024.1150.2 241 5/29/2024
2024.1150.1 240 5/29/2024
2024.1149.1 238 5/28/2024
2024.1147.1 249 5/26/2024
2024.1146.2 269 5/25/2024
2024.1146.1 242 5/25/2024
2024.1145.1 239 5/24/2024
2024.1135.2 254 5/14/2024
2024.1135.1 244 5/14/2024
2024.1134.1 226 5/13/2024
2024.1130.1 265 5/9/2024
2024.1123.1 256 5/2/2024
2024.1121.1 264 4/30/2024
2024.1114.1 260 4/22/2024
2024.1113.0.5-preview 135 4/22/2024
2024.1113.0.3-preview 160 4/22/2024
2024.1113.0.2-preview 156 4/22/2024
2024.1113.0.1-preview 140 4/22/2024
2024.1108.0.1-preview 169 4/17/2024
2024.1107.0.1-preview 155 4/16/2024
2024.1094.2 249 4/3/2024
2024.1094.1 225 4/3/2024
2024.1092.1 256 4/1/2024
2024.1088.1 266 3/28/2024
2024.1085.1 266 3/25/2024
2024.1080.2 262 3/20/2024
2024.1080.1 247 3/20/2024
2024.1078.1 260 3/18/2024
2024.1077.1 274 3/17/2024
2024.1073.1 237 3/13/2024
2024.1070.1 259 3/10/2024
2024.1069.1 253 3/9/2024
2024.1068.1 259 3/8/2024
2024.1066.2 264 3/6/2024
2024.1066.1 217 3/6/2024
2024.1065.1 246 3/5/2024
2024.1065.0.1-preview 146 3/5/2024
2024.1063.2 281 3/3/2024
2024.1063.1 233 3/3/2024
2024.1062.1 262 3/2/2024
2024.1061.2 267 3/1/2024
2024.1061.1 238 3/1/2024
2024.1060.2 260 2/29/2024
2024.1060.1 233 2/29/2024
2024.1060.0.5-preview 137 2/29/2024
2024.1060.0.3-preview 160 2/29/2024
2024.1059.0.1-preview 148 2/28/2024
2024.1058.1 242 2/27/2024
2024.1056.1 227 2/25/2024
2024.1055.1 269 2/24/2024
2024.1052.1 293 2/21/2024
2024.1050.2 267 2/20/2024
2024.1050.1 240 2/19/2024
2024.1049.1 266 2/18/2024
2024.1048.1 255 2/17/2024
2024.1047.1 231 2/16/2024
2024.1035.1 260 2/4/2024
2024.1034.2 232 2/3/2024
2024.1029.1 271 1/29/2024
2024.1023.1 269 1/23/2024
2024.1022.1 280 1/22/2024
2024.1020.1 265 1/20/2024
2024.1019.1 301 1/19/2024
2024.1017.1 279 1/17/2024
2024.1012.1 269 1/12/2024
2024.1010.1 298 1/10/2024
2024.1008.1 288 1/8/2024
2024.1007.1 319 1/7/2024
2024.1005.1 275 1/5/2024
2024.1004.1 298 1/4/2024
2023.1365.1 289 12/31/2023
2023.1362.1 295 12/28/2023
2023.1361.1 299 12/27/2023
2023.1359.1 339 12/25/2023
2023.1358.1 297 12/24/2023
2023.1357.1 305 12/23/2023
2023.1342.1 389 12/8/2023
2023.1336.1 294 12/2/2023
2023.1332.1 334 11/28/2023
2023.1330.1 290 11/26/2023
2023.1325.1 285 11/21/2023
2023.1323.1 285 11/19/2023
2023.1320.1 287 11/17/2023
2023.1318.1 322 11/15/2023
2023.1317.1 311 11/13/2023
2023.1307.1 327 11/3/2023
2023.1305.1 291 11/1/2023
2023.1304.1 283 10/31/2023
2023.1294.1 327 10/21/2023
2023.1290.1 322 10/16/2023
2023.1289.1 329 10/16/2023
2023.1284.1 324 10/11/2023
2023.1276.1 350 10/3/2023
2023.1275.1 335 10/2/2023
2023.1272.1 358 9/29/2023
2023.1269.1 326 9/26/2023
2023.1242.1 446 8/30/2023
2023.1231.1 441 8/19/2023
2023.1229.1 432 8/17/2023
2023.1228.1 458 8/16/2023
2023.1227.1 439 8/15/2023
2023.1224.2 438 8/12/2023
2023.1224.1 483 8/12/2023
2023.1213.2 533 8/1/2023
2023.1213.1 523 8/1/2023
2023.1209.1 516 7/27/2023
2023.1201.1 552 7/20/2023
2023.1197.1 515 7/16/2023
2023.1178.1 539 6/27/2023
2023.1175.1 557 6/24/2023
2023.1174.1 525 6/22/2023
2023.1169.1 575 6/18/2023
2023.1165.1 486 6/14/2023
2023.1161.1 571 6/11/2023
2023.1159.1 559 6/7/2023
2023.1157.1 547 6/6/2023
2023.1146.1 562 5/27/2023
2023.1139.1 556 5/19/2023
2023.1137.1 594 5/17/2023
2023.1136.1 532 5/16/2023
2023.1118.1 582 4/28/2023
2023.1111.1 574 4/21/2023
2023.1110.1 652 4/20/2023
2023.1105.1 605 4/15/2023
2023.1103.1 558 4/13/2023
2023.1102.1 569 4/12/2023
2023.1101.1 572 4/11/2023
2023.1090.1 600 3/31/2023
2023.1089.1 603 3/30/2023
2023.1088.1 617 3/29/2023
2023.1082.1 621 3/23/2023
2023.1078.1 666 3/19/2023
2023.1075.1 596 3/16/2023
2023.1070.1 605 3/11/2023
2023.1069.1 625 3/10/2023
2023.1064.1 630 3/5/2023
2023.1060.1 649 3/1/2023
2023.1057.1 705 2/26/2023
2023.1046.1 668 2/15/2023
2023.1043.2 667 2/12/2023
2023.1043.1 651 2/12/2023
2023.1042.1 661 2/11/2023
2023.1041.1 689 2/10/2023
2023.1039.1 664 2/8/2023
2023.1036.1 680 2/5/2023
2023.1035.1 659 2/4/2023
2023.1033.1 708 2/2/2023
2023.1030.1 734 1/30/2023
2023.1028.1 685 1/28/2023
2023.1026.1 635 1/26/2023
2023.1025.1 687 1/25/2023
2023.1024.1 676 1/24/2023
2023.1023.1 687 1/23/2023
2022.1319.1 752 11/15/2022
2022.1309.1 785 11/5/2022
2022.1307.1 765 11/3/2022
2022.1295.1 775 10/22/2022
2022.1290.1 822 10/17/2022
2022.1289.2 781 10/16/2022
2022.1289.1 777 10/16/2022
2022.1283.1 831 10/10/2022
2022.1282.1 777 10/9/2022
2022.1278.1 778 10/5/2022
2022.1272.2 828 9/29/2022
2022.1272.1 828 9/29/2022
2022.1271.1 863 9/28/2022
2022.1266.1 859 9/23/2022
2022.1259.1 829 9/16/2022
2022.1257.1 906 9/14/2022
2022.1250.1 857 9/7/2022
2022.1250.0.2-preview 497 9/7/2022
2022.1249.0.2-preview 507 9/6/2022
2022.1249.0.1-preview 489 9/6/2022
2022.1197.1 849 7/16/2022
2022.1196.1 837 7/15/2022
2022.1194.1 881 7/13/2022
2022.1182.1 847 7/1/2022
2022.1178.1 826 6/27/2022
2022.1166.1 858 6/15/2022
2022.1157.1 877 6/6/2022
2022.1150.1 877 5/30/2022
2022.1149.1 867 5/29/2022
2022.1144.1 897 5/24/2022
0.6.2 912 5/23/2022
0.6.1 889 5/23/2022
0.6.0 865 5/14/2022
0.5.3 856 5/8/2022
0.5.2 843 5/1/2022
0.5.1 836 5/1/2022
0.5.0 824 4/23/2022
0.4.1 873 4/15/2022
0.4.0 884 4/9/2022
0.3.3 869 4/8/2022
0.3.2 872 4/1/2022
0.3.1 884 3/29/2022
0.3.0 897 3/28/2022
0.2.3 869 3/28/2022
0.2.2 878 3/25/2022
0.2.1 861 3/21/2022
0.2.0 914 3/18/2022