I'm following a course on Pluralsight about ASP.NET Core but, when accessing to Restaurant Page I receive the following error:
InvalidOperationException: Unable to resolve service for type 'Data.IRestaurantsData' while attempting to activate 'OdeToFood.Pages.Restaurants.ListModel'.
I saw another post on StackOverflow that suggests moving the singleton in Startup.cs outside from the lambda function. I move it in the position but the error is still there. Can you help me understand the problem?
Restaurant.cs
namespace OdeToFood.core {
public class Restaurant {
public int Id { get; set; }
public string? Name { get; set; }
public string? Location { get; set; }
public CuisineType Cuisine { get; set; }
}
}
IRestaurantData.cs
using OdeToFood.core;
namespace Data {
public interface IRestaurantsData {
IEnumerable<Restaurant> GetRestaurantsByName(string name);
}
public class InMemoryRestaurantsData : IRestaurantsData {
public List<Restaurant> restaurants;
public InMemoryRestaurantsData()
{
restaurants = new List<Restaurant>()
{
new Restaurant { Id = 1, Name = "Pizza", Location = "Milano", Cuisine = CuisineType.Italian },
new Restaurant { Id = 2, Name = "Rice", Location = "Mexic", Cuisine = CuisineType.Mexican },
new Restaurant { Id = 3, Name = "Chicken", Location = "London", Cuisine = CuisineType.Indian},
};
}
public IEnumerable<Restaurant> GetRestaurantsByName(string name = null) {
return from r in restaurants
where string.IsNullOrEmpty(name) || r.Name.StartsWith(name)
orderby r.Name
select r;
}
}
}
List.cs
using Data;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using OdeToFood.core;
namespace OdeToFood.Pages.Restaurants {
public class ListModel : PageModel {
private readonly IConfiguration config;
private readonly IRestaurantsData restaurantData;
public string Message { get; set; }
public IEnumerable<Restaurant> Restaurants;
public ListModel(IRestaurantsData restaurantsData) {
this.restaurantData = restaurantsData;
}
public void OnGet(string searchTerm) {
Message = config["Message"];
Restaurants = restaurantData.GetRestaurantsByName(searchTerm);
}
}
}
Startup.cs
using Data;
using Microsoft.AspNetCore.Mvc;
namespace OdeToFood {
public class Startup {
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public IRestaurantsData RestaurantsData { get; set; }
public InMemoryRestaurantsData InMemoryRestaurantsData { get; set; }
public void ConfigureServices(IServiceCollection services) {
services.Configure<CookiePolicyOptions>(options => {
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddSingleton<IRestaurantsData, InMemoryRestaurantsData>();
services.AddRazorPages();
services.AddControllers();
}
}
}
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment()) {
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
CodePudding user response:
I think this is the source of a lot of confusion. .NET Core 6 changed the default way startup is handled. Right now, your startup class is doing nothing. It looks like your example code came from a course before .NET 6. You have two options.
1: Move the Registration Statement to program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.services.AddSingleton<IRestaurantsData, InMemoryRestaurantsData>();
var app = builder.Build();
if (!app.Environment.IsDevelopment()) {
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Make sure to move your cookie registration also if you need it.
2: Tell it to use your startup class.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var startup = new Startup(builder.Configuration);
startup.ConfigureServices(builder.Services);
var app = builder.Build();
if (!app.Environment.IsDevelopment()) {
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Make sure to take out the duplicate razor pages registration if you go this route.
Here is an article on it: https://www.infoworld.com/article/3646098/demystifying-the-program-and-startup-classes-in-aspnet-core.html