mvc5 N tier architecture - asp.net-mvc-5.1

I am developing an mvc app with the following N tier structure:
DataAccess
Repository
Models
BusinessLogic
In my BusinessLogic folder I have an interface IClinicBusiness and a class ClinicBusiness that interfaces with IClinicBusiness.
The ClinicBusiness class is as follows:
public void AddClinic(Clinic c)
{
var cr = new ClinicRepository();
var clinc = new Clinic();
if (c != null)
{
clinc.ClinicName = c.ClinicName;
clinc.ClinicLocation = c.ClinicLocation;
}
cr.InsertClinic(c);
cr.Save();
}
}
The ClinicBusiness class implements a method from the Repository class library eg. InsertClinic();
public ClinicRepository()
{ }
public ClinicRepository(DataContext clinics)
{
this.clinic = clinics;
}
public IEnumerable<Clinic> GetClinics()
{
return clinic.Clinics.ToList();
}
public Clinic GetClinicByID(int ClinicId)
{
return clinic.Clinics.Find(ClinicId);
}
public void InsertClinic(Clinic c)
{
clinic.Clinics.Add(c);
}
In my controller I have an action
public ActionResult CreateClinic(Clinic c)
{
var clinicBusiness = new ClinicRepository();
return View(clinicBusiness.InsertClinic(c));
}
I get the following error cannot convert from 'void' to 'object'
Can someone please guide me?

Depending on your requirements, I think you want to change your repository InsertClinic method to
public Clinic InsertClinic(Clinic c)
{
clinic.Clinics.Add(c);
return c;
}
Or change your Action to
public ActionResult CreateClinic(Clinic c)
{
var clinicBusiness = new ClinicRepository();
clinicBusiness.InsertClinic(c)
return View(c);
}
Again, it just depends on what your trying to accomplish and your view model.

Related

How do I resolve dependencies using an object of an associated type using AutoFac?

I am having a difficult time figuring out how to create a 1:1 mapping between objects in a container using AutoFac. I am getting resolution errors and the documentation is too terse with not enough examples.
Here's the rule I would like to use to resolve my dependencies:
An IHouse object can only be constructed using an IDoor parameter of a specific concrete type, creating a 1:1 mapping between IHouse and IDoor types.
As am example, using the code below, if I resolve the container using a MonkeyDoor, it should give me back a fully constructed MonkeyHouse and only a MonkeyHouse object.
[TestClass]
public class HousingDeveloperTest
{
[TestMethod]
public void TestMethod1()
{
// Load them from an assembly or disc. We are interested in IHouse and IDoor types
var builder = new ContainerBuilder();
// Get all the houses
var assembly = Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.Name.EndsWith(nameof(House))).AsImplementedInterfaces();
// get all the doors
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.Name.EndsWith(nameof(Door))).AsImplementedInterfaces();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var house = container.Resolve<IDoor>(new TypedParameter(typeof(MonkeyDoor), new MonkeyDoor()));
}
}
}
public interface IDoor
{
void Open();
}
public abstract class Door : IDoor
{
public void Open()
{
Trace.WriteLine($"Opening {GetType().ToString()}.");
}
}
// Only works with Victorian homes
public class VictorianDoor : Door
{
}
// Only works with Craftsman homes
public class CraftsmanDoor : Door
{
}
// Only works with monkey homes
public class MonkeyDoor : Door
{
}
public interface IHouse
{
void OpenHouse();
}
public abstract class House : IHouse
{
public IDoor Door;
protected House(IDoor door)
{
Door = door;
Trace.WriteLine($"Building this {this.GetType()} with {door.GetType()} door.");
}
public void OpenHouse()
{
Trace.WriteLine($"We're having an open house on this wonderful {this.GetType().ToString()}.");
Door.Open();
}
}
// Doors must match the homes. (i.e. No monkey doors on a Victorian or Craftsman home.)
public class VictorianHouse : House
{
public VictorianHouse(VictorianDoor door) : base(door)
{
}
}
public class CraftsmanHouse : House
{
public CraftsmanHouse(CraftsmanDoor door) : base(door)
{
}
}
public class MonkeyHouse : House
{
public MonkeyHouse(MonkeyDoor door) : base(door)
{
}
}

Autofac, multiple interfaces to same implementation per HTTP request in ASP.NET MVC

