Nabs.Launchpad.Core.Context 10.0.210

Prefix Reserved
dotnet add package Nabs.Launchpad.Core.Context --version 10.0.210
                    
NuGet\Install-Package Nabs.Launchpad.Core.Context -Version 10.0.210
                    
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="Nabs.Launchpad.Core.Context" Version="10.0.210" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nabs.Launchpad.Core.Context" Version="10.0.210" />
                    
Directory.Packages.props
<PackageReference Include="Nabs.Launchpad.Core.Context" />
                    
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 Nabs.Launchpad.Core.Context --version 10.0.210
                    
#r "nuget: Nabs.Launchpad.Core.Context, 10.0.210"
                    
#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 Nabs.Launchpad.Core.Context@10.0.210
                    
#: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=Nabs.Launchpad.Core.Context&version=10.0.210
                    
Install as a Cake Addin
#tool nuget:?package=Nabs.Launchpad.Core.Context&version=10.0.210
                    
Install as a Cake Tool

Nabs Launchpad Core Context Library

The Nabs Launchpad Core Context library provides essential context management classes for multi-tenant Blazor applications with Orleans integration. This library defines the core context objects for users, tenants, and portals, along with utilities for passing context through Orleans grain calls.

Key Features

  • User Context Management: Track authenticated user information across the application
  • Tenant Context Support: Multi-tenant application support with tenant-specific data
  • Portal Configuration: Flexible portal configuration with navigation and branding
  • Orleans Integration: Seamless context propagation through Orleans RequestContext
  • Serialization Support: Orleans-compatible serialization attributes for distributed scenarios
  • Theme Preferences: User-specific theme preferences (dark/light mode)
  • Navigation Configuration: Type-safe navigation item definitions

Core Components

UserContext

Represents the authenticated user's context information including identity, preferences, and correlation tracking. Fully serializable for Orleans grain calls.

TenantContext

Provides tenant-specific context for multi-tenant applications.

PortalContext

Defines portal configuration including branding, navigation, authentication settings, and base paths.

Represents a navigation menu item with path, display name, and icon configuration.

UserContextExtensions

Extension methods for accessing user context from Orleans grains through RequestContext.

Usage Examples

User Context

// Create user context from authentication
var userContext = new UserContext
{
    IsAuthenticated = true,
    ObjectId = "user-123",
    DisplayName = "John Doe",
    Email = "john.doe@example.com",
    CorrelationId = Guid.NewGuid().ToString(),
    PreferredTheme = "dark"
};

// Check authentication
if (userContext.IsAuthenticated)
{
    Console.WriteLine($"Welcome, {userContext.DisplayName}");
}

// Use correlation ID for logging
logger.LogInformation("Request {CorrelationId} from {User}", 
    userContext.CorrelationId, userContext.Email);

Portal Context Configuration

// Configure portal settings
var portalContext = new PortalContext
{
    PortalName = "admin-portal",
    PortalDisplayName = "Administration Portal",
    PortalBasePath = "/admin",
    Copyright = "� 2024 My Company",
    DisableAuth = false,
    NavigationItems = new[]
    {
        new NavigationItem
        {
            Path = "/admin/dashboard",
            DisplayValue = "Dashboard",
            IconClass = "e-icons e-dashboard"
        },
        new NavigationItem
        {
            Path = "/admin/users",
            DisplayValue = "Users",
            IconClass = "e-icons e-users"
        },
        new NavigationItem
        {
            Path = "/admin/settings",
            DisplayValue = "Settings",
            IconClass = "e-icons e-settings"
        }
    }
};

// Use in application configuration
services.AddSingleton(portalContext);

Tenant Context

// Create tenant context
var tenantContext = new TenantContext
{
    DisplayName = "Acme Corporation"
};

// Use in multi-tenant scenarios
services.AddScoped(_ => tenantContext);

Orleans Grain Integration

