how do I get access to the object that I'm intercepting? - c#

I'm using Castle Core to create a custom attribute and interceptor to inject security checks into our code using attributes.
e.g. [Security("Role1")]
In the implementation of the interceptor:
public class SecurityInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
object o;
MethodInfo mi = invocation.Method;
SecurityAttribute[] atts = (SecurityAttribute[])mi.GetCustomAttributes(typeof(SecurityAttribute), true);
// if method not marked with Security attribute, then pass on call
if (atts.Length == 0)
{
invocation.Proceed();
}
else
{
//for now assume that there is only one security attribute on the method
//do some security test
{
invocation.Proceed();
}
}
}
In the "do some security test" section above, I need access to the HttpContext.Session object in order to retrieve some saved objects to do the security test.
Assume the method that this attribute is on, is a code-behind asp.net page, i.e an instance of the Page class)
I can't just use this.Context in the attribute like this [Security("Role1", this.Context)]
as attributes don't allow that.
So how do I get access to the httpContext inside the Intercept method?
Or is there a better way of doing this in an aspect-like way?

The InvocationTarget property of the IInvocation instance has the target object. So in your case, if you are certain that the interception happens on a Page object, you should be able to do this:
var page = (Page)invocation.InvocationTarget;
If that is not always the case, you should gain access to the HTTP context in another way.
It's true, as Ben points out, that HttpContext.Current gives you access to the current HttpContext from anywhere, but accessing that static property is just icky. There's a better way, however, and that is by registering a factory method that allows for injection of the session state:
container.Register(
Component.For<ISessionState>()
.UsingFactoryMethod(k => new SessionWrapper(HttpContext.Current.Session)
.Lifestyle.PerWebRequest));
assuming that you have created the ISessionState interface and an appropriate wrapper that has the API you wish to use when interacting with the ASP.NET HttpSessionState object.
Now, since the interceptor is pulled from the container like everything else, it can depend on ISessionState:
public class SecurityInterceptor : IInterceptor
{
public SecurityInterceptor(ISessionState sessionState)
{
//...
}
}
which makes your interceptor nice and testable.
There's probably many other ways to do this, and possible better ways as well. This is just an idea on how you can get on with your project :)

You can use HttpContext.Current.Session from anywhere so long as the code is being called from an ASP.net process.

Related

Detect whether I am running from an HttpContext of a ThreadContext

With StructureMap, I am registering an interface as follow:
public class PersistenceRegistry : Registry
{
public PersistenceRegistry()
{
For<IClearableSessionProvider>().HybridHttpOrThreadLocalScoped().Use<FirebirdSessionProvider>();
}
}
I would like to know if it is possible to detect by any ways if the resolved instance is resolved from an HttpContext or a "ThreadContext". I don't even need to have access to the context. I just want to know whether I am in the context of an HttpRequest or from a background thread.
I tried several things consisting of injecting the HttpContext if it exists, but whatever I tried, I always get a null reference.
I tried to register an IHttpContextProvider:
public interface IHttpProvider
{
HttpContext GetHttpContext();
}
public class HttpProvider
{
HttpContext GetHttpContext()
{
return HttpContext.Current;
}
}
But HttpContext.Current is always null (even once I get into the controller call).
I tried to register an HttpContextWrapper but also always null:
For<HttpContextBase>().Use(() => new HttpContextWrapper(HttpContext.Current))
I am using StructureMap-2.6.3.0. I am not sure how to formulate correctly but the app is built upon OWIN (which explains why my attempts always return null if I understand correctly what I have been reading before coming here).

Unity - resolving dependencies based on some condition

