Here's how I typically build my n-tier applications, in this case, let's use an MVC web application project.
A class library, typically called: ProjectFoo.Domain
:
Here's where I create my abstract repositories for accessing data. For example:
public interface IAccountRepository
{
IEnumerable<Account> FindAll();
}
I also create my concrete implementations here, one accesses the real database, the other just returns mock information:
public class DbAccountRepository : IAccountRepository
{
public IEnumerable<Account> FindAll()
{
DbConnector db = new DbConnector();
return db.Accounts;
}
}
public class MockAccountRepository : IAccountRepository
{
public IEnumerable<Account> FindAll()
{
return new List<Account>(){
new Account { Name = "Sergio", Age = 22 },
new Account { Name = "Brad", Age = 42 },
new Account { Name = "Chelios", Age = 32 },
}
}
}
Next, in my UI project, typically called ProjectFoo.WebUI
:
Inside a controller I use dependency injection to sort out what implementation I'm working against:
public class AccountController
{
IAccountRepository _accountRepository = new IAccountRepository();
public AccountController(IAccountRepository accountRepository)
{
_accountRepository = accountRepository;
}
public ActionResult Index()
{
// Magic! We don't need to know what exactly we're working against.
var accounts = accountRepository.FindAll();
}
}
Now onto your question, How to pass user input from the UI to the BL?
.
I have my interface written like this:
public class DbAccountRepository : IAccountRepository
{
// Notice this is the entity object type.
public void AddAccount(Account account)
{
db.AddToAccounts(account);
db.SaveChanges();
}
}
Grab user input, shape it, validate it, fit it inside a simple POCO object - once you're sure it's sanitized and functioning correctly, use something like AutoMapper to map to your entity object and pass fully loaded object along the chain towards your repository.
If you have any question or don't quite understand something let me know.