BasePageModel in Razor Pages
Asked Answered
D

3

7

I'm currently refactoring a bloated MVC .NET Core app to a more simpler .NET Core app using Razor Pages and Mediatr.

In the MVC approach there's a BaseController that all controllers inherits from. The BaseController handles the Mediatr DI. How will I go about doing this in Razor Pages? Is it wise to create a BasePageModel class that handles the Mediatr DI, or should I just include the Mediatr DI in every PageModel I create?

Decolonize answered 20/2, 2019 at 10:16 Comment(1)
I wouldn't create a BasePageModel just to handle common injected services. You still have to inject them into your derived classes and then pass them on to the base constructor, so I don't see that you gain much.Magnesium
D
7

I'm using a BasePageModel class to hold common code and properties. The subclasses get the DI injected objects and then pass them up to the base class which handles them with an optional parameters list. There might be more elegant way to accomplish this but this is working well for me.

public class BasePageModel : PageModel {
    public BasePageModel(params object[] list) {
        foreach (var item in list) {
            if (item is ILoggerFactory loggerFactory) {
                _logger = loggerFactory.CreateLogger("Projects");
            }
            if (item is ApplicationDbContext context) {
                _dbContext = context;
            }
            if (item is UserManager<ApplicationUser> manager) {
                _userManager = manager;
            }
            if (item is IHostingEnvironment env) {
                _environment = env;
            }
        }
    }

public class IndexModel : BasePageModel {

    public IndexModel(ApplicationDbContext context, UserManager<ApplicationUser> userManager, ILoggerFactory loggerFactory) :
        base(context, userManager, loggerFactory) { }
}
Delrosario answered 21/2, 2019 at 19:44 Comment(2)
Thanks for the feedback, Brad! This seems like a pretty decent solution.Decolonize
Thanks for this. I'm doing this to reuse some common properties and methods across pages.Actomyosin
D
1

I tried to use the marked answer but when it comes to below line in code:

private readonly ILogger<IndexPage> _logger;

it seems we have to consider the generic type for ILogger

So, I created a generic base class and came up with a variation of the selected answer.

public class _BasePageModel<T> : PageModel where T : PageModel
{
    protected readonly ILogger<T> _logger;

    public _BasePageModel(params object[] list)
    {
        foreach (var item in list)
        {
            if (item is ILogger logger)
            {
                _logger = (ILogger<T>?)logger;
            }
            // check if there are other injected dependencies
        }
    }
}

And changed the Index page as follow:

public class IndexModel : _BasePageModel<IndexModel>
{
    public IndexModel(ILogger<IndexModel> logger) : base(logger)
    {
        //
    }
}
Durative answered 28/12, 2022 at 18:52 Comment(0)
I
0

I use an adaption of FLICKER's answer with auto-injected common dependencies:

public class BasePageModel<T> : PageModel where T : PageModel
{
    private ILogger<T>? _logger;
    private IConfiguration? _config;
    private IMapper? _mapper;

    protected ILogger<T> Logger => _logger ??= HttpContext.RequestServices.GetService<ILogger<T>>()!;

    protected IConfiguration Configuration => _config ??= HttpContext.RequestServices.GetService<IConfiguration>()!;

    protected IMapper Mapper => _mapper ??= HttpContext.RequestServices.GetService<IMapper>()!;

    public BasePageModel(params object[] dependencies)
    {
        foreach (var dependency in dependencies)
        {
            // additional code for handling dependencies, if necessary
        }
 }

That way, page constructors can remain empty unless they need custom dependencies:

public class IndexModel : BasePageModel<IndexModel> 
{ ... }

public class CreateModel(ICustomDependency customDependency) : BasePageModel<CreateModel>
{ ... }
Inhere answered 1/7 at 14:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.