Embedio: Pass data down the process chain with IHttpContext

Created on 23 Apr 2019  路  5Comments  路  Source: unosquare/embedio

Is your feature request related to a problem? Please describe.
I want to pass some object from a module (WebModuleBase) to other modules or controllers (WebApiController) that will process the same IHttpContext later.
Use case: I have a authorization module that queries databases for user information, return HTTP 403 if not authorized. Later in a controller, I need the user's other info, like name or email address. A second request to database could be avoided if we have a way to pass the User object to the controller.

Describe the solution you'd like
Add a IDictionary<object,object> Items { get; set; } to IHttpContext, like what ASP.NET have.

Describe alternatives you've considered

Additional context

enhancement

Most helpful comment

I have no problem with it, I'm not using the setter.
Items.Clear() would serve basically the same function as Items = new Dictionary().

Yes, even with no setter, a module can still clear the dictionary. For this I see no viable solution but good practice.

[...] ASP.NET have it, so it is guaranteed not a bad design.

ASP.NET, be it "classic" or Core, is part of a framework. Its target is, in a word, everybody. In such a context, it probably made little sense to initialize a dictionary (or a Lazy<>) for _every_ HTTP context.

EmbedIO, on the other hand, aims to make it simple to have an embedded Web server in a .NET application. Furthermore, what I am currently struggling to do is make it easy to develop libraries based upon EmbedIO. In this context, the principle of least surprise becomes paramount.

I was going to suggest use IDictionary<string,object>, I think IDictionary<object,object> is better.

I agree. String keys stored as objects are compared as StringComparison.Ordinal does, which does the job nicely, and is faster than using CultureInfo. Besides, if a module developer wants to be absolutely sure to use a unique key, they can do something like this:
```C#
class MyModule : IWebModule
{
// ...
public static object MyKey { get; } = new object();
// ...
context.Items[MyKey] = value;
// ...
}

class MyOtherModule : IWebModule
{
// ...
var myValue = context.Items[MyModule.MyKey];
// ...
}
```

I wonder why would ASP.NET have a setter, is someone have the need to replace the dictionary itself? or just for legacy compatibility.

Most probably the latter IMHO.

Thanks a lot for your input!

All 5 comments

Hi @Genteure, can you check the related PR. Thanks

Seems good, Thank you.

@Genteure, @geoperez, would it be a problem if Items had no setter in next version of EmbedIO, like this?
C# public interface IHttpContext { // ... IDictionary<object, object> Items { get; } // ... }
By making it a read-only property we can be sure that it is never null, which helps to ensure a consistent and reliable API surface for module developers (together with other changes I'm currently working on).

If all you've done so far is set and get items, rather than the dictionary itself, then the change would not affect you in any way. I want to be sure that there are no use cases for the dictionary setter.

I have no problem with it, I'm not using the setter.
Items.Clear() would serve basically the same function as Items = new Dictionary().

The only reason I suggest add IDictionary<object,object> Items { get; set; } is ASP.NET have it, so it is guaranteed not a bad design. I was going to suggest use IDictionary<string,object>, I think IDictionary<object,object> is better.
I wonder why would ASP.NET have a setter, is someone have the need to replace the dictionary itself? or just for legacy compatibility.

I have no problem with it, I'm not using the setter.
Items.Clear() would serve basically the same function as Items = new Dictionary().

Yes, even with no setter, a module can still clear the dictionary. For this I see no viable solution but good practice.

[...] ASP.NET have it, so it is guaranteed not a bad design.

ASP.NET, be it "classic" or Core, is part of a framework. Its target is, in a word, everybody. In such a context, it probably made little sense to initialize a dictionary (or a Lazy<>) for _every_ HTTP context.

EmbedIO, on the other hand, aims to make it simple to have an embedded Web server in a .NET application. Furthermore, what I am currently struggling to do is make it easy to develop libraries based upon EmbedIO. In this context, the principle of least surprise becomes paramount.

I was going to suggest use IDictionary<string,object>, I think IDictionary<object,object> is better.

I agree. String keys stored as objects are compared as StringComparison.Ordinal does, which does the job nicely, and is faster than using CultureInfo. Besides, if a module developer wants to be absolutely sure to use a unique key, they can do something like this:
```C#
class MyModule : IWebModule
{
// ...
public static object MyKey { get; } = new object();
// ...
context.Items[MyKey] = value;
// ...
}

class MyOtherModule : IWebModule
{
// ...
var myValue = context.Items[MyModule.MyKey];
// ...
}
```

I wonder why would ASP.NET have a setter, is someone have the need to replace the dictionary itself? or just for legacy compatibility.

Most probably the latter IMHO.

Thanks a lot for your input!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

felixerdy picture felixerdy  路  7Comments

bufferUnderrun picture bufferUnderrun  路  4Comments

shdwp picture shdwp  路  6Comments

Dewyer picture Dewyer  路  8Comments

erossini picture erossini  路  5Comments