In my ASP.NET Core 2 project, I create new class that inherits the RazorPage class to add some additional property in views.
public abstract class WebViewPage<TModel> : Microsoft.AspNetCore.Mvc.Razor.RazorPage<TModel>
{
public string Version
{
get
{
return "1.00.100";
}
}
public User CurrentUser
{
get
{
//challenge is here:
//return _services.GetRequiredService<IUserService>().GetCurrentUser();
}
}
}
public abstract class WebViewPage : WebViewPage<dynamic>
{
}
and _ViewImport.cshtml
file changed to this:
@inherits MyProject.WebViewPage<TModel>
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
The project works fine till challenge codes are marked as comment. but, how can I inject dependencies to the abstract class? or how to Resolve services in abstract class?
This is my StartUp.cs
file:
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
services.AddMvc();
services.AddTransient<IUserService, UserService>();
//services.AddScoped<IRazorPage<?>, WebViewPage<?>(); // ?: challenge!
}
Any concrete class inheriting the abstract class should be instantiable with a constructor (if not abstract itself of course). But use of constructor is prohibited by Spring because any class that we instantiate this way cannot be taken in charge by Spring's automated dependency injection.
ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies.
As always, the answer is: "It depends." You can't do these approaches with interfaces as interfaces only specify the contract and don't have implementation. If the contract is all you need, then go with an interface. If you need code to be shared by the subclasses, then go with an abstract class.
If you need access to the service provider inside of your razor page, you could access the HttpContext
through the Context
property, e.g.:
var userService = Context.RequestServices.GetRequiredService<IUserService>();
A possibly better alternative would be to have a constructor that takes the IUserService
as a dependency. So implementations of your type would have to pass that dependency on, essentially requiring them to have a constructor dependency on their own (which makes a good explicit design).
As for that dependency registration part, note that you generally cannot register abstract classes because they cannot be instantiated.
But in general, in order to register a generic type, you have to use the more verbose overload of AddScoped
which takes actual Type
arguments:
services.AddScoped(typeof(IRazorPage<>), typeof(WebViewPage<>));
Making a generic method call requires a real type as a generic type argument, so you would have to specify a concrete type for the type argument T
inside IRazorPage<T>
and WebViewPage<T>
. Since you explicitly do not want to use a concrete type there but instead want to tell the dependency injection container to support any type, you cannot use this syntax there.
Since the typeof
operator can determine the actual generic type, you can use it without having to use a specific type argument which would limit the registration to a single type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With