I'm registering the caching service in Startup.cs as follows:
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
services.AddTransient<DataFacade, DataFacade>();
...
}
In the same project my _Layout.cshtml header contains a ViewComponent
@await Component.InvokeAsync(nameof(ViewComponents.PageHeader))
This makes a call to a ModelBuilder component and has a constructor as follows:
using MyApp.Services;
using MyApp.Website.ModelBuilder;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
namespace MyApp.Website.ViewComponents
{
[ViewComponent]
public class Header : ViewComponent
{
private readonly HeaderModelBuilder _modelBuilder;
public Header(HeaderModelBuilder modelBuilder)
{
_modelBuilder = modelBuilder;
}
...and the ModelBuilder service references a DataFacade service:
using MyApp.Data.ExternalCountryData;
using MyApp.Services;
using MyApp.Website.Constants;
using MyApp.Website.Models;
namespace MyApp.Website.ModelBuilder
{
public class HeaderModelBuilder
{
private readonly DataFacade _dataFacade;
public HeaderModelBuilder(DataFacade dataFacade)
{
_dataFacade = dataFacade;
}
...which has a constructor as follows:
using System;
using MyApp.Data;
using MyApp.Data.ExternalSiteData;
using MyApp.Domain.Services.Data;
using Microsoft.Extensions.Caching.Memory;
namespace MyApp.Services
{
public class DataFacade
{
private MemoryCache _cache;
public DataFacade(MemoryCache memoryCache)
{
_cache = memoryCache;
}
However, when running the code I get the following thrown by Program.cs:
InvalidOperationException: Unable to resolve service for type 'Microsoft.Extensions.Caching.Memory.MemoryCache' while attempting to activate 'MyApp.Services.DataFacade'.
If I comment out the view component, the cache can be accessed fine by other parts of the app.
Why would the view component be having problems? Am I registering one of the services wrongly?
Inject the IMemoryCache abstraction and not the implementation
public class DataFacade {
private readonly IMemoryCache _cache;
public DataFacade(IMemoryCache memoryCache) {
_cache = memoryCache;
}
//...
The source code that adds memory cache adds the interface when registering with the service collection
/// <summary>
/// Adds a non distributed in memory implementation of <see cref="IMemoryCache"/> to the
/// <see cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
public static IServiceCollection AddMemoryCache(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddOptions();
services.TryAdd(ServiceDescriptor.Singleton<IMemoryCache, MemoryCache>());
return services;
}
Source
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With