I have layered asp.net MVC application.
In the service layer, I have a container to register dependencies. e.g:
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<ISomething, Something>();
}
Based on the design, we need to have a mock implementation of the
classes if the user decided to open the application for testing purpose.
So, I came up with an Idea like
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<ISomething, Something>();
container.RegisterType<ISomething, SomethingMock>();
}
If I use a flag somewhere to indicate whether or not system runs at testing mode, how can I make a decision on which dependency to resolve at the runtime?
If it is not an elegant solution, what could be the alternative?
If I use a flag somewhere to indicate whether or not system runs at testing mode, how can I make a decision on which dependency to resolve at the runtime?
You should not change the structure of your object graph based on runtime decisions. This is very much related to the anti-pattern of injecting runtime data into components.
In case you require to switch implementations based on runtime conditions (meaning: the value might change from request to request), the solution is to create a proxy class that implements ISomething and wraps the two ISomething implementations (this article shows some examples of proxy implementations). When ISomething.Method is called, it can forward the call to the right implementation, based on the runtime condition that it determines at that point.
In your case however, you are most likely not talking about runtime conditions, but about a configuration value. Configuration values don't change during the lifetime of the application. Only after a restart (or redeploy) you would typically see a change of value.
That means that you can simply read the configuration value at startup and decide at that point which implementation should be registered:
if (bool.Parse(ConfigurationManager.AppSettings["Production"]))
{
container.RegisterType<ISomething, Something>();
}
else
{
container.RegisterType<ISomething, SomethingMock>();
}
While I fully support Stevens answer and his considerations, there is technically a way to do what you intended.
You can use named registration:
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<ISomething, Something>();
container.RegisterType<ISomething, SomethingMock>("SomethingMock");
}
and then use a string parameter to resolve it:
string s= "";
var mySomething = container.Resolve<ISomething>(s); // will return standard implementation
s = "SomethingMock"
var mySomething = container.Resolve<ISomething>(s); // will return mock implementation
you would need to intercept when asp wants to resolve ISomething.
For reference see
https://msdn.microsoft.com/en-us/library/ff660923%28v=pandp.20%29.aspx
Now it's up to you which way you go.

MVC5 Ninject binding and HttpContext

