asp.net mvc autofac registery and resolver - asp.net-mvc

I am working on ASP.NET MVC 3 application. I am using Autofac as my dependency resolver.
I have two projects one core and other UI. In the core project I have an interface which holds
information about the logged in user if any. This is inherited in my UI project.
public interface IWebContext
{
User User {get;set}
bool IsLoggedIn {get;}
}
In ui project this is implemented as
public class WebContext : IWebContext
{
//codes here to get user and islogged in proerty.
}
In the core project I am creating link based on some logic.
public static class ButtonExtension
{
public static MvcHtmlString EditButton(this HtmlHelper helper, string controller, string action, object id, string text)
{
var webContext= how to get IWebContext here.
if (!webContext.IsLoggedIn)
{
return MvcHtmlString.Empty;
}
return MvcHtmlString.Create(string.Format("{3}", controller, action, id, text));
}
}
In my global.asax I am registering all my services using IOC static class
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
IOC.Build();
}
here is my IOC class.
public static class IOC
{
private static IContainer _container;
public static void Build()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.Register(c => new WebContext()).As<IWebContext>().SingleInstance();
builder.Register(c => new ImageServiceLocal()).As<IImageService>().InstancePerHttpRequest();
builder.RegisterFilterProvider();
_container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(_container));
}
public static T Resolve<T>()
{
if (_container == null)
Build();
return _container.Resolve<T>();
}
}

var webContext = DependencyResolver.Current.GetRequestLifetimeScope()
.Resolve<IWebContext>();

Related

Creating an OrmLite repository base class for ASP.NET

I'm trying to create a general base class that I can use in my whole project. I've written some code but still getting a NULL instance on my DbConnectionFactory.
I've create a ASP.Net web api project and added the AppHost file. I'm using Funq together with Simple Injector to Injector my custom services into the Api Controllers.
AppHost.cs
public class AppHost : AppHostBase
{
public AppHost() : base("Erp", typeof(AppHostService).Assembly)
{
}
public override void Configure(Container container)
{
// init
var simpleInjectorContainer = new SimpleInjector.Container();
var erpConnection = ConnectionStrings.ErpLocal;
var isLocal = HelperTools.IsLocalPath();
// check
if (isLocal)
{
erpConnection = ConnectionStrings.ErpOnline;
}
// mvc
ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container));
// register funq services
container.Register<IErpDbConnectionFactory>(c => new ErpDbConnectionFactory(erpConnectionString));
container.RegisterAutoWiredAs<CategoryService, ICategoryService>();
container.RegisterAutoWiredAs<ManufacturerService, IManufacturerService >();
container.RegisterAutoWiredAs<ProductService, IProductService>();
container.RegisterAutoWiredAs<ProductAttributeService, IProductAttributeService>();
container.RegisterAutoWiredAs<SpecificationAttributeService, ISpecificationAttributeService>();
//...
// simple injector services
SimpleInjectorInitializer.Initialize(simpleInjectorContainer, isLocal);
// register SimpleInjector IoC container, so ServiceStack can use it
container.Adapter = new SimpleInjectorIocAdapter(simpleInjectorContainer);
}
}
Base Class I'm trying to use
public abstract class ApiOrmLiteController : ApiController
{
IDbConnection _erpDb;
public virtual IErpDbConnectionFactory ErpDbConnectionFactory { get; set; }
public virtual IDbConnection ErpDb => _erpDb ?? (_erpDb = ErpDbConnectionFactory.OpenDbConnection());
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_erpDb?.Dispose();
}
}
Web Api Controller
public class ShippingController : ApiOrmLiteController
{
#region Fields
private readonly IOrderService _orderService;
private readonly IAddressService _addressService;
private readonly ICustomerService _customerService;
private readonly IPdfService _pdfService;
private readonly IMessageService _messageService;
private readonly ITranslationService _translationService;
#endregion Fields
#region Ctor
public ShippingController(IOrderService orderService, IAddressService addressService, ICustomerService customerService, IPdfService pdfService, IMessageService messageService, ITranslationService translationService)
{
_orderService = orderService;
_addressService = addressService;
_customerService = customerService;
_pdfService = pdfService;
_messageService = messageService;
_translationService = translationService;
}
#endregion Ctor
[HttpGet]
[System.Web.Http.Route("Test")]
public void Test()
{
var products = ErpDb.Select<Category>();
}
}
You may need to use constructor injection for Web API or MVC controllers, alternatively you can access dependencies in ServiceStack's IOC via HostContext.TryResolve<T>, e.g:
public virtual IDbConnection ErpDb => _erpDb ??
(_erpDb = HostContext.TryResolve<IErpDbConnectionFactory>().OpenDbConnection());

