I'm pretty sure it's an error with DI, but I don't know how to fix it.
using Microsoft.EntityFrameworkCore;
using RestApi.Models;
namespace RestApi.Services;
public class Builder
{
public static WebApplication Configurate(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("AppDb");
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// User defined
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<IPassword, Password>();
builder.Services.AddDbContext<ApiContext>(x => x.UseSqlServer(connectionString));
return builder.Build();
}
}
using System.Security.Cryptography;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
namespace RestApi.Services;
public class Password : IPassword
{
public Password()
{
}
public string Hash(string password, byte[]? userSalt = null)
{
// Generate a 128-bit salt using a sequence of
// cryptographically strong random bytes.
byte[]? salt;
salt = userSalt ?? RandomNumberGenerator.GetBytes(128 / 8); // divide by 8 to convert bits to bytes
// derive a 256-bit subkey (use HMACSHA256 with 100,000 iterations)
var hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password!,
salt: salt,
prf: KeyDerivationPrf.HMACSHA256,
iterationCount: 100000,
numBytesRequested: 256 / 8));
return hashed;
}
public bool Validate(string password, byte[] salt, string correctPassword)
{
var hashed = Hash(password, salt);
if (hashed == correctPassword)
{
return true;
}
return false;
}
}
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using RestApi.Models;
namespace RestApi.Services;
public class UserService : IUserService
{
private readonly ApiContext _context;
private readonly Password _password;
public UserService(ApiContext context, Password password)
{
_context = context;
_password = password;
if (_context.Users == null)
throw new Exception();
}
public async Task<IEnumerable<UserModel>> All()
{
return await _context.Users.ToListAsync();
}
public async Task<ActionResult<UserModel>> Create(UserModel userModel)
{
userModel.Password = _password.Hash(userModel.Password);
_context.Users.Add(userModel);
await _context.SaveChangesAsync();
return new UserModel
{
Id = userModel.Id
};
}
public async Task<ActionResult<UserModel>> GetById(long id)
{
var userModel = await _context.Users.FindAsync(id);
if (userModel == null)
return null;
return userModel;
}
public async Task<bool> Delete(long id)
{
var userModel = await _context.Users.FindAsync(id);
if (userModel == null)
return false;
_context.Users.Remove(userModel);
await _context.SaveChangesAsync();
return true;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using RestApi.Models;
using RestApi.Services;
namespace RestApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
private readonly IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
// GET: api/Users
[HttpGet]
public async Task<IEnumerable<UserModel>> GetUsers()
{
return await _userService.All();
}
// POST: api/Users
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPost]
public async Task<ActionResult<UserModel>> PostUserModel(UserModel userModel)
{
return CreatedAtAction("GetUserModel", await _userService.Create(userModel), userModel);
}
// GET: api/Users/5
[HttpGet("{id}")]
public async Task<ActionResult<UserModel>> GetUserModel(long id)
{
ActionResult<UserModel> user = await _userService.GetById(id);
if (user == null)
{
return NotFound();
}
return user;
}
// DELETE: api/Users/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteUserModel(long id)
{
if (!await _userService.Delete(id))
return NotFound();
return Ok();
}
/*// PUT: api/Users/5
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPut("{id}")]
public async Task<IActionResult> PutUserModel(long id, UserModel userModel)
{
if (id != userModel.Id)
{
return BadRequest();
}
_context.Entry(userModel).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!UserModelExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
private bool UserModelExists(long id)
{
return (_context.Users?.Any(e => e.Id == id)).GetValueOrDefault();
}*/
}
}
An error occurred while starting the application:
AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: RestApi.Services.IUserService Lifetime: Scoped ImplementationType: RestApi.Services.UserService': Unable to resolve service for type 'RestApi.Services.Password' while attempting to activate 'RestApi.Services.UserService'.)
Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection serviceDescriptors, ServiceProviderOptions options)
InvalidOperationException: Error while validating the service descriptor 'ServiceType: RestApi.Services.IUserService Lifetime: Scoped ImplementationType: RestApi.Services.UserService': Unable to resolve service for type 'RestApi.Services.Password' while attempting to activate 'RestApi.Services.UserService'.
Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: RestApi.Services.IUserService Lifetime: Scoped ImplementationType: RestApi.Services.UserService': Unable to resolve service for type 'RestApi.Services.Password' while attempting to activate 'RestApi.Services.UserService'.)
I am trying to inject the dependencies and start the program
You injected the IPassword
interface but used the Password
class in UserService
instead of the interface.
change your UserService
class to this
public UserService(ApiContext context, IPassword password)
{
_context = context;
_password = password;
if (_context.Users == null)
throw new Exception();
}