I am trying to set up a new project and I've added a new class MembershipService that requires the HttpContext to be passed in it's constructor.
In a previous project I used the code
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IMembershipService>()
.To<MembershipService>()
.InRequestScope()
.WithConstructorArgument("context", HttpContext.Current);
....
}
However in the new project I'm using Ninject Modules, and after some searching on StackOverflow and Google, I've come up with the code below:
public class ServiceHandlerModule : NinjectModule
{
public override void Load()
{
Bind<IMembershipService>()
.To<MembershipService>()
.WithConstructorArgument("context", ninjectContext=> HttpContext.Current);
this.Kernel.Bind(x =>
{
x.FromAssemblyContaining(typeof(NinjectWebCommon))
.SelectAllClasses()
.Where(t => t != typeof(MembershipService))
.BindDefaultInterface();
});
this.Kernel.Bind(x =>
{
x.FromAssemblyContaining<BrandServiceHandler>()
.SelectAllClasses()
.Where(t => t != typeof(MembershipService))
.BindDefaultInterface();
});
}
}
However, I get the error below:
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: Ninject.ActivationException: Error activating
string No matching bindings are available, and the type is not
self-bindable. Activation path:
5) Injection of dependency string into parameter filename of
constructor of type HttpRequest
4) Injection of dependency HttpRequest into parameter request of
constructor of type HttpContext
3) Injection of dependency HttpContext into parameter httpContext of
constructor of type MembershipService
2) Injection of dependency IMembershipService into parameter
membershipService of constructor of type HomeController
1) Request for HomeController
Can someone point out where I'm going wrong?
Thanks,
John
Steven was right about the HttpContext being a runtime value. Its values are not even populated at the time the application is composed.
This makes sense if you think about it because the application should be initialized outside of any individual user context.
However, Steven's solution only moved the problem to a different service. After all, the class that implements IUserContext will still need to take HttpContext as a dependency.
The solution is to use an Abstract Factory to allow the HttpContext instance to be accessed at runtime instead of when the factory is wired up.
Important: HttpContext is not an abstraction, so it cannot be swapped or mocked. To ensure we are dealing with an abstraction, Microsoft has provided the HttpContextBase abstract class and the default concrete type HttpContextWrapper. HttpContextBase has exactly the same interface as HttpContext. You should always use HttpContextBase as the abstract reference type within your services, not HttpContext.
With those 2 things in mind, you can create a factory for your HttpContext, as follows:
public interface IHttpContextFactory
{
HttpContextBase Create();
}
public class HttpContextFactory
: IHttpContextFactory
{
public HttpContextBase Create()
{
return new HttpContextWrapper(HttpContext.Current);
}
}
Your MembershipService can then be modified to accept an IHttpContextFactory in its constructor:
public class MembershipService : IMembershipService
{
private readonly IHttpContextFactory httpContextFactory;
// This is called at application startup, but note that it
// does nothing except get our service(s) ready for runtime.
// It does not actually use the service.
public MembershipService(IHttpContextFactory httpContextFactory)
{
if (httpContextFactory == null)
throw new ArgumentNullException("httpContextFactory");
this.httpContextFactory = httpContextFactory;
}
// Make sure this is not called from any service constructor
// that is called at application startup.
public void DoSomething()
{
HttpContextBase httpContext = this.httpContextFactory.Create();
// Do something with HttpContext (at runtime)
}
}
And you need only inject the HttpContextFactory at composition time.
kernel.Bind<IHttpContextFactory>()
.To<HttpContextFactory>();
kernel.Bind<IMembershipService>()
.To<MembershipService>();
This alone might not solve the entire issue, though. You need to ensure that the rest of your application does not try to use HttpContext before it is ready. In terms of DI, it means you can't use HttpContext in any constructor of types that are composed in application start or any service members that one of those constructors calls. To solve that, you may need to create additional abstract factories to ensure those services don't call members of IMembershipService until HttpContext is ready.
See this answer for more information about how to accomplish that.
Steven's solution also entailed creating a Facade around HttpContext. While this does not really help solve the problem at hand, I agree that this might be a good idea if your MembershipService (and perhaps other services) only uses a small number of members of HttpContext. Generally, this pattern is to make a complex object simpler to work with (such as flattening it down to a few members that may be nested deep within its hierarchy). But you really need to weigh the extra maintenance of adding another type against the complexity of using HttpContext within your application (or the value of swapping out a section of it) to make that decision.
I've added a new class MembershipService that requires the HttpContext
to be passed in it's constructor.
This is where you're going wrong. The HttpContext is a runtime value, but your object graph should only consist of compile-time or configuration-time dependencies. Anything else, the runtime values, should either be passed through method calls, or should be exposed as properties from the services that are injected.
Not following this guideline, will make it much harder to compose and test your object graphs. Testing your composition root is a good example, since HttpContext.Current is not available when run inside a testing framework.
So prevent this MembershipService from taking a constructor dependency on HttpContext. Instead, inject a service that exposes the HttpContext as a property, because this allows you to request this context after the object graph is constructor.
But perhaps even better is to hide the HttpContext behind an abstraction that is application specific. HttpContext is not an abstraction; it is a big and ugly API that makes your code much harder to test and much harder to comprehend. Instead, create very narrow/focused interfaces, for instance an interface like this:
public interface IUserContext
{
User CurrentUser { get; }
}
Now your MembershipService can depend on a IUserContext that exposes a User object through a property. Now you can create an AspNetUserContext implementation that uses the HttpContext.Current internally, when the CurrentUser property is called. This results in much cleaner, more maintainable code.
Here's a possible implementation:
public class AspNetUserContext : IUserContext
{
public User CurrentUser
{
// Do not inject HttpContext in the ctor, but use it
// here in this property
get { return new User(HttpContext.Current.User); }
}
}
I agree with Steven, however, you could also:
kernel.Bind<HttpContext>().ToMethod(c => HttpContext.Current);

Simple Injector Scope for specific LifeStyle

