1

I'm creating custom Authorization in .net core. Everything is working completely fine but I want to add localizer in attribute response.

Below is my code

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
    public class CustomAuthorizeFilters : AuthorizeAttribute, IAuthorizationFilter
    {
        public CustomAuthorizeFilters()
        { }

        public void OnAuthorization(AuthorizationFilterContext context)
        {
            var User = context.HttpContext.User;

            if (!User.Identity.IsAuthenticated)
                return;

            using (var account_help = new AccountHelpers(Startup.ConnectionString))
            {
                var userId = Guid.Parse(new security.AesAlgoridhm().Decrypt(User.Claims.Where(x => x.Type == JwtRegisteredClaimNames.Sid)?.FirstOrDefault().Value));
                ProfileResponse user = new ProfileResponse();

                if (user == null)
                    context.Result = new CustomResultFilters("error_access_token_expired", 401);

                if (!user.EmailConfirmed)
                    context.Result = new CustomResultFilters("bad_response_account_not_confirmed", 400);

                if (!user.Active)
                    context.Result = new CustomResultFilters("bad_response_account_inactive", 400);
            }
        }
    }

I've tried passing localizer in the constructor like this but when I'm passing an argument from the controller it is giving me error as

attribute constructor parameter has type which is not a valid attribute parameter type

  IStringLocalizer<dynamic> localize { get; set; }
  public CustomAuthorizeFilters(IStringLocalizer<dynamic> localizer = null)
  {
            localize = localizer;
  }

I know attribute only supports primitive datatypes that's why I've also tried injecting direct dependency as

context.HttpContext.RequestServices.GetService(typeof(IStringLocalizer<dynamic>));

but that is giving error as:

cannot convert from object to localizer.

Dale K
  • 25,246
  • 15
  • 42
  • 71
Kinjal Parmar
  • 342
  • 1
  • 3
  • 17
  • 2
    You can't use dynamic as type parameter. The string localizer requires a **TYPE**. The type is used to locate the resource file containing the translations, i.e. `IStringLocalizer` will look for a resource file named `MyController.xx-yy.resx`. If you want a shared localization resource, use a fixed class or dummy class, such as `IStringLocalizer` where `SharedResources` is just an empty class `public class SharedResources { }` – Tseng Apr 04 '19 at 07:20
  • 3
    Also see [docs](https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.2#servicefilterattribute) on how to do dependency injection into attributes using the `ServiceFilter` attribute – Tseng Apr 04 '19 at 07:23
  • you could try define the localizer string in shared resource, and pass `SharedResource`, refer [Make the app's content localizable](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/localization?view=aspnetcore-2.2#make-the-apps-content-localizable) – Edward Apr 05 '19 at 05:50

1 Answers1

2

You can use shared resources and get localizer like this

Type localizerType = typeof(IStringLocalizer<SharedResource>);
IStringLocalizer localizer = (IStringLocalizer)context.HttpContext.RequestServices.GetService(localizerType );

Or if you are using resources per controller you can get controller type from context and get controller localizer

public void OnAuthorization(AuthorizationFilterContext context)
{
    //..
    Type localizerType = GetLocalizerType(context);
    IStringLocalizer localizer = (IStringLocalizer)context.HttpContext.RequestServices.GetService(localizerType);
    //..
}

private Type GetLocalizerType(AuthorizationFilterContext context)
{
    var controllerType = (context.ActionDescriptor as ControllerActionDescriptor).ControllerTypeInfo;
    return typeof(IStringLocalizer<>).MakeGenericType(controllerType);
}
Alexander
  • 9,104
  • 1
  • 17
  • 41