Dependency Injection in an DisplayName attribute - asp.net-core

I have a class in which data that needs to be shown to the user is kept. I want to use Localizer for this class and ı wrote custom DisplayName Attribute class for this. But ı cant access IStringLocalizer from this class. How can i acces this class can u help me pls.
This is my Custom class.
public class CustomName:DisplayNameAttribute
{
static IStringLocalizer<CustomName> _localizer;
private readonly ServiceProvider _di;
public CustomName(IStringLocalizer<CustomName> localizer)
{
_localizer = localizer;
}
public CustomName(string key) : base(Lookup(key)) { }
static string Lookup(string key)
{
if (_localizer == null) {
//always getting here cause constructor wont run
}
try
{
return _localizer.GetString(key);
}
catch
{
return key; // fallback
}
}
}
How can i access localizer object without depencency injection ?

Related

How can I validate different types within a collection using FluentValidation?

I have a class with a collection that needs validation. The generic on the collection takes an interface and different types can be added to the collection.
What is the cleanest path forward to creating a FluentValidation validator that supports polymorphism?
public interface IWizardStep {}
public class WizardOne : IWizardStep
{
public string Model { get; set; }
}
public class WizardTwo : IWizardStep
{
public string FirstName { get; set; }
}
public class Wizard
{
public Wizard()
{
var w1 = new WizardOne();
var w2 = new WizardTwo();
Steps = new List<IWizardStep>
{
w1,
w2
};
}
public IList<IWizardStep> Steps { get; set; }
}
public class WizardValidator : AbstractValidator<Wizard>
{
public WizardValidator()
{
RuleFor(x => x.Steps)
// Steps First where is WizardOne
// Model.NotEmpty()
// Steps First where is WizardTwo
// FirstName.NotEmpty()
}
FluentValidation doesn't support polymorphism for child collections like this out of the box, but you can add this behaviour by using a custom property validator, or by using OfType in your rule definitions.
I've written about both approaches before here:
Step 1: Create a validator for each implementor
Start by creating a validator for WizardOne and WizardTwo:
public class WizardOneValidator : AbstractValidator<WizardOne> {
public WizardOneValidator() {
RuleFor(x => x.Model).NotEmpty();
}
}
public class WizardTwoValidator : AbstractValidator<WizardTwo> {
public WizardTwoValidator() {
RuleFor(x => x.FirstName).NotEmpty();
}
}
Step 2: Create the parent validator
You have two options for defining the parent validator. The simplest approach is to use OfType, but this is less performant. The more complex option is to use a custom property validator.
Option 1: Using OfType
public WizardValidator : AbstractValidator<Wizard> {
public WizardValidator() {
RuleForEach(x => x.Steps.OfType<WizardOne>()).SetValidator(new WizardOneValidator());
RuleForEach(x => x.Steps.OfType<WizardTwo>()).SetValidator(new WizardTwoValidator());
}
}
This is the simplest approach, but calling OfType inside the call RuleFor will end up bypassing FluentValidation's expression cache, which is a potential performance hit. It also iterates the collection multiple. This may or may not be an issue for you - you'll need to decide if this has any real-world impact on your application.
Option 2: Using a custom PropertyValidator.
This uses a custom custom validator which can differentiate the underlying type at runtime:
public WizardValidator : AbstractValidator<Wizard> {
public WizardValidator() {
RuleForEach(x => x.Steps).SetValidator(new PolymorphicValidator<Wizard, IWizardStep>()
.Add<WizardOne>(new WizardOneValidator())
.Add<WizardTwo>(new WizardTwoValidator())
);
}
}
Syntactically, this isn't quite as nice, but doesn't bypass the expression cache and doesn't iterate the collection multiple times. This is the code for the PolymorphicValidator:
public class PolymorphicValidator<T, TInterface> : ChildValidatorAdaptor<T, TInterface> {
readonly Dictionary<Type, IValidator> _derivedValidators = new Dictionary<Type, IValidator>();
// Need the base constructor call, even though we're just passing null.
public PolymorphicValidator() : base((IValidator<TInterface>)null, typeof(IValidator<TInterface>)) {
}
public PolymorphicValidator<T, TInterface> Add<TDerived>(IValidator<TDerived> derivedValidator) where TDerived : TInterface {
_derivedValidators[typeof(TDerived)] = derivedValidator;
return this;
}
public override IValidator<TInterface> GetValidator(PropertyValidatorContext context) {
// bail out if the current item is null
if (context.PropertyValue == null) return null;
if (_derivedValidators.TryGetValue(context.PropertyValue.GetType(), out var derivedValidator)) {
return new ValidatorWrapper(derivedValidator);
}
return null;
}
private class ValidatorWrapper : AbstractValidator<TInterface> {
private IValidator _innerValidator;
public ValidatorWrapper(IValidator innerValidator) {
_innerValidator = innerValidator;
}
public override ValidationResult Validate(ValidationContext<TInterface> context) {
return _innerValidator.Validate(context);
}
public override Task<ValidationResult> ValidateAsync(ValidationContext<TInterface> context, CancellationToken cancellation = new CancellationToken()) {
return _innerValidator.ValidateAsync(context, cancellation);
}
public override IValidatorDescriptor CreateDescriptor() {
return _innerValidator.CreateDescriptor();
}
}
}
This will probably be implemented in the library as a first class feature at some point in the future - you can track its development here if you're interested.

Extending ResourceManagerStringLocalizer functionality

I am fairly new to .net core and I want to implement localization in my application. The built in ResourceManagerStringLocalizer service satisfies almost all my requirements and works great out of the box, but I want to add some custom functionality to it, without copy pasting all of the class' code and adding some to it in my own localizer. Currently I have tried deriving from the class in my own Localizer and injecting that as my IStringLocalizer:
services.AddTransient<IStringLocalizer<MyApp.SharedResource>, MyLocalizer<MyApp.SharedResource>>();
...
public class MyLocalizer<T> : ResourceManagerStringLocalizer, IStringLocalizer<T> {
public MyLocalizer(ResourceManager resourceManager, IResourceStringProvider resourceStringProvider, string baseName, IResourceNamesCache resourceNamesCache, ILogger logger) : base(resourceManager, resourceStringProvider, baseName, resourceNamesCache, logger) {
}
public override LocalizedString this[string name] {
get {
//do some custom functionality
return base[name];
}
}
public override LocalizedString this[string name, params object[] arguments] {
get {
//do some custom functionality
return base[name, arguments];
}
}
}
But this gives the following exception when trying to use it:
System.InvalidOperationException: 'Unable to resolve service for type 'System.Resources.ResourceManager' while attempting to activate 'MyApp.Services.MyLocalizer`1[MyApp.SharedResource]'.'
My question is, what's the best way to this? And whats best practice for doing things like this? I feel like this sort of stuff may come up more often in the future of this application and all help will be appreciated.
You don't have to override the built-in localizer, just implement your custom one:
public class MyLocalizer
{
private readonly IStringLocalizer _localizer;
public MyLocalizer(IStringLocalizerFactory factory)
{
var type = typeof(MyResourceType);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
_localizer = factory.Create("MyResourceType", assemblyName.Name);
}
public LocalizedString this[string name]
{
get
{
// ...
return _localizer[name];
}
}
public LocalizedString this[string name, params object[] arguments]
{
get
{
// ...
return _localizer[name, arguments];
}
}
}
Then you can simple inject it to the views:
#inject MyLocalizer _loc;
<h1>#_loc["Hellow"]</h1>
or to the backend:
public class HomeController : Controller
{
private readonly MyLocalizer _loc;
public HomeController(MyLocalizer loc)
{
_loc = loc;
}
public IActionResult Index()
{
var msg = _loc["Welcome"];
//...
}
}

Access attribute from outside of a controller

Is it possible to access a custom attribute of a controller action from outside of that controller? I have a custom output formatter that should return a file with a specific name. I made a custom attribute that accepts a string (filename) and I'd like to try to access the value of that attribute from within the custom output formatter.
public class FileAttribute : Attribute
{
public ExcelTemplateAttribute(string fileName)
{
FileName = fileName;
}
public string FileName { get; }
}
My OutputFormatter looks like this:
public class FileOutputFormatter : OutputFormatter
{
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
{
// string filename = ???
}
}
My API action returns a service
[File("Template.txt")]
public IActionResult Get([FromQuery]int Id)
{
IEnumerable<int> data = _kenoReport.GetReportData(Id);
return Ok(data);
}
Controller and/or action information is not easily accessible outside of the MVC-specific parts of the middleware pipeline without resorting to complex (and easy-to-break) code relying on reflection.
However, one workaround is to use an action filter to add the attribute details to the HttpContext.Items dictionary (which is accessible throughout the entire middleware pipeline) and have the output formatter retrieve it later on in the middleware pipeline.
For example, you could make your FileAttribute derive from ActionFilterAttribute and have it add itself to HttpContext.Items (using a unique object reference as the key) when executing:
public sealed class FileAttribute : ActionFilterAttribute
{
public FileAttribute(string filename)
{
Filename = filename;
}
public static object HttpContextItemKey { get; } = new object();
public string Filename { get; }
public override void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Items[HttpContextItemKey] = this;
}
}
Then in your output formatter you can retrieve the attribute instance and access the filename:
public sealed class FileOutputFormatter : OutputFormatter
{
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
{
if (context.HttpContext.Items.TryGetValue(FileAttribute.HttpContextItemKey, out var item)
&& item is FileAttribute attribute)
{
var filename = attribute.Filename;
// ...
}
}
}

Simplest way to mock properties of PostSharp attribute

I'm using a PostSharp method attribute to do authorisation and auditing on my WCF service. It's working properly but now I'm trying to get my unit tests working with the attribute and am struggling to find a way to mock and inject the properties on the attribute.
My attribute is as below.
[Serializable]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class AuthoriseAndAuditAttribute : OnMethodBoundaryAspect
{
private static ILog logger = AppState.logger;
private static Ninject.IKernel _kernel = MyKernel.Kernel;
private UserRoleTypesEnum _requiredRole = UserRoleTypesEnum.None;
[Inject]
public IServiceAuthToken _serviceAuthToken { get; set; }
[Inject]
public UserSessionDataLayer _userSessionDataLayer { get; set; }
public AuthoriseAndAuditAttribute(UserRoleTypesEnum role = UserRoleTypesEnum.None)
{
_requiredRole = role;
_kernel.Inject(this);
}
public override void OnEntry(MethodExecutionArgs args)
{
// Get the user's session from cookie.
UserSession userSession = GetUserSession();
// Check that user is in the required role.
bool isAuthorised = (_requiredRole == UserRoleTypesEnum.None || (userSession != null && userSession.Roles.Contains(_requiredRole)));
if (!isAuthorised)
{
logger.Warn("Not authorised for " + args.Method.Name + ".");
throw new UnauthorizedAccessException();
}
else if (userSession != null)
{
Thread.CurrentPrincipal = new MyPrincipal(userSession);
}
}
private UserSession GetUserSession()
{
if (_serviceAuthToken != null)
{
string sessionID = _serviceAuthToken.GetSessionID();
if (!sessionID.IsNullOrBlank())
{
return _userSessionDataLayer.GetForSessionID(sessionID);
}
}
return null;
}
}
I have a singleton class setting up the Ninject kernel:
public class MyKernel
{
public static StandardKernel Kernel { get; set; }
static MyKernel()
{
Kernel = new StandardKernel();
Kernel.Bind<IServiceAuthToken>().To<ServiceAuthToken>();
Kernel.Bind<UserSessionDataLayer>().To<UserSessionDataLayer>();
}
}
In my WCF service I use the PostSharp attribute as below:
[AuthoriseAndAudit(UserRoleTypesEnum.Operator)]
public JSONResult<bool> IsAliveAuthorised()
{
return new JSONResult<bool>() { Success = true, Result = true };
}
And in my unit test I'm using RhinoMocks to try and mock the two DI properties in the attribute.
[TestMethod]
public void IsAliveAuthorisedIsAuthorisedTest()
{
var mockServiceAuthToken = MockRepository.GenerateStrictMock<ServiceAuthToken>();
mockServiceAuthToken.Stub(x => x.GetSessionID()).Return("x");
var mockUserSessionDataLayer = MockRepository.GenerateStrictMock<UserSessionDataLayer>();
mockUserSessionDataLayer.Stub(x => x.GetForSessionID(Arg<string>.Is.Anything)).Return(new UserSession());
MyKernel.Kernel.Bind<ServiceAuthToken>().ToConstant(mockServiceAuthToken);
MyKernel.Kernel.Bind<UserSessionDataLayer>().ToConstant(mockUserSessionDataLayer);
var service = new MyService();
Assert.IsTrue(service.IsAliveAuthorised().Result);
}
The issue I have is the mock objects in the unit test are never ending up being set as the properties on the attribute. What am I doing wrong or conversely is there a better way to do unit testing on a PostSharp attribute? Also bearing in mind I really want to minimise the use of the Ninject DI to the bare minimum.
Instead of using the [Inject] attribute on your properties, redefine them like this:
public IServiceAuthToken _serviceAuthToken { get { return _kernel.Get<IServiceAuthToken>(); } }
public UserSessionDataLayer _userSessionDataLayer { get { return _kernel.Get<UserSessionDataLayer>(); } }
Also, in your test method you need to re-bind (note also that you were using the concrete type ServiceAuthToken in the first bind instead of the interface IServiceAuthToken):
MyKernel.Kernel.Rebind<IServiceAuthToken>().ToConstant(mockServiceAuthToken);
MyKernel.Kernel.Rebind<UserSessionDataLayer>().ToConstant(mockUserSessionDataLayer);

Avoiding Service Locator with AutoFac 2

I'm building an application which uses AutoFac 2 for DI. I've been reading that using a static IoCHelper (Service Locator) should be avoided.
IoCHelper.cs
public static class IoCHelper
{
private static AutofacDependencyResolver _resolver;
public static void InitializeWith(AutofacDependencyResolver resolver)
{
_resolver = resolver;
}
public static T Resolve<T>()
{
return _resolver.Resolve<T>();
}
}
From answers to a previous question, I found a way to help reduce the need for using my IoCHelper in my UnitOfWork through the use of Auto-generated Factories. Continuing down this path, I'm curious if I can completely eliminate my IoCHelper.
Here is the scenario:
I have a static Settings class that serves as a wrapper around my configuration implementation. Since the Settings class is a dependency to a majority of my other classes, the wrapper keeps me from having to inject the settings class all over my application.
Settings.cs
public static class Settings
{
public static IAppSettings AppSettings
{
get
{
return IoCHelper.Resolve<IAppSettings>();
}
}
}
public interface IAppSettings
{
string Setting1 { get; }
string Setting2 { get; }
}
public class AppSettings : IAppSettings
{
public string Setting1
{
get
{
return GetSettings().AppSettings["setting1"];
}
}
public string Setting2
{
get
{
return GetSettings().AppSettings["setting2"];
}
}
protected static IConfigurationSettings GetSettings()
{
return IoCHelper.Resolve<IConfigurationSettings>();
}
}
Is there a way to handle this without using a service locator and without having to resort to injecting AppSettings into each and every class? Listed below are the 3 areas in which I keep leaning on ServiceLocator instead of constructor injection:
AppSettings
Logging
Caching
I would rather inject IAppSettings into every class that needs it just to keep them clean from the hidden dependency on Settings. Question is, do you really need to sprinkle that dependency into each and every class?
If you really want to go with a static Settings class I would at least try to make it test-friendly/fakeable. Consider this:
public static class Settings
{
public static Func<IAppSettings> AppSettings { get; set; }
}
And where you build your container:
var builder = new ContainerBuilder();
...
var container = builder.Build();
Settings.AppSettings = () => container.Resolve<IAppSettings>();
This would allow to swap out with fakes during test:
Settings.AppSettings = () => new Mock<IAppSettings>().Object;
Now the AppSettings class (which I assume there is only one of) you could do with regular constructor injection. I assume also that you really want to do a resolve on each call to your settings properties, thus injecting a factory delegate that retrieves an instance when needed. If this is not needed you should of course inject the IConfigurationSettings service directly.
public class AppSettings : IAppSettings
{
private readonly Func<IConfigurationSettings> _configurationSettings;
public AppSettings(Func<IConfigurationSettings> configurationSettings)
{
_configurationSettings = configurationSettings;
}
public string Setting1
{
get
{
return _configurationSettings().AppSettings["setting1"];
}
}
public string Setting2
{
get
{
return _configurationSettings().AppSettings["setting2"];
}
}
}