AutoFac Injection into attribute - dependency-injection

So I have a need for injecting a number of different services into an authorization attribute I'm using. For simplicity I will leave this to show the configuration manager.
public class FeatureAuthorizeAttribute : AuthorizeAttribute
{
public IConfigurationManager ConfigurationManager;
private readonly string _feature;
public FeatureAuthorizeAttribute(string feature)
{
_feature = feature;
var test = ConfigurationManager.GetCdnPath();
}
}
Which would be used as follows
[FeatureAuthorize("Admin")]
I have tried to use constructor injection
public FeatureAuthorizeAttribute(string feature, IConfigurationManager configurationManager)
{
ConfigurationManager = configurationManager;
_feature = feature
}
However this just causes an error when I attempt
[FeatureAuthorize("Admin", IConfigurationManager)]
Which seems like the wrong way to go about it in the first place. I'm assuming that I need to register my custom authorization attribute with the container to get it to start picking up

Instead of trying to use Dependency Injection with attributes (which you can't do in any sane, useful way), create Passive Attributes.
Specifically, in this case, assuming that this is an ASP.NET MVC scenario, you can't derive from AuthorizeAttribute. Instead, you should make your Authorization service look for your custom attribute, and implement IAuthorizationFilter. Then add the filter to your application's configuration.
More details can be found in this answer: https://stackoverflow.com/a/7194467/126014.

Related

Can I use Ninject to inject dependencies into attributes rather than using the service locator pattern?

I'm using feature flags to selectively enable/disable certain aspects of my MVC4 web application in different environments. I have an interface named IConfiguration with a IsEnabled(FeatureFlag) method that provides access to these flags.
To this end, I want to disable certain MVC action methods when the feature they relate to is turned off. I have an attribute named FeatureAttribute defined like this:
// Usage: [Feature(FeatureFlag.I18N)]
public class FeatureAttribute : ActionMethodSelectorAttribute {
private IConfiguration _config;
private FeatureFlag _feature;
public FeatureAttribute(FeatureFlag feature) {
_config = DependencyResolver.Current.GetService<IConfiguration>();
_feature = feature;
}
public override bool IsValidForRequest(ControllerContext controllerContext,
MethodInfo methodInfo) {
return _config.IsEnabled(_feature);
}
}
This works, but using DependencyResolver to get an instance of IConfiguration smells funny. Is there any way I can redesign my code to avoid the Service Locator pattern?
I initially thought of using filter injection, but ActionMethodSelectorAttribute is not actually a filter, so it doesn't apply here.
Attributes are created by the .NET Framework. So you can't do Constructor injection. The only two ways to inject into Attributes is to do PropertyInjection or ServiceLocation.
PropertyInjection can be done like this:
Add a IPlanningStrategy that does the scanning with reflection for your attribute (or ActionMethodSelectorAttribute). Return immediatly if not a controller.
Foreach method that has this attribute add a IDirective that contains a reference to the MethodInfo
Add A IActivationStrategy that injects the attribute using kernel.Inject(attribute).
Best you have a look at the PropertyInjection implementation of Ninject it works exactly like this. It just needs some changes to do what you want.

Accessing IAuthSession in non-controller classes in ServiceStack/MVC4

I am new to ServiceStack, so this is probably a noob question:
I am working on an ASP.NET MVC4 application that uses ServiceStack and am trying to figure out how I could get a hold of the current IAuthSession from within a class (either a EF context or a PetaPoco Database) used by my MVC4 controllers derived from ServiceStackController.
The class in question is registered with Funq with the ReuseScope.Request scope (i.e. on the per-HTTP request basis), and ideally I'd like every instance of it to be autowired with the current IAuthSession using either a constructor parameter or a public property.
How do I do that?
UPDATE
After some digging I came up with what I think might work.
In my AppHost.Configure I register a lambda that returns a session from the current request:
container.Register<IAuthSession>(c =>
HttpContext.Current.Request.ToRequest().GetSession());
Also:
container.RegisterAutoWired<EFCatalogDb>();
where EFCatalogDb is my EF context that takes IAuthSession as a constructor argument:
public class EFCatalogDb : DbContext
{
public EFCatalogDb(IAuthSession session) : base()
{ }
// ...etc....
}
Unfortunately I am not at the point in my development when I can test this workaround, so have to ask others if it makes sense at all.
My first suggestion would be to try to keep IAuthSession out of your database classes since that creates a dependency on ServiceStack that seems unnecessary.
That being said, I think you could go the route of registering IAuthSession and having the container automatically inject IAuthSession. A better way might be creating your own 'wrapper class' around IAuthSession and injecting that into your database classes. That would then break the dependency on ServiceStack.
If you have no issue keeping a dependency on ServiceStack another possibility would be using the SessionFeature class and doing something like
var key = SessionFeature.GetSessionKey();
authSession = AppHost.Resolve<ICacheClient>().Get<IAuthSession>(key);

Autofac 2.6 and Orchard 1.6 - Action Filter construction injection

To begin with two things.
I am trying to achieve an action filter that logs when and action begins and when it end
I am well aware of the .AsActionFilter() method in Autofac 3.0 BUT...
The project that this is using is based in Orchard 1.6 which is known to be compatible with autofac 2.6.xxx. We do not want to go through a potentially lengthy process of upgrading to Autofac 3.0 at this time so the .AsActionFilter() option is not available to us.
The other option is to set the filter (which extends ActionFilterAttribute) as an attribute on our base controller (from which all other inherit btw). The problem is that the filter itself has two dependencies:
A service of our own that holds information on the context
An implementation of an ILoggingService
What I cannot find is a way to inject these into the actual property at the head of the class. Does anyone know a way in which to achieve this either through the [Attribute] line itself of some function of Autofac during registation?
The ActionFilterAttribute:
public class GRMSActionLoggingFilter : ActionFilterAttribute {
private readonly IGRMSCoreServices _grmsCoreServices;
private readonly ILoggingService _loggingService;
public GRMSActionLoggingFilter(IGRMSCoreServices grmsCoreServices, ILoggingService loggingService) {
_grmsCoreServices = grmsCoreServices;
_loggingService = loggingService;
}
public GRMSActionLoggingFilter() { }
public override void OnActionExecuting(ActionExecutingContext actionContext) {...}
public override void OnActionExecuted(ActionExecutedContext actionContext) {...}
}
Assigning the attribute to the base controller:
// This currently compiles but will fail during run time as the IGRMSCoreSerivces and ILoggingService will both be null. Need to property inject these services somehow.
[GRMSActionLoggingFilter]
Anyone have any idea to achieve this?
You cannot (easily) inject runtime values to attributes.
This is how attributes work in C# - you can only pass constant values of certain types. You can read more about it here.
In order to achieve desired functionality in Orchard you need to split your code into two components:
a marker attribute class you put on your action
an action filter class inheriting from FilterProvider and implementing IActionFilter
The way it works is that you put an attribute on some action and then use the action filter to check existence of that attribute (using filterContext.ActionDescriptor.GetCustomAttributes(...)). If an attribute exists, do your stuff.
There are lots of examples of this technique in Orchard core. Check eg. the ThemedAttribute and ThemeFilter action filter classes.

MVC DisplayNameAttribute and Ninject: Possible?

Let's assume following basic Project-Setup:
- Core
-- Attributes
--- CustomDisplayNameAttribute : DisplayNameAttribute
- UI
UI represents the MVC Web interface, the core implements all the domain business objects, including self written attributes like CustomDisplayNameAttribute. This attribute contains additional dependencies like a language resolver, which e.g. deals with fallback orders. Hibernate sessions would be another possible dependency.
In earlier projects, these attributes did a global request in order to get the resolver. This is IMO ugly and should be handled differently. Furthermore, Core should stay without HttpContext: since the language-resolver is required per request, it might end up in HttpContext Items Collection.
Now I am quite a beginner with Ninject, and I am not sure if it is the right tool in order to get such dependencies into something like a CustomDisplayNameAttribute?
In words it would be something like this:
If the attribute is created, populate the additional language resolver property with the language resolver from HttpContext Items Collection
If there is no HttpContext (e.g. testing, quartz jobs etc.), get it from somewhere else.
Thx for any inputs
Edit: Sample-Code
namespace Core.Attributes
{
public class CustomDisplayNameAttribute : DisplayNameAttribute
{
private string textCode;
/// <param name="textCode">According to this Text-Code, we will load
/// and resolve the text.</param>
public DeimosDisplayNameAttribute(string textCode)
{
this.textCode = textCode;
}
/// <summary>
/// Load and resolve Text according to Text-Code
/// </summary>
public override string DisplayName
{
get
{
// Load - Ooops: First global access
// --> How can it be injected with IoC?
TextbausteinRepository repo = Root.GetTextBausteinRepository();
var textItem = repo.GetText(textCode);
// Resolve - Ooops: Second global access
// --> How can it be injected with IoC?
TextResolver resolver = Root.GetTextResolver();
return resolver.resolve(textItem);
}
}
}
}
Edit 2: In that context, it seems that there is no way around a global access, like a registry pattern or similar. UI would register the needed data in there, and the attributes would access it from there. We started to think about storing it in ThreadLocal<T>, but this seems not really save due to the fact that there is a possibility of thread-swapping during the life-cycle. So there seems no way around storing HttpContext in the registry layer. For more info about this subject, see [Cup(Of T)][1].
I don't think this is possible, because data attributes are not run-time dispatched like filters are. As such, there's no place to intercept the creation and inject what you're looking for.

Dependency injection and ASP.Net Membership Providers

I am in the process of creating a custom membership provider for an ASP.Net MVC website. The provider is being created as a separate class as part of a bigger library. There is a need for the back-end data store to be flexible as it could be an Xml File or SQL database. My initial thought was to create an interface for the data store and inject this into provider using dependency injection.
The end result is required is that a developer can inherit the data store interface and provide the required methods to update the data, which will then be used by the custom membership providers.
However through my own lack of skill I can't figure out how to inject the class into the membership provider when adding it to the website? What needs to be done to link the data store to the provider? What would be the simplest way to enable this in the website?
If you are configuring the custom membership providers via the <membership> element in the Web.config file, then I can see the issues you will have with dependency injection.
The providers are constructed and managed by the framework, and there is no opportunity for you to intercept that construction to provide additional dependency injection for the IDataStore interface.
If my assumption is correct, then what you can do is override the Initialize() method in your custom provider, and do the dependency injection there. You can have a custom name/value setting in the provider configuration which points to a type that implements IDataStore, which is passed as part of a dictionary to the Initialize() method.
Then, you activate an instance of the data store type and set it on the appropriate property:
public class MyMembershipProvider : MembershipProvider
{
public IDataStore DataStore
{
get;
set;
}
public override Initialize(string name, NameValueCollection config)
{
var dataStoreType = config["dataStoreProvider"];
if (!String.IsNullOrEmpty(dataStoreType))
{
var type = Type.GetType(dataStoreType);
DataStore = (IDataStore) Activator.CreateInstance(type);
}
}
}
Initialize() will be called by the framework after it constructs an instance of your provider, so that is the perfect place to do any additional setup work such as this.
For testing scenarios, you just set the data store property on the provider instance itself, as you will be constructing it directly in your tests.
Isn't this better? I use it with MVC3 and ninject. It's enough to add a property to your custom membership provider class. Remember to add "using System.Web.Mvc;" on top.
public IRepository Repository
{
get
{
return DependencyResolver.Current.GetService<IRepository>();
}
}
The simplest way to do dependency injection that I've seen (and actually the only one I've used so far...) is to have a constructor of your dependent class take the interface as a parameter, and assign it to a private field. If you want, you can also add a "default" constructor, which chains to the first one with a default value.
Simplified, it would look something like this:
public class DependentClass
{
private IDataStore _store;
// Use this constructor when you want strict control of the implementation
public DependentClass(IDataStore store)
{
this._store = store;
}
// Use this constructor when you don't want to create an IDataStore instance
// manually every time you create a DependentClass instance
public DependentClass() : this(new DefaultDataStore()) { }
}
The concept is called "Constructor chaining", and there's a lot of articles on the web on how to do it. I find this tutorial very explanatory of the DI pattern.

Resources