My DbContext implementation implements two interfaces.
I'm trying to follow best practices and instantiate one DbContext instance per HTTP request.
However, I have a controller action where I need to instantiate two classes, each of which takes different interface in constructor.
I am worried if in that scenario, for that specific action, two DbContext instances would be raised.
I've setup my ContainerBuilder like this:
builder.RegisterType<MyDbContext>()
.As<IWorkflowPersistenceStore>()
.As<IDocumentPersistenceStore>()
.InstancePerHttpRequest();
builder.RegisterType<WorkflowManager>().As<IWorkflowManager>().InstancePerHttpRequest();
builder.RegisterType<DocumentManager>().As<IDocumentManager>().InstancePerHttpRequest();
public class OperationController : Controller
{
private IWorkflowManager _workflowManager;
private IDocumentManager _documentManager;
public OperationController(IWorkflowManager workflowManager, IDocumentManager documentManager)
{
_workflowManager = workflowManager;
_documentManager = documentManager;
}
public ActionResult SaveWorkflowDocument(...)
{
// will my managers point to same DbContext?
_workflowManager.DoSomething(...);
_documentManager.DoSomethingElse(...);
return View();
}
}
public class WorkflowManager : IWorkflowManager
{
private IWorkflowPersistenceStore _store;
public WorkflowManager(IWorkflowPersistenceStore store)
{
_store = store;
}
}
public class DocumentManager : IDocumentManager
{
private IDocumentPersistenceStore _store;
public DocumentManager (IDocumentPersistenceStore store)
{
_store = store;
}
}
Is this good enough?
Do I have to add .SingleInstance()? I'm worried that it might create singleton for whole application.
I think you're ok with what you have. Test passes:
using Autofac;
using NUnit.Framework;
namespace AutofacTest
{
[TestFixture]
public class ScopeTest
{
[Test]
public void Test()
{
var builder = new ContainerBuilder();
builder.RegisterType<Component>()
.As<IServiceA>()
.As<IServiceB>()
.InstancePerLifetimeScope();
using (var container = builder.Build())
using (var scope = container.BeginLifetimeScope())
{
var a = scope.Resolve<IServiceA>();
var b = scope.Resolve<IServiceB>();
Assert.AreEqual(a, b);
}
}
}
public interface IServiceA { }
public interface IServiceB { }
public class Component : IServiceA, IServiceB { }
}

Intranet Application - Data Access in separate project

I have an MVC intranet application which uses EF 6. I have setup the DataAccess project in a separate class library which has EF 6 referenced. I have an entity which implements an interface:
public interface IAuditable
{
DateTime CreatedDateTime { get; set; }
string CreatedBy { get; set; }
}
public class Collection : IAuditable
{
// Properties
}
However, in the SaveChanges method I obviously don't have access to HttpContext.Current.User.Identity.Name as it is in a separate class library, so I was wondering how one would set this in SaveChanges?
public override int SaveChanges()
{
var addedEntries = ChangeTracker.Entries().Where(x => x.State == EntityState.Added);
foreach (var dbEntityEntry in addedEntries)
{
var entity = dbEntityEntry.Entity as IAuditable;
if (entity != null)
{
entity.CreatedDateTime = DateTime.Now;
// how do I set entity.CreatedBy = HttpContext.Current.User.Identity.Name?
}
}
return base.SaveChanges();
}
Edit
Following on from #CodeCaster solution, I have the following:
[BreezeController]
public class BreezeController : ApiController
{
private readonly BTNIntranetRepository _repository;
public BreezeController(BTNIntranetRepository repository)
{
_repository = repository;
_repository.LoggedInUser = HttpContext.Current.User.Identity.Name;
}
// Methods
}
But HttpContext.Current.User is null
This can be solved in many ways.
You're not really showing relevant code, but you can for example give the library class you expose a public string LoggedInUser (or ActingUser or give it a name) property which you set when instantiating it:
public class SomeController : Controller
{
private IDataSource _dataSource;
public SomeController(IDataSource dataSource)
{
_dataSource = dataSource;
_dataSource.LoggedInUser = HttpContext.Current.User.Identity.Name
}
}
You can then simply use that property in your IDataSource.SaveChanges() method:
public override int SaveChanges()
{
// ...
entity.CreatedBy = this.LoggedInUser;
}

How to cast a class to an interface using generics in c#?

I've this interface:
public interface IRepository<T>
{
List<T> List();
T Get(int Id);
bool Add(T entity);
bool Update(T entity);
}
And I've this class:
public class Customer<T> : IRepository<Entities.Customer>
{
public Entities.Customer Get(int Id)
{
var c = new Entities.Customer();
return c;
}
//continue...
}
How can I cast a generic class to a generic interface like so:
//Other method
public IRepositorio<T> DoStuff<T>(int Id)
{
var a = (IRepository<Entities.Customer>)Activator.CreateInstance(typeof(T)); // ok
var b = (IRepository<T>)Activator.CreateInstance(typeof(T)); // Exception: unable to cast
return object; // an object
}
And I call from this MCV controller:
public ActionResult Home()
{
var repo = new Repository();
repo.DoStuff<Customer<Entities.Custormer>>(10);
return View();
}
My conception is ok? This is possible without dynamic?
Based on the code supplied, I've tried the following which compiles OK
public class Entities {
public class Customer {
}
}
public interface IRepository<T> {
T Get(int Id);
}
public class Customer<T> : IRepository<Entities.Customer> {
public Entities.Customer Get(int Id) {
var cliente = new Entities.Customer();
return cliente;
}
}
public class foo {
public static IRepository<T> DoStuff<T>(int Id) {
var a = (IRepository<Entities.Customer>)Activator.CreateInstance(typeof(T));
var b = (IRepository<T>)Activator.CreateInstance(typeof(T));
return b; // an object
}
}
However, I'm not sure what T is meant to be. When I run and call
foo.DoStuff<Entities.Customer>(0);
then I get a runtime error on the var a line, because the class Entities.Customer does not implement the interface IRepository<T>. If I call
foo.DoStuff<Customer<Entities.Customer>>(0);
then I get the runtime error on the 'var b' line, because the class Customer<Entities.Customer> implements IRepository<Entities.Customer> and not IRepository<Customer<Entities.Customer>>
Both exceptions are correct, so hopefully the author of the question can work out where the problem lies from this answer.
Activator.CreateInstance(typeof(T)); - this creates for you new instance of T, which is Entities.Customer in your example, but it looks like you want to create instance of Customer<Entities.Customer>.