Is there a way to define a scope for a specific lifestyle? I am attempting to implement my own scope that I want to persist across an application, but internally I also create another scope, and then a request to GetInstance returns the inner scoped instance instead.
I thought if I could define my lifestyle as:
public class MyScopedLifestyle : ExecutionContextScopeLifestyle
{
public MyScopedLifestyle(bool disposeInstanceWhenScopeEnds)
: base("MyScopedLifestyle", disposeInstanceWhenScopeEnds)
{
}
protected override int Length
{
get
{
return 100;
}
}
}
And my usage is:
var container = new Container();
container.Register<IRequestData, RequestData>(new MyScopedLifestyle());
// i had hoped I could say
// container.BeginExecutionContextScope(MyScopedLifestyle)
// or something similar
// this is controlled by me
using (var scope1 = container.BeginExecutionContextScope())
{
// do some stuff
container.GetInstance<IRequestData>().RequestMarket = "en-US";
// this is done via the webapi execution scope (using simpleinjector dependency resolver)
using (var scope2 = container.BeginExecutionContextScope())
{
Assert.Equal("en-US", container.GetInstance<IRequestData>().RequestMarket); // false
}
}
But I'm unsure how to utilize my custom lifestyle when creating the inner execution scope.
What I really want to happen, is that my instance of IRequestData used in scope1, is the same instance of IRequestData inside of scope2. Is this something I can achieve with SimpleInjector?
Edit
I removed the fact that I'm attempting to create an instance of an object per OWIN request, rather than per WebAPI request. Ideally I'm attempting to create:
container.RegisterOwinRequest<IRequestData, RequestData>();
So that when I resolve IFoo anywhere within my pipeline (be it an OWIN middleware, or in the WebAPI part, the same instance is returned for a particular request).
Edit 2
Swapped our IFoo/Foo/MyProperty for better names.
What you're trying to accomplish with a custom lifestyle is absolutely possible, but might not be that easy, because you will have to store that scope somewhere (probably in the CallContext) and need to create a BeginMyCustomScope method that creates a new scope and have a custom Scope implementation that removes itself from the CallContext when Dispose is called. I think this is too much work and too much complexity.
The problem exists because during the time you want to set the RequestMarket property, there is no Web API request scope started. The way to usually force such scope to be started is to call the GetDependencyScope method on the HttpRequestMessage:
message.GetDependencyScope();
Right after that you can resolve the IRequestData and it works as expected:
container.GetInstance<IRequestData>().RequestMarket = "en-US";
I'm unsure however, whether the HttpRequestMessage is available at that point in time, so if not, I think working with a DelegatingHandler as you expressed in the comments is a good alternative.
In the past, a good way to communicate data across the callstack was using thread-specific variables, but that obviously fails when using async/await models as with Web API and OWIN. So the new way to do this is using the CallContext. So instead of using a DelegatingHandler, you might be able to do something like this:
container.RegisterInitializer<IRequestData>(data =>
data.RequestMarket = (string)CallContext.LogicalGetData("RequestMarketKey"));
And when the OWIN request starts, you do this:
CallContext.LogicalSetData("RequestMarketKey", "en-US");

Simple Injector FilterInjection seems to be reinitialising RegisterPerWebRequest injected item