Using Microsoft.Extension.DependencyInjection in Asp.net Web Api2

I am trying to implement Asp.Net webApi project which is depending on a third-party framework that does a lot of stuff with HttpContext.Current which does not exists in Asp.net Core. That is why I could not create Asp.net Core Web Application targeting .net full framework.
So I created old-school Asp.net Web Application project with WebApi extension.
Now I am trying to use Microsoft.Extension.DependencyInjection framework with it.
I found this example for Asp.Net Mvc4 but my project is WebApi. That approach did not work. Can anyone provide link or code snippet for me to move forward?
P.S: When providing an example, please make sure it should not use OWIN framework. Because when I tried to use OWIN pipeline, the third-party library(closed source) is not working properly.
I also found that example a while ago, i make it work perfect both in
Asp.Net Mvc4 and WebApi2 project.
Use some IoC container (eg. Unity, Autofac) for WebApi project, the most important thing is implementing the interface IDependencyResolver to make your own dependency resolver.
Hers's my code snippet for WebApi project.
WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
// using Microsoft.Extension.DependencyInjection here.
Startup.Bootstrapper(config);
}
}
Startup
public class Startup
{
public static void Bootstrapper(HttpConfiguration config)
{
var provider = Configuration();
var resolver = new DefaultDependencyResolver(provider);
config.DependencyResolver = resolver;
}
private static IServiceProvider Configuration()
{
var services = new ServiceCollection();
services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
.Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
.Where(t => typeof(IHttpController).IsAssignableFrom(t)
|| t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));
var serviceProvider = services.BuildServiceProvider();
return serviceProvider;
}
}
DefaultDependencyResolver
public class DefaultDependencyResolver : IDependencyResolver
{
private IServiceScope serviceScope;
protected IServiceProvider ServiceProvider { get; set; }
public DefaultDependencyResolver(IServiceProvider serviceProvider)
{
this.ServiceProvider = serviceProvider;
}
public object GetService(Type serviceType)
{
return this.ServiceProvider.GetService(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return this.ServiceProvider.GetServices(serviceType);
}
public IDependencyScope BeginScope()
{
serviceScope = this.ServiceProvider.CreateScope();
return new DefaultDependencyResolver(serviceScope.ServiceProvider);
}
public void Dispose()
{
// you can implement this interface just when you use .net core 2.0
// this.ServiceProvider.Dispose();
//need to dispose the scope otherwise
//you'll get a memory leak
serviceScope?.Dispose();
}
}
ServiceProviderExtensions
public static class ServiceProviderExtensions
{
public static IServiceCollection AddControllersAsServices(this IServiceCollection services,
IEnumerable<Type> controllerTypes)
{
foreach (var type in controllerTypes)
{
services.AddTransient(type);
}
return services;
}
}

ArgumentNullException in WindsorControllerActivator

I have a project with multiple layers(assemblies). I used Castle Windsor to solve Dependency Injection. Also create my controllers with castle. so I installed and used castle in Web API and WebUI Layers too. Beside I have a bootstrapper layer which registers all services and repositories.
First my web API:
In WebApiConfig.cs file, I registered UI Dependencies with flowing code:
public static void Register(HttpConfiguration config)
{
var corsAttr = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(corsAttr);
// Web API configuration and services
var container = Bootstrapper.WireUp();// to register services and repositories
RegisterControllers(container);
config.Services.Replace(typeof(IHttpControllerActivator), new WindsorControllerActivator(container));
}
private static void RegisterControllers(IWindsorContainer container)
{
//container.Register(Component.For<VisitorController>().LifestylePerWebRequest());
//container.Register(Component.For<ValueController>().LifestylePerWebRequest());
//container.Register(Component.For<ValidateController>().LifestylePerWebRequest());
//container.Register(Component.For<CaptchaImageController>().LifestylePerWebRequest());
container.Register(Classes.FromAssemblyContaining<VisitorController>()
.BasedOn<ApiController>().LifestyleTransient());
}
And activator factory is like this:
public class WindsorControllerActivator : IHttpControllerActivator
{
private readonly IWindsorContainer _container;
public WindsorControllerActivator(IWindsorContainer container)
{
_container = container;
}
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
return (IHttpController)_container.Resolve(controllerType);//System.ArgumentNullException: Value cannot be null. error
}
}
Also in WebUI project I used Castle Windsor to create my controllers. But when I run the project I get "System.ArgumentNullException: Value cannot be null." error when is resolving Controller.I mean in this line:
(IHttpController)_container.Resolve(controllerType);
I also tried "LifeStylePerWebRequest" for my controllers and nothing were changed.
Whats more, nothing is wrong with WireUp Method,(Registering service and repositories works fine). This problem is just for controllers(in WebUI and WebApi projects). Same problem happens for WebUI project.
I normally use implementation of IDependencyResolver instead of IHttpControllerActivator. You can this approach instead. Add the floowing class:
public class WindsorDependencyResolver : IDependencyResolver
{
readonly IWindsorContainer _container;
public WindsorDependencyResolver(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException(nameof(container));
}
_container = container;
}
public IDependencyScope BeginScope()
{
return new WindsorDependencyScope(this, _container.Release);
}
public void Dispose()
{
}
public object GetService(Type t)
{
var ret = _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null;
return ret;
}
public IEnumerable<object> GetServices(Type t)
{
var ret = _container.ResolveAll(t).Cast<object>().ToArray();
return ret;
}
}
This class is required by the dependency resolver:
public class WindsorDependencyScope : IDependencyScope
{
readonly List<object> _instances;
readonly Action<object> _release;
readonly IDependencyScope _scope;
public WindsorDependencyScope(IDependencyScope scope, Action<object> release)
{
if (scope == null)
{
throw new ArgumentNullException(nameof(scope));
}
if (release == null)
{
throw new ArgumentNullException(nameof(release));
}
_scope = scope;
_release = release;
_instances = new List<object>();
}
public void Dispose()
{
foreach (object instance in _instances)
{
_release(instance);
}
_instances.Clear();
}
public object GetService(Type t)
{
var service = _scope.GetService(t);
AddToScope(service);
return service;
}
public IEnumerable<object> GetServices(Type t)
{
var services = _scope.GetServices(t);
AddToScope(services);
return services;
}
void AddToScope(params object[] services)
{
if (services.Any())
{
_instances.AddRange(services);
}
}
}
And this is how you register the the dependency resolver in you Register method:
config.DependencyResolver = new WindsorDependencyResolver(container);
I would recommend to register your controllers with lifestyle transient as the dependency resolver takes care of disposing them.

Using Unity with Web Api 2 gives error does not have a default constructor

I have ASP.NET MVC5 web application and i also have Web API in the same application. I am uisng Unity (version 4) for DI.
I am configuring the Unity container on APP start as below
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
UnityConfiguration.Config();
}
}
public class UnityConfiguration()
{
public void Config()
{
UnityContainer container = new UnityContainer();
container.RegisterType<IMyService, Myservice>();
container.RegisterType<IGenericRepository, GenericRepository>();
container.RegisterType<DbContext, MyEntities>();
}
}
public class GenericRepository:IGenericRepository
{
private DbContext _dbcontext;
public GenericRepository(DbContext dbcontext)
{
_dbcontext = dbcontext;
}
}
public class MyService:IMyService
{
private IGenericRepository _repo;
publi void MyService(IGenericRepository repository)
{
_repo = repository;
}
}
public class MyApiController:ApiController
{
provate IMyService _service;
MyApiController(IMyService myservice)
{
_service = myservice;
}
public IEnumerable<MyModel> GetData()
{
var result = _service.GetData();
return result.ConvertToMyModel();
}
}
However when i call the url like
localhost://lookup/getdata
I get error
Type 'LookupController' does not have a default constructor
How do i solve this issue? Do i need to register each controller i create with Unity or Unity automatically registers all MVC controllers?
I tend to use the Unity.Mvc-package.
You do not need to register the controllers, but you need to register Unity with WebAPI.
public class UnityConfiguration()
{
public IUnityContainer Config()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IMyService, Myservice>();
container.RegisterType<IGenericRepository, GenericRepository>();
container.RegisterType<DbContext, MyEntities>();
// return the container so it can be used for the dependencyresolver.
return container;
}
}
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Your routes...
// Register Unity with Web API.
var container = UnityConfiguration.Config();
config.DependencyResolver = new UnityResolver(container);
// Maybe some formatters?
}
}
You also need a DependencyResolver:
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
container.Dispose();
}
}
You can also take a look at this similiar question, except for the Owin-part. Unity.WebApi | Make sure that the controller has a parameterless public constructor
I had the same error and in my case the problem was, that i forgot to register a dependency that one of the classes, I had registered for dependency injection, injects in the constructor.
In your example, could it be that you inject something into MyEntities that you forgot to Register?
Install Nuget Package Unit.WebAP instead of Unity.MVC5
Make sure the correct unity package is installed using nuget
I Installed Unity.MVC5 and was facing similar exception "parameterless constructor"
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<ICar, Tesla>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}

ASP.NET MVC4 Unity - Resolve dependencies on another project

I have this configuration in my project MVC4 Unity and a generic configucion for drivers.
Bootstrapper.cs
namespace MyProyect.Web
{
public static class Bootstrapper
{
public static void Initialise()
{
var container = BuildUnityContainer();
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
container.RegisterType<MyProyect.Model.DataAccessContract.ICountryDao, MyProyect.DataAccess.CountryDao>();
container.RegisterType<MyProyect.Model.DataAccessContract.IContactDao, MyProyect.DataAccess.ContactDao>();
return container;
}
}
}
Global.asax:
protected void Application_Start()
{
...
Bootstrapper.Initialise();
...
}
GenericModelBinder.cs:
namespace MyProyect.Web.ModelBinder
{
public class GenericModelBinder : DefaultModelBinder//, IValueProvider
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var resolver = (Unity.Mvc4.UnityDependencyResolver)DependencyResolver.Current;
if (modelType == null)
{
return base.CreateModel(controllerContext, bindingContext, null);
}
return resolver.GetService(modelType);
}
}
}
Now that I need is to resolve a dependency in another project within the solution. My question is how I can do to that recognize the settings Unity in another project?. I currently I have this class but the current configuration does not bring in the MVC project.
namespace MyProyect.Model.ListData
{
public abstract class ListDataGenericResolver
{
protected T ResolverType<T>()
{
IUnityContainer container = new UnityContainer();
UnityServiceLocator locator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => locator);
//return unity.Resolve<T>();
return (T)container.Resolve(typeof(T));
}
}
}
this is a example how to use ListDataGenericResolver:
namespace MyProyect.Model.ListData.Types
{
public class CountryListData : ListDataGenericResolver, IGetListData
{
private readonly ICountryDao countryDao;
private string defaultValue;
public CountryListData(object defaultValue)
{
// Resolver
this.countryDao = this.ResolverType<ICountryDao>();
this.defaultValue = defaultValue == null ? string.Empty : defaultValue.ToString();
}
public IList<SelectData> GetData()
{
var data = this.countryDao.GetAllCountry(new Entity.Parameters.CountryGetAllParameters());
return data.Select(d => new SelectData
{
Value = d.CountryId.ToString(),
Text = d.Description,
Selected = this.defaultValue == d.CountryId.ToString()
}).ToList();
}
}
}
Thank you.
Here is how I do this.
In Application_Start, I create the unity container. I have a custom library that I use for all of my MVC projects that I import through NuGet, so I make the call to its configure method, then call the other project's Configure() methods. You could simply omit the custom library and add that code in here as well. All of that keeps my Application_Start nice and clean.
protected void Application_Start()
{
// Standard MVC setup
// <removed>
// Application configuration
var container = new UnityContainer();
new CompanyName.Mvc.UnityBootstrap().Configure(container);
new AppName.ProjectName1.UnityBootstrap().Configure(container);
new AppName.ProjectName2.UnityBootstrap().Configure(container);
// <removed>
}
This is the code for the custom MVC library's UnityBootstrap class
namespace CompanyName.Mvc
{
/// <summary>
/// Bootstraps <see cref="CompanyName.Mvc"/> into a Unity container.
/// </summary>
public class UnityBootstrap : IUnityBootstrap
{
/// <inheritdoc />
public IUnityContainer Configure(IUnityContainer container)
{
// Convenience registration for authentication
container.RegisterType<IPrincipal>(new InjectionFactory(c => HttpContext.Current.User));
// Integrate MVC with Unity
container.RegisterFilterProvider();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
}
}
Then, in the other projects, I have a UnityBootstrap there, that was called from Application_Start:
ProjectName1:
namespace AppName.ProjectName1
{
public class UnityBootstrap : IUnityBootstrap
{
public IUnityContainer Configure(IUnityContainer container)
{
return container.RegisterType<IDocumentRoutingConfiguration, DocumentRoutingConfiguration>();
}
}
}
ProjectName2: - and you can see in here, that this one depends on some other projects in another library and it is calling their Configure() methods to get them set up too...
namespace AppName.ProjectName2
{
public class UnityBootstrap : IUnityBootstrap
{
public IUnityContainer Configure(IUnityContainer container)
{
new CompanyName.Security.UnityBootstrap().Configure(container);
new CompanyName.Data.UnityBootstrap().Configure(container);
container.RegisterSecureServices<AuthorizationRulesEngine>(typeof(UnityBootstrap).Assembly);
return container
.RegisterType<IAuthorizationRulesEngine, AuthorizationRulesEngine>()
.RegisterType<IDateTimeFactory, DateTimeFactory>()
.RegisterType<IDirectoryInfoFactory, DirectoryInfoFactory>()
.RegisterType<IDirectoryWrapper, DirectoryWrapper>()
.RegisterType<IEmailService, EmailService>()
.RegisterType<IEntryPointService, EntryPointService>();
}
}
}
Here is the IUnityBootstrap interface that is used throughout the code above (for your reference)
/// <summary>
/// Defines a standard interface for bootstrapping an assembly into a Unity container.
/// </summary>
public interface IUnityBootstrap
{
/// <summary>
/// Registers all of the assembly's classes to their public interfaces and performs any other necessary configuration.
/// </summary>
/// <param name="container">The Unity container instance to configure.</param>
/// <returns>The same IUnityContainer object that this method was called on.</returns>
IUnityContainer Configure(IUnityContainer container);
}
I hope this helps you out.

Resources