How to avoid repositories that duplicate code

I have successfully setup a simple mvc application that lists teams. I'm using Ninject to inject the appropriate repository depending on the controller (thanks to stack overflow ;). All looks good, except that the repository code looks exactly the same. And I know that's wrong. So my TeamRepository has two classes (for now).
public class SwimTeamRepository : ITeamRepository<SwimTeam>
{
private readonly Table<SwimTeam> _teamTable;
public SwimTeamRepository(string connectionString)
{
_teamTable = (new DataContext(connectionString).GetTable<SwimTeam>());
}
public IQueryable<SwimTeam> Team
{
get { return _teamTable; }
}
}
public class SoccerTeamRepository : ITeamRepository<SoccerTeam>
{
private readonly Table<SoccerTeam> _teamTable;
public SoccerTeamRepository(string connectionString)
{
_teamTable = (new DataContext(connectionString).GetTable<SoccerTeam>());
}
public IQueryable<SoccerTeam> Team
{
get { return _teamTable; }
}
}
They look exactly the same except for the Class and Table name, so clearly I need to re-factor this. What would be the best approach here? Singleton? Factory Method?
Thanks in advance!
You could use generics:
public interface ITeamRepository<T>
{
}
public class TeamRepository<TTeam> : ITeamRepository<TTeam>
where TTeam : Team
{
private readonly Table<TTeam> _teamTable;
public TeamRepository(string connectionString)
{
_teamTable = (new DataContext(connectionString).GetTable<TTeam>());
}
public IQueryable<TTeam> Team
{
get { return _teamTable; }
}
}
public class Team
{
}
public class SwimTeam : Team
{
}
Then use it like so...
public void MyMethod()
{
var repository = new TeamRepository<SwimTeam>();
}
...and set up your IoC container w/ Ninject like so...
public class MyModule : NinjectModule
{
public override void Load()
{
Bind<ITeamRepository<SwimTeam>>
.To<TeamRepository<SwimTeam>>();
}
}
public void MyMethod()
{
var repository = kernel.Get<ITeamRepository<SwimTeam>>();
}
If you want to get REAL generic and have a single repository for ALL of your mapped classes, you can do something like this:
public interface IRepository
{
IQueryable<T> Get<T>() where T : class, new();
}
public class Repository : IRepository, IDisposable
{
private DataContext _dataContext;
public Repository(string connectionString)
{
_dataContext = new DataContext(connectionString);
}
public IQueryable<T> Get<T>()
where T : class, new()
{
return _dataContext.GetTable<T>().AsQueryable();
}
public void Dispose()
{
if (_dataContext != null)
{
_dataContext.Dispose();
_dataContext = null;
}
}
}
...which you could call like so (after setting up your Ninject container)...
using (var repository = kernel.Get<IRepository>())
{
var swimTeam = repository.Get<SwimTeam>();
}
Since Ninject takes care of the life-cycle management of your objects, you don't HAVE to wrap the repository in a using statement. In fact, you don't want to use a using statement there at all if you plan to use the repository more than once within the scope of its lifetime. Ninject will automatically dispose of it when it's life-cycle ends.
Here's a good article by Rob Conery on using this kind of technique to reduce the friction of using different ORMs.
EDIT by keeg:
I Think
public class TeamRepository<TTeam> : ITeamRepository<TTeam> where TTeam : Team {}
Should be
public class TeamRepository<TTeam> : ITeamRepository<TTeam> where TTeam : class {}
Please correct if I'm wrong.
Is this what you want?
public class TeamRepository : ITeamRepository<T>
{
private readonly Table<T> _teamTable;
public TeamRepository(string connectionString)
{
_teamTable = (new DataContext(connectionString).GetTable<T>());
}
public IQueryable<T> Team
{
get { return _teamTable; }
}
}

Resources