justawebguy justawebguy - 2 months ago 49
C# Question

Can I use Dependency Injection in a ViewModel for DbContext? Core2.0

I am trying to migrate an app to Core 2.0 from a framework project. The problem I am running into Is very Similar to this one, but I am trying to use DI. I created a sample project in line with that problem but using a view model similar to how I am using it in my project. I have been trying to figure out what I'm doing wrong to over a day so hopefully someone on here can help.

In case It's helpful code on github

ApplicationDbContext.cs

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<Gig> Gigs { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}

protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}

public DbSet<gigs2.Models.Gig> Gig { get; set; }
}


GigsController.cs

public class GigsController : Controller
{
// GET: Gigs
public ActionResult Index()
{
GigsViewModel vm = new GigsViewModel();
vm.Get();
return View(vm);
}
}


I am erroring out on
new GigsViewModel();
it says because I need to pass options to the ApplicationDbContext


There is no argument given that corresponds to the required formal
parameter 'options' of
'ApplicationDbContext.ApplicationDbContext(DbContextOptions)'


GigsViewModels.cs

public class GigsViewModel
{
private ApplicationDbContext _context;

public GigsViewModel(ApplicationDbContext context) {
_context = context;

}
public List<GigViewModel> Gigs { get; set; }

public void Get()
{
Gigs = _context.Gigs.Select(g => new GigViewModel {
Id = g.Id,
Date = g.Date,
Time = g.Time,
Venue = g.Venue
}).ToList();
}
}


startup.cs

public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&'*+-/=?^_`{|}~.@ ";
options.User.RequireUniqueEmail = false;
options.Password.RequireDigit = false;
options.Password.RequiredLength = 4;
options.Password.RequireDigit = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddScoped<UserManager<ApplicationUser>, ApplicationUserManager>();
services.AddScoped<SignInManager<ApplicationUser>, ApplicationSignInManager<ApplicationUser>>();
services.Configure<Configuration.cofAuthSettings>(Configuration.GetSection("cofAuthSettings"));


// Add application services.
services.AddTransient<IEmailSender, EmailSender>();

services.AddMvc();
}

Answer Source

Add a constructor to your GigsController class which accepts an instance of your GigsViewModel. This will allow the IoC container to construct the dependency tree (instead of creating it yourself like you are doing at the moment.

Something like this should work:

private readonly GigsViewModel _gigsViewModel;

public GigsController(GigsViewModel gigsViewModel)
{
    _gigsViewModel = gigsViewModel;
}

// GET: Gigs
public ActionResult Index()
{
    _gigsViewModel.Get();
    return View(_gigsViewModel);
}