Skip to content

Introduce a session metadata to load session asynchronously in session middleware #35154

@Kahbazi

Description

@Kahbazi

Background and Motivation

The default session provider in ASP.NET Core loads session records from the underlying IDistributedCache backing store asynchronously only if the ISession.LoadAsync method is explicitly called before the TryGetValue, Set, or Remove methods. If LoadAsync isn't called first, the underlying session record is loaded synchronously, which can incur a performance penalty at scale.

We could provide a new endpoint metadata with SessionState property for session which controls the behavior of SessionMiddleware.

  • SessionState.Default: The current behavior which creates a session key, set the session feature, set cookie if needed.
  • SessionState.EagerLoad: Calls LoadAsync in session middleware [Needs a better name than EagerLoad!]
  • SessionState.Disabled: Do nothing in session middleware, not even setting the session feature
  • SessionState.ReadOnly: Calls LoadAsync in session middleware, but not CommitAsync and wrap ISession in a class which throw exception when Set, Remove or Clear called.

Proposed API

public class SessionOptions
{
     // The behavior of session middleware when `ISessionStateMetadata` is not available.
+   public SessionState DefaultBehavior { get; set; }
}
public interface ISessionStateMetadata
{
    SessionState State { get; }
}

public enum SessionState
{
    Default = 0,
    EagerLoad = 1,
    Disabled = 2,
    ReadOnly = 3,
}

public class SessionStateAttribute : ISessionStateMetadata
{
    SessionState State { get; }
}

public static class RoutingEndpointConventionBuilderExtensions
{
    public static TBuilder SetSessionBehvior<TBuilder>(this TBuilder builder, SessionState sessionState) where TBuilder : IEndpointConventionBuilder;
}

Usage Examples

[SessionState(SessionState.Disabled)]
public class CustomerController
{
    ...
}

app.MapGet("/nosession", (HttpContext context) => $"Hello World!").SetSessionBehvior(SessionState.Disabled);

app.MapGet("/nosession2", [SessionState(SessionState.Disabled)] (HttpContext context) => $"Hello World!");

app.MapGet("/", (HttpContext context) => $"{context.Session.GetString("Hi")} World!").SetSessionBehvior(SessionState.ReadOnly);

Risks

If Endpoints are marked by mistake the session would load for all requests even when they don't need session.

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-middlewareIncludes: URL rewrite, redirect, response cache/compression, session, and other general middlewaresfeature-session

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions