使用自定义Redis输出缓存提供器时MVCDonutCaching失效故障排查
I've run into this exact issue before — the problem boils down to how Type.GetType(string) resolves types outside the current executing assembly. When MVCDonutCaching tries to load your CustomRedisOutputCache class, it uses Type.GetType, which only checks the current assembly and mscorlib by default. Since your custom provider lives in your xxx.xxx.Web assembly (not the MVCDonutCaching assembly), it returns null.
Here are the most reliable solutions:
1. Use the Full Type Name Including Assembly
Update the type attribute in your web.config to include the assembly name. Your provider entry should look like this:
<add name="CustomRedisOutputCache" type="xxx.xxx.Web.Caching.CustomRedisOutputCache, xxx.xxx.Web" applicationName="xxx.xxx" connectionString="Redis" databaseId="4" throwOnError="false" retryTimeoutInMilliseconds="5000" loggingClassName="" loggingMethodName="" />
The format here is Namespace.ClassName, AssemblyName. This tells Type.GetType exactly where to look for the type, bypassing its default assembly limitations. The regular OutputCache provider likely uses a different type resolution mechanism that handles this automatically, which is why it worked before.
2. Modify MVCDonutCaching's Type Loading Logic (If You Have Access to Source)
If you can fork or modify the MVCDonutCaching source code, replace the problematic type loading code with a more robust approach that searches all loaded assemblies:
try { Type providerType = Type.GetType(providerSettings.Type); if (providerType == null) { // Search all loaded assemblies for the type foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { providerType = assembly.GetType(providerSettings.Type, false, true); if (providerType != null) break; } } Instance = (OutputCacheProvider)Activator.CreateInstance(providerType); Instance.Initialize(providerSettings.Name, providerSettings.Parameters); } catch (Exception ex) { throw new ConfigurationErrorsException( string.Format("Unable to instantiate and initialize OutputCacheProvider of type '{0}'. Make sure you are specifying the full type name.", providerSettings.Type), ex ); }
This method iterates through every assembly loaded in the current AppDomain, ensuring it finds your custom provider even if Type.GetType misses it.
3. Pre-Load Your Custom Provider's Assembly
Force your xxx.xxx.Web assembly to load early in the application lifecycle (e.g., in Global.asax.cs's Application_Start):
protected void Application_Start() { // Pre-load the assembly containing your custom cache provider Assembly.Load("xxx.xxx.Web"); // Rest of your startup logic... }
Sometimes assemblies are loaded lazily, so when MVCDonutCaching tries to resolve the type, your assembly hasn't been loaded yet. Pre-loading it ensures it's available in the AppDomain when needed.
Verification Steps
After making one of these changes, restart your application and test the [DonutOutputCache] attribute. If you still see errors:
- Double-check the assembly name (case-sensitive, and include version/public key token if your assembly is strongly named)
- Ensure your
CustomRedisOutputCachehas a public, parameterless constructor (required forActivator.CreateInstance) - Confirm the
xxx.xxx.Webassembly is present in your application'sbindirectory
内容的提问来源于stack exchange,提问作者Pete

