2
votes

(My previous question/issue was not specific enough. Hence the complete rewrite.)

Issue: ServiceStack 4.0.16 does not work with Redis.

Steps to recreate:

  1. Create a new ASP.NET Webforms Application in VS 2013.
  2. Update Nuget Packages
  3. Install Nuget Package => Install-Package ServiceStack.Host.AspNet
  4. Run App - Example todo's work. /metadata shows example services
  5. Startup a local or remote instance of Redis (I tested both local on Windows, remote on Linux)
  6. Add the RedisClientsManager to the AppHost.cs

container.Register(c => new PooledRedisClientManager("localhost:6379")); container.Register(c => (ICacheClient)c.Resolve() .GetCacheClient()) .ReusedWithin(Funq.ReuseScope.None);

  1. Run the project, you should just get a blank screen in Chrome
  2. Navigate to /metadata and you will get a generic HTTP Error 500.0 - Internal Server Error
  3. Open the Event Viewer and go to Applications and you should see three Errors

    1. Failed to initialize the AppDomain:/LM/W3SVC/24/ROOT

Exception: System.Runtime.Serialization.SerializationException

Message: Type 'ServiceStack.DispsableTracker' in assembly 'ServiceStack, Version=4.0.16.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.

StackTrace: at System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel) at System.Web.Hosting.ApplicationManager.CreateAppDomainWithHostingEnvironment(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters) at System.Web.Hosting.ApplicationManager.CreateAppDomainWithHostingEnvironmentAndReportErrors(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters)

2. An error occurred while trying to start an integrated application instance.

Exception: System.Runtime.Serialization.SerializationException

Message: Type 'ServiceStack.DispsableTracker' in assembly 'ServiceStack, Version=4.0.16.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.

StackTrace: at System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel) at System.Web.Hosting.ApplicationManager.CreateAppDomainWithHostingEnvironment(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters) at System.Web.Hosting.ApplicationManager.CreateAppDomainWithHostingEnvironmentAndReportErrors(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters) at System.Web.Hosting.ApplicationManager.GetAppDomainWithHostingEnvironment(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters) at System.Web.Hosting.ApplicationManager.CreateObjectInternal(String appId, Type type, IApplicationHost appHost, Boolean failIfExists, HostingEnvironmentParameters hostingParameters) at System.Web.Hosting.ProcessHost.StartApplication(String appId, String appPath, Object& runtimeInterface)

3. An application has reported as being unhealthy. The worker process will now request a recycle. Reason given: ASP.NET application initialization failed.. The data is the error.

1
This does not sound like a redis or servicestack problem. My guess is, that the request cannot be serialized into html. Have you tried it in a simple standalone .NET GUI program? Is your exception handling okay?Tw Bert
Although it could be something different, it is clear that the default application has no problem working without a Redis Cache. It also works fine when I register the memory cache client instead of Redis. container.Register<ICacheClient>(new MemoryCacheClient()); But the minute I use Redis it breaks. So it obviously is somehow related to Redis.Zoran
Also, (not related to this issue or project) when I used a CustomUserSession object to save session data in Redis, it blew up because I did not have the Serialization Attributes on my properties. So, serialization does play a role when using Redis. I don't know how ServiceStack.DispsableTracker fit's into this scenario, but it is obviously causing some issue that comes to light when using Redis.Zoran
Yes, it didn't mean to imply that it has nothing to do with using Redis within this scenario. It clearly does. But I see that you are connecting to localhost on the default Redis port, and this might mean that you are using MsOpenTech's redis clone. I'd isolate the code first and run it outside of ASP, and check how it behaves. Then I'd run the code from ASP without outputting it (so serialization at least has a smaller scope). As far as serialization within ASP, that's not something I'm doing a lot, other ppl can answer that better.Tw Bert
Also check if your ASP thread is allowed to communicate with localhost:6379. You could use a simple raw TCP socket for this. And/or use a different port.Tw Bert

1 Answers

1
votes

This issue was resolved inside ServiceStack and released as v4.0.17.

Information on the issue from Demis:

It was due to resolving an IDisposable dependency during initialization (i.e. not at runtime) which means the HttpContext.Items doesn't exist so disposables were being tracked in the CallContext's LogicalData store, which apparently in an IIS Express host doesn't support non-serializable items. So I've added a new Container.Exists api to check for IOC existence so we no longer have to resolve items internally (in ServiceStackHost), we're also not tracking items in RequestContext during App initialization.

Why did this work fine with the MemoryCacheClient and not with the RedisClientManager?

Because there's default logic that if you haven't registered an ICacheClient it will first check to see if you have Redis registered in which case it will register it as an ICacheClient otherwise it will register a MemoryCacheClient instead, code is at: https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/ServiceStackHost.cs#L376

Originally it was resolving the instance to check for existence, now it uses the new Exists method that checks without resolving an instance.

@Demis, thanks for the help!