4

In an MVC app I need to store some user data to verify if he has all the rights to access some pages (like he is an owner of an object etc.). I experimented with adding a private static field to one of my services for handling user data and adding a static, get-only property for accessing the private field. This property pulls user data from the database if the private field is null. Obviously that's a bad idea, because an MVC app does not live only during requests, so once the private static field was set, it would stayed there indefinitely.

A search for an alternative to the above solution, led me to ThreadStatic attribute. Which seemed to work fine (at least on the first glance). But then I read more about the attribute and found out that one request can be actually handled by multiple threads (in my case that wasn't particularly a problem) and that some threads can be reused in several requests (extreme, but apparently rare case). Now this sounded like a real problem, it would mean that the user data I once pulled from the database, could possibly leak to another request and one user could be verified based on data of another.

So I searched for yet another alternative and found CallContext. This time I also noticed that people gave warnings that it will probably not work the way one would expect it to. In case of ThreadStatic poeple explaind what are the risks of using it, but in case of CallContext not so much.

So, can data stored in CallContext leak from one request to another (like it can happen with ThreadStatic fields) or the worst that can happen is loss of the data in the middle of a request (I can live with that)?

jahu
  • 5,427
  • 3
  • 37
  • 64
  • Is "Session" another option? – Ron Apr 08 '14 at 09:01
  • @Ron Actually handling everything as instances within controllers is a viable option, but the main reason I experimented with static and ThreadStatic was to reduce duplicate code from a number of controllers and actions. – jahu Apr 08 '14 at 09:26
  • Are you using asynchronous controllers and `async/await`? – noseratio Apr 08 '14 at 13:16
  • @Noseratio as far as I know, I don't use asynchronous controllers or async/await – jahu Apr 09 '14 at 09:13

3 Answers3

2

In an MVC app I need to store some user data to verify if he has all the rights to access some pages (like he is an owner of an object etc.).

What you are looking for is HttpContext.Session, as @Ron's answer suggest. You'd need to enable the session support.

OTOH, the lifetime of HttpContext.Items is limited to a given HTTP request, it does not flow between requests. Some HTTP protocol textual state data (e.g. cookies) will be flowed via HttpContext.Current.Request.

Can data stored in CallContext leak between requests?

If you still like to know if the logical call context data (CallContext.LogicalGetData / CallContext.LogicalSetData) flows between different HTTP requests, the answer would be no. If it did, that'd be a serious security hole, as different requests may come from different users.

It does however flow between threads within the same request, so for that matter it can be used as a substitution for ThreadLocal. Aalthough, use with care, as there's copy-on-write behavior, check Stephen Cleary's blog for more details. You may only need it if you use asynchronous controller methods and async/await (or ContinueWith etc).

Community
  • 1
  • 1
noseratio
  • 59,932
  • 34
  • 208
  • 486
1

According to this post, you should use HttpContext instead of CallContext.

By the way, HttpContext is "per request", if you want to save database accesses, you can use "Session", by creating an AbstractController, you can avoid duplicity among controllers and actions.

Community
  • 1
  • 1
Ron
  • 6,037
  • 4
  • 33
  • 52
  • Thanks for posting suggestions on how should I solve my problem, but I'm still would love to know if CallContext suffers from all the same issues as ThreadStatic. – jahu Apr 08 '14 at 11:07
  • My understanding is, since CallContext will not migrate when ASP.NET migrate requests from one thread to another, it will have the same issue when playing with ASP.NET. – Ron Apr 08 '14 at 11:31
1

My current stack is WCF, not ASP.Net, but I'd like to provide an answer to the OP's question as presented in the title:

Contrary to any and all resources I've come across on the web, contrary to the accepted answer of @noseratio, and contrary to reason (major security hole etc.) I believe that the correct answer, at least for WCF, is:

Yes.

I'd like to be careful and mention that I do not fully understand the reasoning, and I can not deterministically reproduce this. Still, since I suspected this may be the case based on some sporadic exception we've run into in my company, I've set up an experiment where I store OperationContext.Current.IncomingMessageHeaders.Action (in WCF, this is the name of the operation) via CallContext.LogicalSetData(), then refresh a million times and wait for my sporadic exception's breakpoint to hit. When it finally did, I compared the stored value against OperationContext.Current.IncomingMessageHeaders.Action, and the actions (hence the requests) were different.

May be relevant: The code reading and writing the LogicalCallContext in my WCF application is running inside a MessageInspector.

Unfortunately I lack the in-depth knowledge to create a stable working reproduction example. Please feel free to confront me with how my test case may be wrong by asking for any additional relevant detail I may have overlooked, such as configuration values, environment variables etc. I find my own finding somewhat alarming and even unlikely, and I would be happy to stand corrected. Until such a time, I figured it's a good idea to share this with the community.

.Net Framework version: 4.7.2.

WCF service is hosted in IIS.


You can find some additional info regarding my observation on Stephen Cleary's blog post about LogicalCallContext (see comments section).

tsemer
  • 2,959
  • 3
  • 29
  • 26