How to access IHttpRequest from my custom serializer in ServiceStack - c#

We have custom serializers for our Models that protect sensitive data depending on the request path. (For instance, if the request does not start with "/admin").
Up until now, we've tried registering the IHttpRequest with the Funq container on a RequestFilter with ReuseScope.None or ReuseScope.Request and on the serializers, we're getting the IHttpRequest from the container.
We found out that if there are multiple requests pending, the container will return that last registered IHttpRequest, which will not always be the correct request object.
I know that we could try to implement this protection of sensitive data on our models applying filter attributes, but that's very cumbersome, since our model object are often embedded in other objects or collections.
Having the serializer to do it is by far the best solution for us, if it werent for this issue of not being able to get the correct HttpRequest object from within the serializers.
So, what would be the correct way to do this? Or is this a bad practice?
Here a few code samples:
So this is a private method that my serializers use to define if they're being serialized within a "admin" route or not:
private bool IsAdminRoute() {
var path = container.Resolve<IHttpRequest> ().PathInfo;
var res = path.StartsWith ("/admin");
return res;
}
Here's the use of it:
public Question QuestionSerializer(Question question)
{
if (!IsAdminRoute())
{
// do stuff like nullyfying certain properties
}
return question;
}
On my AppHost initialization I have:
void ConfigureSerializers(Funq.Container container)
{
Serializers = new CustomSerializers ();
// ...
JsConfig<Question>.OnSerializingFn = Serializers.QuestionSerializer;
// ...
}
public void HttpRequestFilter(IHttpRequest httpReq, IHttpResponse httpRes, object dto) {
Container.Register <IHttpRequest>(c => httpReq).ReusedWithin (Funq.ReuseScope.Request);
}
Note: I'm using ServiceStack v3.

I managed to make it work by registering the IHttpRequest this way:
container.Register(c => HttpContext.Current.ToRequestContext ().Get<IHttpRequest>()).ReusedWithin(Funq.ReuseScope.None);
Now, I am always getting the IHttpRequest object I am supposed to when I try to resolve them.
Also, after more thourough tests in my application I was able to detect that everything that was relying on registering with ReuseScope.Request was getting mixed up if the concurrency was high enough.
The solution was quite simple, I am relying now on the HttpContext.Current.Items collection for storing these request-specific dependencies and registering them on a request filter like this:
HttpContext.Current.Items ["Token"] = token;
container.Register<Token> (c => (Token)HttpContext.Current.Items["Token"]).ReusedWithin(Funq.ReuseScope.None);
Now it works as it was supposed to every time.

Related

Associate class instance to Session in asp.net core

