I have a generic services which are calling generic repository. I need to manage unit test, but not able to do it. May you help me ?
public class EntityService<TEntity> : IEntityService<TEntity> where TEntity : class, new()
{
private readonly IRepositoryAsync<TEntity> _repository;
public EntityService(IRepositoryAsync<TEntity> repository)
{
_repository = repository;
}
public virtual IQueryable<TEntity> Entities => Queryable();
public virtual bool Delete(object id)
{
if (id == null)
throw new ArgumentNullException(nameof(id));
TEntity entity = _repository.Find(id);
if (entity != null)
return Delete(entity);
return false;
}
}
GENERIC REPOSITORY
public class Repository<TEntity> : IRepositoryAsync<TEntity> where TEntity : class, new()
{
private readonly IDataContextAsync _context;
private readonly DbSet<TEntity> _dbSet;
public Repository(IDataContextAsync context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
if (context is DbContext dbContext)
_dbSet = dbContext.Set<TEntity>();
}
public virtual void Delete(object id)
{
TEntity entity = _dbSet.Find(id);
Delete(entity);
}
}
What I tried is next:
I had create abstract generic test
public abstract class EntityServiceUnitTests<TEntity> where TEntity : class, IEntity,new()
{
private readonly IEntityService<TEntity> _service;
public EntityServiceUnitTests()
{
_service = CreateSystemUnderTest();
}
[Test]
[TestCase("299cd2b5-ab47-4006-9a47-c85e4770e9b1")]
public void Delete_EntityWithExistUniqueIdentifier_ReturnsTrue(Guid id)
{
bool response = _service.Delete(id);
Assert.True(response);
}
protected abstract IEntityService<TEntity> CreateSystemUnderTest();
}
Than I had implement concrete for unit test
public class ConcreteEntityServiceUnitTests : EntityServiceUnitTests<Data>
{
protected override IEntityService<Data> CreateSystemUnderTest()
{
MockBehavior behavior = MockBehavior.Strict;
Mock<IRepositoryAsync<Data>> repoMock = new Mock<IRepositoryAsync<Data>>(behavior);
repoMock.Setup(s => s.Queryable()).Returns(DataList().AsQueryable);
SetupService();
IEntityService<Data> entityService = new EntityService<Data>(repoMock.Object);
return entityService;
}
private void SetupService()
{
Mock<IEntityService<Data>> service = new Mock<IEntityService<Data>>();
service.Setup(s => s.Find(It.Is<Data>(f => f.Id == It.IsAny<Guid>()))).Returns(DataList().FirstOrDefault(w => w.Id == It.IsAny<Guid>()));
}
private IList<Data> DataList()
{
List<Data> dataList = new List<Data>();
dataList.Add(new Data
{
Id = new Guid("299cd2b5-ab47-4006-9a47-c85e4770e9b1"),
ObjectState = ObjectState.Added
});
dataList.Add(new Data
{
Id = new Guid("229cd2b5-ab47-4006-9a47-c85e4770e9b1"),
ObjectState = ObjectState.Added
});
return dataList;
}
}
As error I'm getting:
Moq.MockException :
IRepository<Data>.Find([299cd2b5-ab47-4006-9a47-c85e4770e9b1])
invocation failed with mock behavior Strict.
Related
I have a Category table in my project, I used Generic repository and Unit of Work pattern in my project. It is an API. It is working when I use mock of UnitOfWork lonely but It is not working when I want to check my controller result. My controller response is 404 always. I think it is because of my mistake in setup but I don't know where it is.
`
[DisplayName("Category Table")]
public class Category
{
public int Id { get; set; }
public int? Priority { get; set; }
public string Name { get; set; }
public string? Details { get; set; }
public bool Enabled { get; set; }
public int? ParentCategoryId { get; set; }
public virtual Category Parent { get; set; }
public virtual IList<Category> Children { get; set; }
}
public interface IGenericRepository<T> where T : class, new()
{
Task<T> GetByIdAsync(object id);
Task<IReadOnlyList<T>> ListAllAsync();
Task<T> GetEntityWithSpec(ISpecification<T> spec);
Task<IReadOnlyList<T>> ListWithSpecAsync(ISpecification<T> spec);
...
}
public class GenericRepository<T> : IGenericRepository<T> where T : class, new()
{
private readonly FactoryContext _context;
public GenericRepository(FactoryContext context)
{
_context = context;
}
public async Task<T> GetByIdAsync(object id)
{
return await _context.Set<T>().FindAsync(id);
}
public async Task<IReadOnlyList<T>> ListAllAsync()
{
return await _context.Set<T>().ToListAsync();
}
public async Task<T> GetEntityWithSpec(ISpecification<T> spec)
{
return await ApplySpecification(spec).FirstOrDefaultAsync();
}
public async Task<IReadOnlyList<T>> ListWithSpecAsync(ISpecification<T> spec)
{
return await ApplySpecification(spec).ToListAsync();
}
...
private IQueryable<T> ApplySpecification(ISpecification<T> spec)
{
return SpecificationEvaluator<T>.GetQuery(_context.Set<T>().AsQueryable(), spec);
}
}
public interface IUnitOfWork : IDisposable
{
IGenericRepository<TEntity> Repository<TEntity>() where TEntity : class, new();
Task<int> Complete();
}
public class UnitOfWork : IUnitOfWork
{
private readonly FactoryContext _context;
private Hashtable _repositories;
public UnitOfWork(FactoryContext context)
{
_context = context;
}
public async Task<int> Complete()
{
return await _context.SaveChangesAsync();
}
public void Dispose()
{
_context.Dispose();
}
public IGenericRepository<TEntity> Repository<TEntity>() where TEntity : class, new()
{
if (_repositories == null) _repositories = new Hashtable();
var type = typeof(TEntity).Name;
if (!_repositories.ContainsKey(type))
{
var repositoryType = typeof(GenericRepository<>);
var repositoryInstance = Activator.CreateInstance(repositoryType.MakeGenericType(typeof(TEntity)), _context);
_repositories.Add(type, repositoryInstance);
}
return (IGenericRepository<TEntity>)_repositories[type];
}
}
public class CategoriesController : BaseApiController
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
public CategoriesController(IUnitOfWork unitOfWork, IMapper mapper)
{
_unitOfWork = unitOfWork;
_mapper = mapper;
}
[HttpGet("getcategorybyid/{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ApiResponse), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<CategoryToReturnDto>> GetCategoryById(int id)
{
try
{
var spec = new GetCategoriesWithParentsSpecification(id);
var category = await _unitOfWork.Repository<Category>().GetEntityWithSpec(spec);
if (category.Id == 0) return NotFound(new ApiResponse(404));
var returnCategories = _mapper.Map<Category, CategoryToReturnDto>(category);
return new OkObjectResult(new ApiResponse(200, "Ok", returnCategories));
}
catch (Exception ex)
{
return BadRequest(new ApiResponse(400, ex.Message));
}
}
}
public class CategoriesControllerTests
{
private readonly Mock<IMapper> _mapper;
private readonly Mock<IUnitOfWork> _unitOfWork;
public CategoriesControllerTests()
{
_mapper = new Mock<IMapper>();
_unitOfWork = new Mock<IUnitOfWork>();
}
[Fact]
public async Task Get_OK_ObjectResult_CategoryById()
{
//Arrange
Category newCategory = CreateTestCategory();
var spec = new GetCategoriesWithParentsSpecification(1);
_unitOfWork.Setup(x => x.Repository<Category>().GetEntityWithSpec(spec)).ReturnsAsync(newCategory)
.Verifiable();
//Act
// Here it is working and result2 has data.
var result2 = await _unitOfWork.Object.Repository<Category>().GetEntityWithSpec(spec);
var controller = new CategoriesController(_unitOfWork.Object, _mapper.Object);
var result = await controller.GetCategoryById(1);
// Assert
result.Value?.Id.ShouldBe(newCategory.Id);
result.Value?.Name.ShouldBeEquivalentTo(newCategory.Name);
result.Value?.Name.ShouldBeEquivalentTo("newCategory.Name");
// My problem here. My result is NotFoundObjectResult always.
result.Result.ShouldBeOfType<OkObjectResult>();
}
private Category CreateTestCategory()
{
return new Category()
{
Id = 1,
Priority = 1,
Name = "Test Category",
Enabled = true,
Details = "Testing category data"
};
}
}
`
The spec that you pass during the moq setup isn't the same as the spec that your repository receives inside the controller
In your test, you should change the setup in such a way that it checks the type of input instead and avoid passing a reference.
_unitOfWork.Setup(x => x.Repository<Category>()
.GetEntityWithSpec(It.IsAny<ISpecification<Category>>()))
.ReturnsAsync(newCategory)
.Verifiable();
Here we set up the moq in a way that as long as the input is ISpecification<Category>, it returns newCategory
The specificatio didn't use truly. Your setup should be like this:
_unitOfWork.Setup(x => x.Repository<Category>()
.GetEntityWithSpec(It.IsAny<ISpecification<Category>>()))
.ReturnsAsync(newCategory)
.Verifiable();
I am trying to implement a repository pattern, however I don't understand how its possible when entities have id's of different types. Currently I have to fallback to using object, while I would really like to use the specific type of the id of the entity the repository is holding.
interface IEntity
{
object GetId();
}
class Foo : IEntity
{
private string id;
public Foo(string id)
{
this.id = id;
}
public object GetId()
{
return id;
}
}
class Bar : IEntity
{
private int id;
public Bar(int id)
{
this.id = id;
}
public object GetId()
{
return id;
}
}
class Repository<T> where T : IEntity
{
private Dictionary<object, T> entities = new Dictionary<object, T>();
public IEnumerable<T> List => entities.Values.AsEnumerable();
public void Add(T entity)
{
entities.Add(entity.GetId(), entity);
}
public T Get(object id)
{
return entities[id];
}
}
class Program
{
static void Main(string[] args)
{
var foo = new Foo("0");
var bar = new Bar(0);
var fooRepo = new Repository<Foo>();
fooRepo.Add(foo);
fooRepo.Get(foo.GetId());
var barRepo = new Repository<Bar>();
barRepo.Add(bar);
barRepo.Get(bar.GetId());
}
}
I also tried something like:
class Repository<Id, Value> where Value : IEntity
{
private Dictionary<Id, Value> entities = new Dictionary<Id, Value>();
public IEnumerable<Value> List => entities.Values.AsEnumerable();
public void Add(Value entity) // But got stuck here, I don't want to pass in Id as separate parameter, I want it auto magically from the interface.
{
entities.Add(entity.GetId(), entity);
}
public Value Get(Id id)
{
return entities[id];
}
}
You can add a generic type of the key to IEntity. E.g.,
interface IEntity<TId>
{
TId GetId();
}
class Foo : IEntity<string>
{
private string id;
public Foo(string id)
{
this.id = id;
}
public string GetId()
{
return id;
}
}
class Repository<TEntity, TId> where TEntity : IEntity<TId>
{
private Dictionary<TId, TEntity> entities = new Dictionary<TId, TEntity>();
public void Add(TEntity entity)
{
entities.Add(entity.GetId(), entity);
}
public TEntity Get(TId id)
{
return entities[id];
}
}
Joel's solution could be extended to allow for variance. The same way generic collections implement both IEnumerable and IEnumerable<T>.
Entity
interface IEntity
{
object GetId();
}
interface IEntity<TId> : IEntity
{
new TId GetId();
}
abstract class EntityBase<TId> : IEntity<TId>
{
protected TId id;
protected EntityBase(TId id)
{
this.id = id;
}
public TId GetId() => id;
object IEntity.GetId() => GetId();
}
Repository
abstract class Repository
{
protected Dictionary<object, IEntity> entities;
protected Repository()
{
entities = new Dictionary<object, IEntity>();
}
public virtual void Add(IEntity entity)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
entities.Add(entity.GetId(), entity);
}
public virtual IEntity Get(object id)
{
if (id == null) throw new ArgumentNullException(nameof(id));
return entities[id];
}
}
abstract class Repository<TId, TEntity> : Repository
where TEntity : class, IEntity<TId>
{
protected Repository() : base() { }
public override void Add(IEntity entity)
{
Add((TEntity)entity);
}
public override IEntity Get(object id)
{
return Get((TId)id);
}
public void Add(TEntity entity)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
entities.Add(entity.GetId(), entity);
}
public TEntity Get(TId id)
{
if (id == null) throw new ArgumentNullException(nameof(id));
return (TEntity)entities[id];
}
}
Use Case
class Foo : EntityBase<string>
{
public Foo(string id) : base(id) { }
}
class Bar : EntityBase<int>
{
public Bar(int id) : base(id) { }
}
class FooRepository : Repository<string, Foo>
{
public FooRepository() { }
}
class BarRepository : Repository<int, Bar>
{
public BarRepository() { }
}
Test
[TestMethod]
public void IEntitySupport()
{
// use IEntity and object
IEntity bar = new Bar(1);
Repository barRepository = new BarRepository();
barRepository.Add(bar);
var bar2 = barRepository.Get((object)1);
Assert.AreSame(bar, bar2);
}
[TestMethod]
public void TEntitySupport()
{
// use TEntity and TId
var foo = new Foo("a");
var fooRepository = new FooRepository();
fooRepository.Add(foo);
var foo2 = fooRepository.Get("a");
Assert.AreSame(foo, foo2);
}
I am building out unit tests for a small app we need to build.
I have implemented the Repository / Unit Of Work pattern. My manager classes implement the unit of work pattern.
For a given interface:
public interface IUserManager
{
List<ApplicationUser> GetUsers(Expression<Func<ApplicationUser, bool>> filter = null);
ApplicationUser GetUser(Expression<Func<ApplicationUser, bool>> filter);
ApplicationUser AddUser(string username, List<string> environmentIds, bool isAdmin = false);
void DeleteUser(string username);
ApplicationUser UpdateUser(string id, List<string> environmentIds, bool isAdmin = false);
IList<string> GetUserRoles(string id);
}
I have implemented
public class UserManager : IUserManager
{
#region private fields
private readonly IRepository<ApplicationUser> _userRepository;
private readonly IRepository<Application> _applicationRepository;
private readonly IRepository<Role> _roleRepository;
private readonly IActiveDirectoryManager _activeDirectoryManager;
#endregion
#region ctor
public UserManager(AppDbContext context, IActiveDirectoryManager activeDirectoryManager)
{
_activeDirectoryManager = activeDirectoryManager;
_userRepository = new Repository<ApplicationUser>(context);
_applicationRepository = new Repository<Application>(context);
_roleRepository = new Repository<Role>(context);
}
#endregion
#region IUserManager
public ApplicationUser AddUser(string username, List<string> applicationIds, bool isAdmin = false)
{
//Get the environments in the list of environmentIds
var applications = _applicationRepository.Get(e => applicationIds.Contains(e.Id)).ToList();
//Get the user from AD
var user = _activeDirectoryManager.GetUser(username);
//set the Id
user.Id = Guid.NewGuid().ToString();
//add the environments to the user
applications.ForEach(x =>
{
user.Applications.Add(x);
});
//if the user is an admin - retrieve the role and add it to the user
if (isAdmin)
{
var role = _roleRepository.Get(r => r.Name == "admin").FirstOrDefault();
if (role != null)
{
user.Roles.Add(role);
}
}
//insert and save
_userRepository.Insert(user);
_userRepository.Save();
//return the user
return user;
}
//removed for brevity
}
My unit test class:
[TestClass]
public class UserManagerUnitTest
{
private readonly Mock<IActiveDirectoryManager> _adManager;
private readonly IUserManager _userManager;
private readonly Mock<IRepository<Application>> _applicationRepository;
private readonly Mock<IRepository<ApplicationUser>> _userRepository;
private readonly Mock<IRepository<Role>> _roleRepository;
public UserManagerUnitTest()
{
var context = new Mock<AppDbContext>();
_adManager = new Mock<IActiveDirectoryManager>();
_applicationRepository = new Mock<IRepository<Application>>();
_userRepository = new Mock<IRepository<ApplicationUser>>();
_roleRepository = new Mock<IRepository<Role>>();
_userManager = new UserManager(context.Object, _adManager.Object);
}
[TestMethod]
[TestCategory("AddUser"), TestCategory("Unit")]
public void AddUser_ValidNonAdmin_UserIsAdded()
{
#region Arrange
string username = "testUser";
List<string> applicationIds = new List<string>() {"1", "2", "3"};
_applicationRepository.Setup(x => x.Get(It.IsAny<Expression<Func<Application, bool>>>(),
It.IsAny<Func<IQueryable<Application>, IOrderedQueryable<Application>>>(), It.IsAny<string>()))
.Returns(new List<Application>());
_adManager.Setup(x => x.GetUser(It.IsAny<string>())).Returns(new ApplicationUser());
#endregion
#region Act
var result = _userManager.AddUser(username, applicationIds, false);
#endregion
#region Assert
Assert.IsNotNull(result);
Assert.IsFalse(result.IsAdmin);
#endregion
}
}
And finally the repository interface:
public interface IRepository<TEntity> where TEntity : class
{
IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity> , IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "");
TEntity GetById(object id);
void Insert(TEntity entity);
void Delete(object id);
void Delete(TEntity entityToDelete);
void Update(TEntity entityToUpdate);
void Save();
}
And implementation:
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
private readonly AppDbContext _context;
internal DbSet<TEntity> DbSet;
public Repository(AppDbContext context)
{
_context = context;
DbSet = _context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = DbSet;
if (filter != null)
query = query.Where(filter);
foreach (var prop in includeProperties.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(prop);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual TEntity GetById(object id)
{
return DbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
DbSet.Add(entity);
}
public virtual void Delete(object id)
{
TEntity entityToDelete = DbSet.Find(id);
Delete(entityToDelete);
}
public void Get(Expression<Func<Application, bool>> expression, Func<IQueryable<Application>> func, IOrderedQueryable<Application> orderedQueryable)
{
throw new NotImplementedException();
}
public virtual void Delete(TEntity entityToDelete)
{
if (_context.Entry(entityToDelete).State == EntityState.Detached)
{
DbSet.Attach(entityToDelete);
}
DbSet.Remove(entityToDelete);
}
public virtual void Update(TEntity entityToUpdate)
{
DbSet.Attach(entityToUpdate);
_context.Entry(entityToUpdate).State = EntityState.Modified;
}
public void Save()
{
_context.SaveChanges();
}
}
my problem is in the mock IRepository<Application>
_applicationRepository.Setup(x => x.Get(It.IsAny<Expression<Func<Application, bool>>>(),
It.IsAny<Func<IQueryable<Application>, IOrderedQueryable<Application>>>(), It.IsAny<string>()))
.Returns(new List<Application>());
For some reason - actual method is being used versus the overridden proxy from Moq. When the test executes - I get a null reference on the Get method of the repository - specifically on the query = DbSet:
public Repository(AppDbContext context)
{
_context = context;
DbSet = _context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = DbSet; **//null here because db should be** mocked
if (filter != null)
query = query.Where(filter);
I am trying to test just the UserManager implementation - not the repository implementation.
What would be the correct way to set this test up?
The issue is you are passing the AppDbContext in the constructor of UserManager, which makes it dependent on it. The class in turn is creating internal instances of the repositories, thus always using the concrete classes:
public UserManager(AppDbContext context, IActiveDirectoryManager activeDirectoryManager)
{
_activeDirectoryManager = activeDirectoryManager;
_userRepository = new Repository<ApplicationUser>(context);
_applicationRepository = new Repository<Application>(context);
_roleRepository = new Repository<Role>(context);
}
You should instead abstract out the creation of the repositories and modify the constructor so that it takes an instance based on the interfaces:
public UserManager(IRepository<ApplicationUser> userRepository, IRepository<Application> applicationRepository, IRepository<Role> roleRepository, IActiveDirectoryManager activeDirectoryManager)
{
_activeDirectoryManager = activeDirectoryManager;
_userRepository = userRepository;
_applicationRepository = applicationRepository;
_roleRepository = roleRepository;
}
This way you are able to abstract out the repositories so your mocks are used instead of the real classes.
I have a RepositoryBase class that does some basic operations on Entities which are derived from EntityBase.
public class RepositoryBase
{
private ApplicationDbContext _context;
public DbSet<EntityBase> DbSet;
public RepositoryBase(ApplicationDbContext context )
{
_context = context;
}
public List<EntityBase> List(int entityStatus)
{
return DbSet.Where(a => a.EntityStatusId == entityStatus).OrderBy(a => a.Name).ToList();
}
public EntityBase GetTeamDetails(int id)
{
return this.DbSet.FirstOrDefault(a => a.Id == id);
}
internal List<EntityBase> ListActive()
{
return DbSet.Where(a => a.EntityStatusId == (int)EntityStatus.Active).ToList();
}
internal List<EntityBase> ListTrashed()
{
return DbSet.Where(a => a.EntityStatusId == (int)EntityStatus.Trashed).ToList();
}
public void SaveProject(EntityBase item)
{
DbSet.Attach(item);
_context.Entry(item).State = EntityState.Modified;
_context.SaveChanges();
}
public List<EntityBase> ListArchived()
{
return DbSet.Where(a => a.EntityStatusId == (int)EntityStatus.Archived).ToList();
}
internal List<EntityBase> Search(string searchText)
{
return DbSet.Where(a => a.Name.Contains(searchText)).ToList();
}
public EntityBase New(EntityBase item)
{
DbSet.Add(item);
_context.SaveChanges();
return item;
}
}
The issue I am having is passing the DbSet to the base class. This is what I want to do:
public TeamRepository(ApplicationDbContext context) : base(context)
{
this.DbSet = (DbSet<EntityBase>)context.Teams;
}
However, this does not compile. It says it cannot cast from DbSet to DbSet even through Team is derived from EntityBase.
How do I make this cast?
you can make it generic this way:
public class BaseRepository<T> : IBaseRepository<T> where T : EntityBase
{
public BaseRepository(CustomDBContext context)
{
if (context == null)
{
throw new ArgumentNullException("context", "The given parameter cannot be null.");
}
this.Context = context;
}
protected ApplicationDbContext Context
{
get;
private set;
}
public T Get(int id)
{
return Context.Set<T>().Find(id);
}
.....
}
You can't do it like that. What you can do is:
this.DbSet = context.Set<EntityBase>();
I am using Autofac for IoC in my project. I have layers for repository, service and web api.
I have class AutofacWebApi in my web api project that I use for registering repository, service and dbcontext.
public class AutofacWebApi
{
public static void Initialize(HttpConfiguration config)
{
Initialize(config, RegisterServices(new ContainerBuilder()));
}
public static void Initialize(HttpConfiguration config, IContainer container)
{
config.DependencyResolver =
new AutofacWebApiDependencyResolver(container);
}
private static IContainer RegisterServices(ContainerBuilder builder)
{
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// registration goes here
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).PropertiesAutowired();
//EF DbContext
builder.RegisterType(typeof(MOCContext)).As(typeof(DbContext)).InstancePerLifetimeScope();
builder.RegisterType(typeof(UnitOfWork)).As(typeof(IUnitOfWork)).InstancePerLifetimeScope();
//Repositories
builder.RegisterGeneric(typeof(GenericRepository<>)).As(typeof(IGenericRepository<>)).InstancePerLifetimeScope();
builder.RegisterType<CityRepository>()
.As<ICityRepository>()
.InstancePerLifetimeScope();
//Services
builder.RegisterType<CityService>().As<ICityService>().InstancePerLifetimeScope();
return builder.Build();
}
}
My web api controler is like this
public class CityController : ApiController
{
readonly ICityService _cityService;
public CityController(ICityService cityService)
{
_cityService = cityService;
}
public IHttpActionResult Get(int id)
{
var result = _cityService.GetById(id);
return Ok("fdsafds");
}
}
When I call method GetById I got null, but I know that the method should return something because if I call the same method from mvc application I got correct result.
CityService
public class CityService : ICityService
{
IUnitOfWork _unitOfWork;
ICityRepository _cityRepository;
public CityService(IUnitOfWork unitOfWork, ICityRepository cityRepository)
: base()
{
_unitOfWork = unitOfWork;
_cityRepository = cityRepository;
}
public CityDTO GetById(int Id)
{
var result=_cityRepository.GetById(Id);
Mapper.CreateMap<City, CityDTO>()
.ForMember(x=>x.Id,m=>m.MapFrom(d=>d.Id));
var map = Mapper.Map<City, CityDTO>(result);
return map;
}
}
ICityService
public interface ICityService
{
CityDTO GetById(int Id);
}
ICityRepository
public interface ICityRepository:IGenericRepository<City>
{
City GetById(int id);
}
CityRepository
public class CityRepository:GenericRepository<City>, ICityRepository
{
public CityRepository(DbContext context)
: base(context)
{
}
public City GetById(int id)
{
var result = Get(x => x.Id == id);
return result;
}
}
IGenericRepository
public interface IGenericRepository<T> where T : BaseEntity
{
IEnumerable<T> GetAll();
IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate);
T Add(T entity);
T Delete(T entity);
void Edit(T entity);
void Save();
}
GenericRepository
public abstract class GenericRepository<T> : IGenericRepository<T>
where T : BaseEntity
{
protected DbContext _entities;
protected readonly IDbSet<T> _dbset;
public GenericRepository(DbContext context)
{
_entities = context;
_dbset = context.Set<T>();
}
public virtual IEnumerable<T> GetAll()
{
return _dbset.AsEnumerable<T>();
}
public T Get(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
T query = _dbset.Where(predicate).SingleOrDefault();
return query;
}
public IEnumerable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
IEnumerable<T> query = _dbset.Where(predicate).AsEnumerable();
return query;
}
public virtual T Add(T entity)
{
return _dbset.Add(entity);
}
public virtual T Delete(T entity)
{
return _dbset.Remove(entity);
}
public virtual void Edit(T entity)
{
_entities.Entry(entity).State = System.Data.Entity.EntityState.Modified;
}
public virtual void Save()
{
_entities.SaveChanges();
}
}
I don't know why method GetById return result null.
Thanks