I'm trying to move from Ninject to Simple Injector but I'm experiencing an odd issue when trying to duplicate functionality that worked with Ninject.
In Ninject I had a service which contained:
private readonly ICollection<Message> messages;
This service was registered as
Bind<INotificationService>().To<NotificationService>()
.InRequestScope();
This service allowed messages (UI and error) to be passed back to the MVC site.
This service was injected into an ActionFilterAttribute:
kernel.BindFilter<CriticalErrorAttribute>(FilterScope.Last, 1)
.When((context, ad) =>
!string.IsNullOrEmpty(ad.ActionName) &&
ad.ControllerDescriptor.ControllerName.ToLower() != "navigation");
and used within OnActionExecuted.
Because the service was registered to Ninject with InRequestScope, any items pushed to the message queue were available in the Actionfiter. This allowed for a redirect to an error page (displaying critical errors) if necessary.
I've tried to duplicate this with simpleinjector:
container.RegisterPerWebRequest<INotificationService, NotificationService>();
container.RegisterInitializer<CriticalErrorAttribute>(handler =>
{
handler.NotificationService =
container.GetInstance<INotificationService>();
});
The injection is working fine, but even though the message collection contains messages prior to entering the ActionFilter, once in the filter the message collection is empty. It's like the RegisterPerWebRequest is being ignored.
Any help in solving this issues would be appreciated.
UPDATE:
In Simple Injector 2.5 a new RegisterMvcIntegratedFilterProvider extension method has been added to the MVC Integration package that replaces the old RegisterMvcAttributeFilterProvider. This new RegisterMvcIntegratedFilterProvider contains the behavior of the SimpleInjectorFilterAttributeFilterProvider that is given below and allows better integration of attributes into the Simple Injector pipeline. This does mean however that by default, no properties are injected, but this can extended by implementing a custom IPropertySelectionBehavior. The use of the new RegisterMvcIntegratedFilterProvider is adviced over the old RegisterMvcAttributeFilterProvider method, which will be marked [Obsolete] in a future release.
When using the RegisterMvcAttributeFilterProvider extension method, Simple Injector will not call any registered initializer on MVC attributes. If you set a break point inside the anonymous delegate that injects the NotificationService you'll see it's never hit.
Simple Injector does however call the container.InjectProperties method on MVC attributes, but InjectProperties does implicit property injection, which means that it tries to inject all public properties on a type, but skips it if the property can't be injected (for what ever reason).
I bet the CriticalErrorAttribute.NotificationService property has a type of NotificationService instead of INotificationService. Since you didn't register NotificationService explicitly, the container will create a transient instance for you, which means you'll get a different instance for the CriticalErrorAttribute than the rest of the application is getting.
Quick fix: change the property type to INotificationService.
To be honest, I regret ever implemented the MVC integration package for Simple Injector to use the InjectProperties method. Implicit Property injection is very evil, because it doesn't fail fast when there's a misconfiguration and I'm even thinking about removing support for InjectProperties in the future. The problem is however that many developers are depending on InjectProperties. Either directly by calling it, or indirectly by letting the container inject properties on MVC attributes.
InjectProperties does not run any initializer. That's by design, and there are other constructs that allow running the full initialization process on objects that are not created by the container. Problem is however, that adding this could break existing clients, since this could result in properties being injected multiple times.
In your case, I suggest a different solution:
Prevent calling container.RegisterMvcAttributeFilterProvider() in the startup path of your application. This will register a special FilterAttributeFilterProvider that calls InjectProperties internally. You don't want to use implicit property injection, you want a more explicit (and complete) behavior. Instead register the following class:
internal sealed class SimpleInjectorFilterAttributeFilterProvider
: FilterAttributeFilterProvider
{
private readonly ConcurrentDictionary<Type, Registration> registrations =
new ConcurrentDictionary<Type, Registration>();
private readonly Func<Type, Registration> registrationFactory;
public SimpleInjectorFilterAttributeFilterProvider(Container container)
: base(false)
{
this.registrationFactory = type =>
Lifestyle.Transient.CreateRegistration(type, container);
}
public override IEnumerable<Filter> GetFilters(
ControllerContext context,
ActionDescriptor descriptor)
{
var filters = base.GetFilters(context, descriptor).ToArray();
foreach (var filter in filters)
{
object instance = filter.Instance;
var registration = registrations.GetOrAdd(
instance.GetType(), this.registrationFactory);
registration.InitializeInstance(instance);
}
return filters;
}
}
You can use the following code to register this custom provider:
var filterProvider =
new SimpleInjectorFilterAttributeFilterProvider(container);
container.RegisterSingle<IFilterProvider>(filterProvider);
var providers = FilterProviders.Providers
.OfType<FilterAttributeFilterProvider>().ToList();
providers.ForEach(provider => FilterProviders.Providers.Remove(provider));
FilterProviders.Providers.Add(filterProvider);
This custom SimpleInjectorFilterAttributeFilterProvider calls the Registration.InitializeInstance method. This method allows initialization a type that is already created and will initialize it by (among other things) calling the type initializer delegates.
For more information about working with attributes, please read the following discussion.

Categories

Resources