I'm writing my first application using minimal APIs in a .NET 8 application. I'm following a training exercise I found on Microsoft Learn, and I'm using a database I designed. I ran into this error:
CS0311 The type 'Show1' cannot be used as type parameter 'TImplementation' in the generic type or method 'ServiceCollectionServiceExtensions.AddScoped<TService, TImplementation>(IServiceCollection)'. There is no implicit reference conversion from 'Show1' to 'BlazorMediaLibrary.API.Interfaces.IShow1'
I searched this error and came up with Why does a generic type constraint result in a no implicit reference conversion error? here on SO. However, I don't think this fits my situation. Here's what I got for my Interface, which was generated when I scaffolded the database to create the model classes and DbContext:
public interface IShow1
{
int ShowId { get; set; }
int ShowCode { get; set; }
string EpisodeName { get; set; }
string? Synopsis { get; set; }
DateTime? DateLastViewed { get; set; }
DateTime? OriginalBroadcastDate { get; set; }
TimeOnly? PlayTime { get; set; }
double? Rating { get; set; }
TypeOfShow1 ShowCodeNavigation { get; set; }
ICollection<Entries2> Entries2s { get; set; }
ICollection<UserRating> UserRatings { get; set; }
}
and here's the model class implementation:
public partial class Show1 : IShow1
{
public int ShowId { get; set; }
public int ShowCode { get; set; }
public string EpisodeName { get; set; } = null!;
public string? Synopsis { get; set; }
public DateTime? DateLastViewed { get; set; }
public DateTime? OriginalBroadcastDate { get; set; }
public TimeOnly? PlayTime { get; set; }
public double? Rating { get; set; }
public virtual TypeOfShow1 ShowCodeNavigation { get; set; } = null!;
public virtual ICollection<Entries2> Entries2s { get; set; } = new List<Entries2>();
public virtual ICollection<UserRating> UserRatings { get; set; } = new List<UserRating>();
}
In the Program.cs file I defined this record:
internal record Show1(int ShowId, int ShowCode, string EpisodeName,
string? Synopsis, DateTime? DateLastViewed,
DateTime? OriginalBoardcastDate, TimeOnly? PlayTime, float? Rating);
And here's the line in Program.cs
which is raising the error:
builder.Services.AddScoped<IShow1, Show1>();
I didn't include ShowCodeNavigation
, Entries2
or UserRatings
in the record definition in Program.cs
.
Is that what's causing my problem?
In the Program.cs file I defined this record:
internal record Show1
...
It will "shadow" the Show1
which implements the interface and is "imported" via corresponding using
statement. I would recommend to rename the record
to something else, but if there is a very good reason to have both internal record and class with the same name (I can't think of one but still), you can use the "full" type name for the registration:
builder.Services.AddScoped<IShow1, BlazorMediaLibrary.API.Models.Show1>();
If the record is not used in the top-level statement code (i.e. in the Program.cs) then you can switch to the "explicit" Main method (see Should 'using' directives be inside or outside the namespace in C#? for some possible explanation):
namespace MyNamespace
{
using BlazorMediaLibrary.API.Models; // moving import out of the namespace will break the compilation
public class Program
{
public void Main()
{
new ServiceCollection()
.AddScoped<IShow1, Show1>();
}
}
}
internal record Show1(int ShowId, ...);
or moving record to some namespace:
// in Program.cs
app.Run();
namespace MyNamespace
{
internal record Show1(...);
}
In your current code internal record Show1
results in the record class generated in the global namespace which results in the behavior your observe.