Can i pass context in params from controller?

illud

New member
Joined
Jul 7, 2023
Messages
3
Programming Experience
5-10
Hello, im using entity framework, i create context in controller the past into the parameters to service and then repository to make sql queries,
is ok to do that?
or theres a better way?

Controller
C#:
private readonly DataContextDb _db;
public UsersController(DataContextDb contextDb)
{
    _db = contextDb;
}


[HttpGet(Name = "GetUsers")]
public async Task<List<UsersModel>> Get()
{
    UsersService usersService = new();
    return await usersService.Get(_db); //context(_db) in function parameter
}

Services
C#:
public async Task<List<UsersModel>> Get(DataContextDb _db)
{
    UsersRepository usersRepository = new();

    return await usersRepository.GetUsers(_db);//context(_db) in function parameter
}

Repository
C#:
public async Task<List<UsersModel>> GetUsers(DataContextDb _db)//context(_db) in function parameter
{
    return await _db.Users.ToListAsync();
}
 
No it is not okay. You should also be using you inversion of control framework to use the dependency injection to pass that in where it is needed.

Also, why do you have a repository? EntityFramework already implements both that repository pattern and unit of work patterns for you. You are adding an extra later for the sake of cargo cult programming.
 
No it is not okay. You should also be using you inversion of control framework to use the dependency injection to pass that in where it is needed.

Also, why do you have a repository? EntityFramework already implements both that repository pattern and unit of work patterns for you. You are adding an extra later for the sake of cargo cult programming.

Hello, im new with core api an c# in general, could you give a example of how to do that or where to read about this?
 
No it is not okay. You should also be using you inversion of control framework to use the dependency injection to pass that in where it is needed.

Also, why do you have a repository? EntityFramework already implements both that repository pattern and unit of work patterns for you. You are adding an extra later for the sake of cargo cult programming.

So i did a quick research on repository pattern like you said and this is how its done
The only question is where to put business logic, in controller?

Interface
C#:
public interface IUserRepository
{
    Task<UserLoginResponseObject> Create(UserDto users);
    Task<List<UsersModel>> GetUsers();
    Task<ActionResult<UserLoginResponseObject>> GetOneUser(UserLoginDto user);
}

Repository
C#:
private readonly DataContextDb _db;
public UsersRepository(DataContextDb contextDb)
{
    _db = contextDb;
}

public async Task<UserLoginResponseObject> Create(UserDto users)
{
    BcryptService bcryptService = new();

    _db.Users.Add(new UsersModel {
        Id = users.Id,
        Name = users.Name,
        Age = users.Age,
        UserName = users.UserName,
        Password = bcryptService.HashPassword(users.Password)
        });

    await _db.SaveChangesAsync();
    return new UserLoginResponseObject { response = "Created" };
}

Controller
C#:
private readonly IUserRepository _userRepository;
public UsersController(IUserRepository userRepository) {
    _userRepository = userRepository;
}

[HttpPost(Name = "PostUser"), AllowAnonymous]
public async Task<UserLoginResponseObject> Post(UserDto users)
{
    return await _userRepository.Create(users);
}
 
Mostly I see people keep controllers relatively light, calling something else that has the business logic in, and leaving the controller to focus on making a call, and issuing ok or error responses, managing the http side of things etc.
In small apps I tend to load the controller up a bit more with responsibility - for me it depends on the extent that I want to swap stuff out for testing with mocked data

Rather than creating a repository layer, more recently I've started creating extension methods for the context where I might formerly have had a class I called a repository that had the set of ops I wanted to perform on the data source; again that's acknowledging that in the real world we seldom wholesale change our database out for another one but maybe one day you will grow the app to the extent that you want to have a whole extra layer to implement some system wide shifting or dynamic selection of multiple side-by-side different data sources for the same data. Refactoring is always possible and not really that onerous once the existing system has taught you the extents of the problem you have to get to grips with

You don't appear to be using a mapper, and you could apparently make use of one. I also question why you're sending passwords and hashes around (do you have passwords that aren't hashed?!) and IMHO you need to pay more close attention to your pluralizing - "UserDto users" does not represent multiple users, it represent one user. UsersModel is not a class for more than one user. If your database tables are called Users etc then leverage EF's plural conversions to make your classes called UserModel etc. Plural variables are for collections, enumerables etc, and classes shouldn't be named in the plural

I know I've laid some rules down, but remember that mostly engineering is about making choices between a set of options that will work; it's more important that you can justify your choices for right now and that you're willing to change them if it starts biting you in the ass. If you can justify naming singular variables plural I'll accept it; for me "books.Where(b => b.Title == ...)" reads more sensibly than "book.Where" - having a plural to go with an operation that is clearly performed on a collection is logical. Seeing "book.Where" doesn't immediately make me think "book" is a collection of books; it makes me think a book is some kind of a collection of Page (why is it not called "pages"?) and Where will get me a Page. Writing code that actively confuses the reader with regards to sensible norms ("a plural named variable represents a collection") should be avoided
 
Last edited:
Mostly I see people keep controllers relatively light,

Let me paraphrase one of the authors of xUnit when they working on ASP.NET MVC: "I want my controllers to be like a Victoria's Secret super model: thin and wearing just enough to get the job done."
 
Back
Top Bottom