I'm currently working on a webserver in asp.net core.
I want the server to process the users input and data and am looking for a good solution to save complex Objects for the runtime.
So my first approach was to use Sessions. In Asp.net, sessions used to work like Session["key"] = new ValueObject()
In asp.net core however you can only use the methods SetString, SetInt32 and Set for byte arrays. I found a lot of solutions which basically converted the objects into Json strings. However in my case this isn't possible due to the objects containing other object references and more.
My second idea was to create a list of objects with the SessionId as identifier. Problem with this is that every time I would make request to the server, it needs to go through all existing Sessions to find the matching one, so this would probably drastically increase the time for the request.
So my question is what would be the best way to save user related objects?
Is using Sessions even the best way for solving this problem or am I missing something?
Note: Request are handled by JQuery AJAX, so reloading the page for accessing data is not an option.
You could try using the MemoryCache that can hold any .net type. It is not a problem but given it is a shared structure, it will be shared to all users, so, you have to carefull manage it. To do it, you could use HttpContext.Session.Id to define the keys on the memory cache instance. For sample (pseudo-code I didn't test):
public class HomeController : Controller
{
private IMemoryCache _cache;
public HomeController(IMemoryCache memoryCache)
{
_cache = memoryCache;
}
public async Task<IActionResult> CacheGetOrCreateAsynchronous()
{
string cacheKey = $"{HttpContext.Session.Id}_data";
var cacheEntry = await
_cache.GetOrCreateAsync(cacheKey , entry =>
{
entry.SlidingExpiration = TimeSpan.FromSeconds(3);
return Task.FromResult(DateTime.Now);
});
return View("Cache", cacheEntry);
}
}

NancyFx per module or per route serialization

I use NancyFx, I've tried to find the answer prior to question.
I have a single return type per module, but in different URL routes I need to serialize it differently, just specific properties.
If I wire serialization in Nancy pipeline, it touches all routes.
Is it possible to customize serialization per route or module without copy pasting the same type in different namespaces?
Not certain what to specifically recommend without better understanding the requirements.
Consider implementing a response processor.
In your implementation of CanProcess you can examine the NancyContext to evaluate your rule for which serialization scheme to use.
Example:
public ProcessorMatch CanProcess(MediaRange requestedMediaRange, dynamic model, NancyContext context)
{
return context.Request.Path != "/" &&
!context.Request.Path.StartsWith("/someroute/") &&
!context.Request.Path.StartsWith("/someotherroute") &&
!context.Request.Path.StartsWith("/login")
? new ProcessorMatch
{
ModelResult = MatchResult.DontCare,
RequestedContentTypeResult = MatchResult.ExactMatch
}
: new ProcessorMatch
{
ModelResult = MatchResult.DontCare,
RequestedContentTypeResult = MatchResult.NoMatch
};
}
See https://github.com/NancyFx/Nancy/wiki/Content-Negotiation
Consider: content negotiation using WithMediaRangeModel for the route.
Enables you to define media type specific models that should be used
during negotiation. The negotiation pipeline will first attempt to
find a media type specific model to use and will fallback to the
default model, which is specified using WithModel, if it fails.
I've come up with 2 solutions:
Derived type with JsonConvert attribute on corresponding overriden props;
Using serialization within module and return a string.

SimpleInjector - Register Object that depends on values from another registered object

Using SimpleInjector, I am trying to register an entity that depends on values retrieved from another registered entity. For example:
Settings - Reads settings values that indicate the type of SomeOtherService the app needs.
SomeOtherService - Relies on a value from Settings to be instantiated (and therefore registered).
Some DI containers allow registering an object after resolution of another object. So you could do something like the pseudo code below:
container.Register<ISettings, Settings>();
var settings = container.Resolve<ISettings>();
System.Type theTypeWeWantToRegister = Type.GetType(settings.GetTheISomeOtherServiceType());
container.Register(ISomeOtherService, theTypeWeWantToRegister);
SimpleInjector does not allow registration after resolution. Is there some mechanism in SimpleInjector that allows the same architecture?
A simple way to get this requirement is to register all of the available types that may be required and have the configuration ensure that the container returns the correct type at run time ... it's not so easy to explain in English so let me demonstrate.
You can have multiple implementations of an interface but at runtime you want one of them, and the one you want is governed by a setting in a text file - a string. Here are the test classes.
public interface IOneOfMany { }
public class OneOfMany1 : IOneOfMany { }
public class OneOfMany2 : IOneOfMany { }
public class GoodSettings : ISettings
{
public string IWantThisOnePlease
{
get { return "OneOfMany2"; }
}
}
So let's go ahead and register them all:
private Container ContainerFactory()
{
var container = new Container();
container.Register<ISettings, GoodSettings>();
container.RegisterAll<IOneOfMany>(this.GetAllOfThem(container));
container.Register<IOneOfMany>(() => this.GetTheOneIWant(container));
return container;
}
private IEnumerable<Type> GetAllOfThem(Container container)
{
var types = OpenGenericBatchRegistrationExtensions
.GetTypesToRegister(
container,
typeof(IOneOfMany),
AccessibilityOption.AllTypes,
typeof(IOneOfMany).Assembly);
return types;
}
The magic happens in the call to GetTheOneIWant - this is a delegate and will not get called until after the Container configuration has completed - here's the logic for the delegate:
private IOneOfMany GetTheOneIWant(Container container)
{
var settings = container.GetInstance<ISettings>();
var result = container
.GetAllInstances<IOneOfMany>()
.SingleOrDefault(i => i.GetType().Name == settings.IWantThisOnePlease);
return result;
}
A simple test will confirm it works as expected:
[Test]
public void Container_RegisterAll_ReturnsTheOneSpecifiedByTheSettings()
{
var container = this.ContainerFactory();
var result = container.GetInstance<IOneOfMany>();
Assert.That(result, Is.Not.Null);
}
As you already stated, Simple Injector does not allow mixing registration and resolving instances. When the first type is resolved from the container, the container is locked for further changes. When a call to one of the registration methods is made after that, the container will throw an exception. This design is chosen to force the user to strictly separate the two phases, and prevents all kinds of nasty concurrency issues that can easily come otherwise. This lock down however also allows performance optimizations that make Simple Injector the fastest in the field.
This does however mean that you sometimes need to think a little bit different about doing your registrations. In most cases however, the solution is rather simple.
In your example for instance, the problem would simply be solved by letting the ISomeOtherService implementation have a constructor argument of type ISettings. This would allow the settings instance to be injected into that type when it is resolved:
container.Register<ISettings, Settings>();
container.Register<ISomeOtherService, SomeOtherService>();
// Example
public class SomeOtherService : ISomeOtherService {
public SomeOtherService(ISettings settings) { ... }
}
Another solution is to register a delegate:
container.Register<ISettings, Settings>();
container.Register<ISomeOtherService>(() => new SomeOtherService(
container.GetInstance<ISettings>().Value));
Notice how container.GetInstance<ISettings>() is still called here, but it is embedded in the registered Func<ISomeOtherService> delegate. This will keep the registration and resolving separated.
Another option is to prevent having a large application Settings class in the first place. I experienced in the past that those classes tend to change quite often and can complicate your code because many classes will depend on that class/abstraction, but every class uses different properties. This is an indication of a Interface Segregation Principle violation.
Instead, you can also inject configuration values directly into classes that require it:
var conString = ConfigurationManager.ConnectionStrings["Billing"].ConnectionString;
container.Register<IConnectionFactory>(() => new SqlConnectionFactory(conString));
In the last few application's I built, I still had some sort of Settings class, but this class was internal to my Composition Root and was not injected itself, but only the configuration values it held where injected. It looked like this:
string connString = ConfigurationManager.ConnectionStrings["App"].ConnectionString;
var settings = new AppConfigurationSettings(
scopedLifestyle: new WcfOperationLifestyle(),
connectionString: connString,
sidToRoleMapping: CreateSidToRoleMapping(),
projectDirectories: ConfigurationManager.AppSettings.GetOrThrow("ProjectDirs"),
applicationAssemblies:
BuildManager.GetReferencedAssemblies().OfType<Assembly>().ToArray());
var container = new Container();
var connectionFactory = new ConnectionFactory(settings.ConnectionString);
container.RegisterSingle<IConnectionFactory>(connectionFactory);
container.RegisterSingle<ITimeProvider, SystemClockTimeProvider>();
container.Register<IUserContext>(
() => new WcfUserContext(settings.SidToRoleMapping), settings.ScopedLifestyle);
UPDATE
About your update, if I understand correctly, you want to allow the registered type to change based on a configuration value. A simple way to do this is as follows:
var settings = new Settings();
container.RegisterSingle<ISettings>(settings);
Type theTypeWeWantToRegister = Type.GetType(settings.GetTheISomeOtherServiceType());
container.Register(typeof(ISomeOtherService), theTypeWeWantToRegister);
But please still consider not registering the Settings file at all.
Also note though that it's highly unusual to need that much flexibility that the type name must be placed in the configuration file. Usually the only time you need this is when you have a dynamic plugin model where a plugin assembly can be added to the application, without the application to change.
In most cases however, you have a fixed set of implementations that are already known at compile time. Take for instance a fake IMailSender that is used in your acceptance and staging environment and the real SmptMailSender that is used in production. Since both implementations are included during compilation, allowing to specify the complete fully qualified type name, just gives more options than you need, and means that there are more errors to make.
What you just need in that case however, is a boolean switch. Something like
<add key="IsProduction" value="true" />
And in your code, you can do this:
container.Register(typeof(IMailSender),
settings.IsProduction ? typeof(SmtpMailSender) : typeof(FakeMailSender));
This allows this configuration to have compile-time support (when the names change, the configuration still works) and it keeps the configuration file simple.

Unity -- using information from request to resolve dependencies

I've recently refactored my MVC application to use Unity dependency injection to resolve dependencies, which is great. It's much more decomposable, etc., etc.
What I'm doing now is adding the capability for multiple tenants to use it. The approach I'm using (so that the rest of the code doesn't have to know much about the tenants) is creating things like a tenant-filtered version of my repository interface (which is just a proxy for another repository... so it will call one of the underlying methods, then check if the record has the right tenant and behave accordingly). This lets me basically emulate having a totally separate store for each tenant even though under the hood the data is not segregated, so relatively little of the client code needs to change.
The problem with all of this is how it fits into the DI way of doing things. What I'm planning to do is, at the beginning of the request, detect the host name, then use that to determine the tenant (each tenant will have a list of hostnames in the DB). Although I'm using per-request lifetimes for most objects Unity is constructing and resolving I don't really get how Unity can "know" what tenant to use since it would need both the data about the request (which I suppose the controller will have, but I don't think is available in my container configuration method) and access to the database to know which host (and it hardly seems desirable to have my container configuration making database calls). I can solve #2 by only passing in a host name and making the classes with tenants go figure out which tenant is being referenced, but that doesn't help with #1.
Right now I'm using "property injection" (also known as "a public property" in less high-falutin' circles), but I don't see how I'm going to avoid having my controller be the one that actually feeds the tenant data in, so now I don't really have just the one composition root controlling everything.
Is there a way I can do this in the composition root, or should I just resign myself to having the controller do this work?
For some reason you seem to forget about injection factories. Registering interface/type against a factory lets you execute arbitrarily complicated code upon resolving, including consulting the request, tenant database, whatever.
container.RegisterType<IRepository>(
new InjectionFactory(
c => {
// whatever, consult the database
// whatever, consult the url
return ...;
} );
The factory composition is transparent so that whenever you need it, the target doesn't even know that the factory code has been executed rather than a type instance from simple mapping.
Somewhere it needs to make a database call. Maybe the simplest place would be in global.ascx if it's needed system wide.
private static ConcurrentDictionary<string, string> _tenantCache = new ConcurrentDictionary<string, string>();
protected virtual void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
var tenantId = _tenantCache.GetOrAdd(app.Context.Request.Url.Host, host =>
{
// Make database call in this class
var tenant = new TenantResolver();
return tenant.GetTenantId(host);
})
app.Context.Items["TenantID"] = tenantId ;
}
You will want to cache the result as Application_BeginRequest is called alot. You can then configure Unity to have child containers. Put all the common/default mappings in the parent container then create a child container per tenant and register the correct implementation for each tenant in it's own child container.
Then implement IDependencyResolver to return the correct child container.
public class TenantDependencyResolver : IDependencyResolver
{
private static IUnityContainer _parentContainer;
private static IDictionary<string, IUnityContainer> _childContainers = new Dictionary<string, IUnityContainer>();
public TenantDependencyResolver()
{
var fakeTenentID = "localhost";
var fakeTenentContainer = _parentContainer.CreateChildContainer();
// register any specific fakeTenent Interfaces to classes here
//Add the child container to the dictionary for use later
_childContainers[fakeTenentID] = fakeTenentContainer;
}
private IUnityContainer GetContainer()
{
var tenantID = HttpContext.Current.Items["TenantID"].ToString();
if (_childContainers.ContainsKey(tenantID)
{
return _childContainers[tenantID];
}
return _parentContainer;
}
public object GetService(Type serviceType)
{
var container = GetContainer();
return container.Resolve(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
var container = GetContainer();
return container.ResolveAll(serviceType);
}
}
Then set ASP.NET MVC DependecyResolver to be the TenantDependencyResolver. I didn't run this code but it should give you an idea of what you would need to do. If your implementations are set then you might be able to do it in the static constructor of TenantDependecyResolver.

How do I associate some custom data with current HttpRequest?

I need to somehow attach my custom data to the HttpRequest being handled by my IIS custom modules - so that code that runs in earlier stages of IIS pipeline attaches an object and code that runs in later stages can retrieve the object and use it and no other functionality of IIS pipeline processing is altered by adding that object.
The data needs to persist within one HTTP request only - I don't need it to be stored between requests. I need it to be "reset" for each new request automatically - so that when a new request comes it doesn't contain objects my code attached to the previous request.
Looks like HttpContext.Items is the way to go, although MSDN description of its purpose is not very clear.
Is using HttpContext.Current.Items the way to solve my problem?
This should work - I have done this in a project before.
I have a class which has a static property like this -
public class AppManager
{
public static RequestObject RequestObject
{
get
{
if (HttpContext.Current.Items["RequestObject"] == null)
{
HttpContext.Current.Items["RequestObject"] = new RequestObject();
}
return (RequestObject)HttpContext.Current.Items["RequestObject"];
}
set { HttpContext.Current.Items["RequestObject"] = value; }
}
}
And then RequestObject contains all my custom data so then in my app I can do
AppManager.RequestObject.CustomProperty
So far I have not come across any issues in the way HttpContext.Items works.

Categories

Resources