Blazor Server: Correct way to cache CSLA objects (avoiding IServiceProvider Disposed) #4797
Replies: 2 comments 2 replies
-
|
What you are encountering is that all business domain objects maintain a reference to their underlying ApplicationContext, which in turn maintains a reference to the underlying ServiceProvider. You can't share an object instance across multiple ServiceProvider contexts, or across multiple ApplicationContext contexts (they are really one and the same). Because things like authorization rules, identity, etc. are maintained at the context level - trying to use an instance across contexts would cause cross-user authorization (and possibly) data leakage. So to cache a "domain object", what you really need to cache the serialized object. Use MobileFormatter to serialize the object into a byte array or stream, cache that, and then deserialize to an instance as needed - so that instance is in the correct context. The data portal itself (starting with CSLA 9) actually has this capability built-in. |
Beta Was this translation helpful? Give feedback.
-
|
I am using CSLA 9.1 and can successfully cache ReadOnlyListBase or BusinessListBase classes for use on any page within the application. However, I do encounter the IServiceProvider Disposed exception if I try to cache a single ReadOnlyBase object. For these objects I have to cache the serialized object. Why would these objects behave in a different manner and any solution for them to work in the same manner as the list classes? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi Rocky,
I would like to clarify a behavior I've observed in a Blazor Server application to ensure I am following the correct architectural pattern.
My Architecture:
I am using Blazor Server.
I have a CacheService registered as Scoped (services.AddScoped).
Internally, this service uses the standard ASP.NET Core IMemoryCache (which is a Singleton) to store data.
I was storing live CSLA ReadOnlyList objects directly in this cache.
The Issue:
I navigate to a page that fetches a CSLA list and caches it.
I navigate to an error page or force a circuit teardown. The Blazor Circuit (and the current Scope) is disposed.
When a new circuit/scope is established (or I reload), the application retrieves the cached CSLA object from the MemoryCache.
As soon as I touch this object (or try to clone it), I get: System.ObjectDisposedException: Cannot access a disposed object. Object name: 'IServiceProvider'.
My Diagnosis: It seems that even though my wrapper service is Scoped, the CSLA object stored in the Singleton IMemoryCache retains a reference to the original (now disposed) IServiceProvider used during its creation/fetching.
The Solution: I have switched to mapping my CSLA lists to POCOs (plain C# objects) before caching them. This solved the issue completely.
My Questions:
Does this confirm that we should never store live CSLA objects in a global/singleton IMemoryCache in Blazor Server because of the captured IServiceProvider reference?
What is the recommended pattern or "correct way" to cache CSLA objects in Blazor?
Does CSLA provide any built-in mechanism or feature specifically designed to handle caching in Blazor applications that avoids these scope/lifetime issues?
Thank you for your guidance.
Beta Was this translation helpful? Give feedback.
All reactions