So there are multiple pages where I want to get the int userId.
All Razor pages inherit from the class PageModel. In your scenario, set Razor pages that "get the int userid" to inherit from a custom page model, as suggested in this SO post.
Inheriting from a base page model allows for centralizing code that would otherwise be repeated in each individual Razor page model.
The inherited class provides access to: DI services, HttpContext, User, etc. In addition, Razor pages that inherit from the base page model can access properties defined in the custom base page model.
The following sample shows how to set up an inherited base page model with dependency injection.
Sample notes
The sample uses the IConfiguration DI service as a substitute for your scenario that requires access to your database service.
The property UserIdAsInt is defined in the inherited base page model. Note that the property is set in the OnGet() method of the Razor view page because the GetUserIdAsInt() method in the inherited class uses the HttpContext object. This object is not available in the constructor methods of the inherited class or the Razor code-behind class. HttpContext is available once code execution gets to the OnGet() method.
MyBasePageModel.cs
This C# class file can be inserted anywhere in your project. You'll just need a using statement in the code-behind .cshtml.cs if the namespace is anything other than [ProjectName].Pages.
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace WebApplication1.Pages
{
public class MyBasePageModel : PageModel // Inherits from 'PageModel'
{
private readonly IConfiguration _configuration;
public int UserIdAsInt { get; set; }
public MyBasePageModel(IConfiguration configuration)
{
_configuration = configuration;
}
public int GetUserIdAsInt()
{
int? id = HttpContext.Session.GetInt32("UserIdAsInt");
if (id == null)
{
// Get user ID as integer from database
id = 100; // For sample purpose set 'id' variable to a hardcoded value
HttpContext.Session.SetInt32("UserIdAsInt", (int)id);
System.Diagnostics.Debug.WriteLine("User ID retrieved from database");
}
else
{
System.Diagnostics.Debug.WriteLine("User ID retrieved from session");
}
return (int)id;
}
public string GetLoggingLevel()
{
return _configuration["Logging:LogLevel:Default"].ToString();
}
}
}
InheritFromBasePageModel.cshtml.cs
namespace WebApplication1.Pages
{
public class InheritFromBasePageModelModel : MyBasePageModel // Inherits from the custom 'MyBasePageModel' class
{
public string? LoggingLevel { get; set; }
public InheritFromBasePageModelModel(IConfiguration configuration)
: base(configuration: configuration)
{
}
public void OnGet()
{
UserIdAsInt = GetUserIdAsInt();
LoggingLevel = GetLoggingLevel();
}
}
}
InheritFromBasePageModel.cshtml
@page
@model WebApplication1.Pages.InheritFromBasePageModelModel
@{
}
@section Styles {
<style>
p > span {
font-weight: bold;
}
</style>
}
<p>Logging level property from base page model: <span>@Model.LoggingLevel</span></p>
<p>Integer value: <span>@Model.UserIdAsInt</span></p>
Program.cs
// Configure session state
// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-7.0#configure-session-state
// https://stackoverflow.com/questions/71070698/session-in-asp-net-core-mvc
// "add session middleware in your configuration file"
builder.Services.AddSession(options =>
{
//options.IdleTimeout = TimeSpan.FromMinutes(1);
});
app.UseSession();
(Edit 11-Nov-2023)
Using OnPageHandlerExecutionAsync() override
The MyBasePageModel.cs base page model class above requires each Razor page that inherits from the base page model to add the line UserIdAsInt = GetUserIdAsInt(); in the OnGet() method.
This SO post and article show how to execute a method for every OnGet() handler that inherits from a base page model without adding it to every Razor page.
Here's a modified MyBasePageModel.cs class file that implements the OnPageHandlerExecutionAsync() override method.
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace WebApplication1.Pages
{
public class MyBasePageModel : PageModel
{
private readonly IConfiguration _configuration;
public int UserIdAsInt { get; set; }
public MyBasePageModel(IConfiguration configuration)
{
_configuration = configuration;
}
// https://stackoverflow.com/questions/55030251/razor-pages-call-method-from-base-class-after-all-onget-handlers
// https://www.learnrazorpages.com/razor-pages/filters
// "Model binding completed. Handler has not been executed."
public async override Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
if (context.HandlerMethod?.MethodInfo.Name == "OnGet")
{
// Code placed here will execute just before the OnGet()
// method is executed.
UserIdAsInt = await GetUserIdAsInt();
}
await base.OnPageHandlerExecutionAsync(context, next);
}
public async Task<int> GetUserIdAsInt()
{
int? id = HttpContext.Session.GetInt32("UserIdAsInt");
// A valid user ID integer value exists in the 'Session'
// object. Therefore, return this value.
if (id != null)
{
System.Diagnostics.Debug.WriteLine("User ID retrieved from session");
return (int)id;
}
// Get user ID as integer from database
// 'Task.Run()' is used to simulate an async execution
// of a database task.
return await Task.Run(() =>
{
id = 200; // For sample purpose set 'id' variable to a hardcoded value
HttpContext.Session.SetInt32("UserIdAsInt", (int)id);
System.Diagnostics.Debug.WriteLine("User ID retrieved from database");
return (int)id;
});
}
public string? GetLoggingLevel()
{
if (_configuration == null) { return "(Configuration does not exist.)"; }
return _configuration["Logging:LogLevel:Default"]?.ToString() ?? "Unset";
}
}
}
userIdto the HttpContext User. Here is the detailed steps.PageModel. Set the pages that "get the int userid" to inherit from a custom page model that centralizes code, provides DI in the custom/inherited page model, provides access toHttpContext, etc. The Razor pages that inherit from the base page model can access properties defined in the custom base page model.