// In your grain interface
public interface IUserGrain : IGrainWithStringKey
{
    Task<UserProfile> GetProfileAsync();
    Task UpdatePreferencesAsync(string theme);
}

// In your grain implementation
public class UserGrain : Grain, IUserGrain
{
    public Task<UserProfile> GetProfileAsync()
    {
        // Access user context from Orleans RequestContext
        var userContext = this.GetUserContext();
        
        if (userContext?.IsAuthenticated != true)
        {
            throw new UnauthorizedAccessException("User not authenticated");
        }
        
        // Use user context information
        var profile = new UserProfile
        {
            UserId = userContext.ObjectId,
            DisplayName = userContext.DisplayName,
            Email = userContext.Email,
            Theme = userContext.PreferredTheme
        };
        
        return Task.FromResult(profile);
    }
    
    public Task UpdatePreferencesAsync(string theme)
    {
        var userContext = this.GetUserContext();
        
        // Log with correlation ID
        logger.LogInformation(
            "User {UserId} updated theme preference to {Theme} (Correlation: {CorrelationId})",
            userContext?.ObjectId,
            theme,
            userContext?.CorrelationId);
        
        // Update preferences logic...
        return Task.CompletedTask;
    }
}

Setting Orleans RequestContext (Client Side)

// In Blazor component or middleware
public class UserContextMiddleware
{
    private readonly RequestDelegate _next;
    
    public UserContextMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    
    public async Task InvokeAsync(HttpContext context, IUserService userService)
    {
        var user = context.User;
        
        if (user.Identity?.IsAuthenticated == true)
        {
            var userContext = new UserContext
            {
                IsAuthenticated = true,
                ObjectId = user.FindFirst("oid")?.Value ?? "",
                DisplayName = user.Identity.Name ?? "",
                Email = user.FindFirst(ClaimTypes.Email)?.Value ?? "",
                CorrelationId = context.TraceIdentifier,
                PreferredTheme = await userService.GetThemePreferenceAsync(user)
            };
            
            // Set in Orleans RequestContext for grain calls
            RequestContext.Set("UserContext", userContext);
        }
        
        await _next(context);
    }
}

Blazor Component Integration

@page "/profile"
@inject IClusterClient ClusterClient
@inject UserContext UserContext

<h3>User Profile</h3>

@if (UserContext.IsAuthenticated)
{
    <div>
        <p><strong>Name:</strong> @UserContext.DisplayName</p>
        <p><strong>Email:</strong> @UserContext.Email</p>
        <p><strong>Theme:</strong> @UserContext.PreferredTheme</p>
    </div>
    
    <button @onclick="UpdateTheme">Toggle Theme</button>
}

@code {
    private async Task UpdateTheme()
    {
        var newTheme = UserContext.PreferredTheme == "dark" ? "light" : "dark";
        
        // Call Orleans grain with automatic context propagation
        var grain = ClusterClient.GetGrain<IUserGrain>(UserContext.ObjectId);
        await grain.UpdatePreferencesAsync(newTheme);
    }
}

Dynamic Navigation from Portal Context

@inject PortalContext PortalContext

<nav>
    <h1>@PortalContext.PortalDisplayName</h1>
    
    <ul>
        @foreach (var navItem in PortalContext.NavigationItems)
        {
            <li>
                <a href="@navItem.Path">
                    <i class="@navItem.IconClass"></i>
                    @navItem.DisplayValue
                </a>
            </li>
        }
    </ul>
    
    <footer>@PortalContext.Copyright</footer>
</nav>

API Reference

UserContext

Properties
IsAuthenticated
public bool IsAuthenticated { get; init; }

Indicates whether the user is authenticated.

ObjectId
public string ObjectId { get; init; }

The unique identifier for the user (typically from identity provider).

DisplayName
public string DisplayName { get; init; }

The user's display name.

Email
public string Email { get; init; }

The user's email address.

CorrelationId
public string CorrelationId { get; init; }

Correlation ID for tracking requests across services.

PreferredTheme
public string PreferredTheme { get; init; }

The user's preferred theme ("dark" or "light"). Defaults to "dark".

TenantContext

Properties
DisplayName
public string DisplayName { get; set; }

The display name of the tenant/organization.

PortalContext

Properties
PortalName
public string PortalName { get; set; }

A unique identifier name for the portal.

PortalDisplayName
public string PortalDisplayName { get; set; }

The human-readable display name for the portal.

PortalBasePath
public string PortalBasePath { get; set; }

The base path for all portal routes. Defaults to "/".

public string Copyright { get; set; }

Copyright text displayed in the portal footer.

public NavigationItem[] NavigationItems { get; set; }

Array of navigation menu items for the portal.

DisableAuth
public bool DisableAuth { get; set; }

Indicates whether authentication is disabled for the portal. Defaults to false.

Properties
Path
public string Path { get; set; }

The navigation path/route.

DisplayValue
public string DisplayValue { get; set; }

The display text for the navigation item.

IconClass
public string IconClass { get; set; }

CSS class(es) for the navigation icon (e.g., "e-icons e-dashboard" for Syncfusion icons).

UserContextExtensions

Methods
GetUserContext
public static UserContext? GetUserContext(this IGrain grain)

Extension method to retrieve the UserContext from Orleans RequestContext within a grain.

Returns: The UserContext if available, otherwise null.

Usage:

public class MyGrain : Grain, IMyGrain
{
    public Task DoSomethingAsync()
    {
        var userContext = this.GetUserContext();
        if (userContext?.IsAuthenticated != true)
        {
            throw new UnauthorizedAccessException();
        }
        // ... rest of implementation
    }
}

Orleans Serialization

The UserContext class is decorated with Orleans serialization attributes:

  • [Serializable]: Marks the class as serializable
  • [GenerateSerializer]: Triggers Orleans source generator for optimized serialization
  • [Alias]: Provides a stable type identifier for serialization versioning
  • [Id(n)]: Marks properties for serialization with explicit ordering

This enables UserContext to be efficiently serialized when passed across Orleans grain boundaries.

Architecture Patterns

Multi-Tenant Support

Use TenantContext to scope data and operations to specific tenants in multi-tenant applications.

Correlation Tracking

Use the CorrelationId property in UserContext to track requests across distributed services for logging and debugging.

Portal Customization

Configure multiple PortalContext instances for different areas of your application (admin portal, user portal, etc.).

Theme Preferences

Store and retrieve user theme preferences through PreferredTheme for consistent UI experience.

Best Practices

  1. Set Context Early: Establish UserContext in middleware or authentication handlers
  2. Use Correlation IDs: Always populate CorrelationId for request tracking
  3. Immutable User Context: Use init properties to ensure context immutability
  4. Validate Authentication: Always check IsAuthenticated before accessing user-specific data
  5. Configure Portal Context at Startup: Register PortalContext as a singleton during application startup
  6. Use Extension Methods: Use GetUserContext() extension method in grains for cleaner code
  7. Handle Null Context: Always check for null when retrieving context in grains

Testing

Mocking User Context

[Fact]
public async Task GrainMethod_WithAuthenticatedUser_Success()
{
    // Arrange
    var mockContext = new UserContext
    {
        IsAuthenticated = true,
        ObjectId = "test-user",
        DisplayName = "Test User",
        Email = "test@example.com",
        CorrelationId = "test-correlation-id",
        PreferredTheme = "dark"
    };
    
    RequestContext.Set("UserContext", mockContext);
    
    var grain = GetTestGrain<IUserGrain>("test-user");
    
    // Act
    var result = await grain.GetProfileAsync();
    
    // Assert
    result.Should().NotBeNull();
    result.DisplayName.Should().Be("Test User");
}

Dependencies

  • Microsoft.Orleans.Core.Abstractions: For Orleans grain abstractions and RequestContext

Target Framework

  • .NET 10
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 (4)

Showing the top 4 NuGet packages that depend on Nabs.Launchpad.Core.Context:

Package Downloads
Nabs.Launchpad.Ui.Shell

Package Description

Nabs.Launchpad.Core.Silo

Package Description

Nabs.Launchpad.Core.Portal

Package Description

Nabs.Launchpad.Ui.Shell.Blazor.Sf

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.210 0 12/30/2025
10.0.209 60 12/30/2025
10.0.208 62 12/30/2025
10.0.207 71 12/29/2025
10.0.206 72 12/29/2025
10.0.205 199 12/24/2025
10.0.204 196 12/21/2025
10.0.203 299 12/18/2025
10.0.202 292 12/17/2025
10.0.200 300 12/17/2025
10.0.199 453 12/10/2025
10.0.197 193 12/5/2025
10.0.196 703 12/3/2025
10.0.195 692 12/3/2025
10.0.194 692 12/3/2025
10.0.193 704 12/2/2025
10.0.192 209 11/28/2025
10.0.190 208 11/27/2025
10.0.189 185 11/23/2025
10.0.187 193 11/23/2025
10.0.186 186 11/23/2025
10.0.184 428 11/20/2025
10.0.181-rc3 304 11/11/2025
10.0.180 308 11/11/2025
10.0.179-rc2 295 11/11/2025
10.0.178-rc2 254 11/10/2025
10.0.177-rc2 239 11/10/2025
10.0.176-rc2 206 11/6/2025
10.0.175-rc2 206 11/6/2025
10.0.174-rc2 216 11/5/2025
10.0.173-rc2 318 11/3/2025 10.0.173-rc2 is deprecated because it is no longer maintained.
10.0.172-rc2 239 11/2/2025 10.0.172-rc2 is deprecated because it is no longer maintained.
10.0.170-rc2 222 11/1/2025 10.0.170-rc2 is deprecated because it is no longer maintained.
10.0.169-rc2 224 11/1/2025 10.0.169-rc2 is deprecated because it is no longer maintained.
10.0.168-rc2 224 10/31/2025 10.0.168-rc2 is deprecated because it is no longer maintained.
10.0.166-rc2 227 10/31/2025 10.0.166-rc2 is deprecated because it is no longer maintained.
10.0.164-rc2 289 10/28/2025 10.0.164-rc2 is deprecated because it is no longer maintained.
10.0.162-rc2 284 10/24/2025 10.0.162-rc2 is deprecated because it is no longer maintained.
10.0.161 296 10/24/2025 10.0.161 is deprecated because it is no longer maintained.
9.0.151 264 10/17/2025 9.0.151 is deprecated because it is no longer maintained.
9.0.150 337 9/10/2025 9.0.150 is deprecated because it is no longer maintained.
9.0.146 278 8/15/2025 9.0.146 is deprecated because it is no longer maintained.
9.0.145 309 8/11/2025 9.0.145 is deprecated because it is no longer maintained.
9.0.144 323 8/8/2025 9.0.144 is deprecated because it is no longer maintained.
9.0.137 276 7/29/2025 9.0.137 is deprecated because it is no longer maintained.
9.0.136 274 7/29/2025 9.0.136 is deprecated because it is no longer maintained.
9.0.135 310 7/28/2025 9.0.135 is deprecated because it is no longer maintained.
9.0.134 336 7/9/2025 9.0.134 is deprecated because it is no longer maintained.
9.0.133 336 7/9/2025 9.0.133 is deprecated because it is no longer maintained.
9.0.132 348 7/9/2025 9.0.132 is deprecated because it is no longer maintained.
9.0.131 356 7/9/2025 9.0.131 is deprecated because it is no longer maintained.
9.0.130 326 7/7/2025 9.0.130 is deprecated because it is no longer maintained.