Unity doesn't resolve my classes - c#

I have more projects in solution (mostly class library and one WebAPI project) and I have problem in Common project in resolving dependencies inside this project. Here is example how I setting up dependency
[Dependency]
public IDbContextFactory DbContextFactory
{
get { return _factory; }
set
{
_factory = value;
DbContext = _factory.Create();
}
}
[Dependency]
public IUnitOfWorkManager Manager
{
get { return _manager; }
set
{
_manager = value;
_manager.AddOpenUnitOfWork(this);
}
}
and in same project I have registration interfaces and classes into Unity container via this class
public class CommonUnityConfiguration : IUnityConfiguration
{
public void Configurate(UnityContainer container)
{
container
.RegisterType<IUnitOfWorkManager, UnitOfWorkManager>()
.RegisterType<IDbContextFactory, DbContextFactory>();
}
}
and finally in WebAPI I have WebApiConfiguration, where I'm creating Unity container and register all classes.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Create instance for Unity container - let's try to run!
var container = new UnityContainer();
container.RegisterType<IUserRepository, UserRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
// Add project classes to IoC container
new CommonUnityConfiguration().Configurate(container);
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Problem is, IDbContextFactory property and IUnitOfWorkManager aren't resolve. Do you have any advice, what should I check?

I think you need to switch these two lines:
config.DependencyResolver = new UnityResolver(container);
new CommonUnityConfiguration().Configurate(container);
You're setting the DependencyResolver to the UnityREsolver before you fully configure it in your CommonUnityConfiguration class

Related

Can't integrate autofac with both web api 2 and mvc

this thing takes one week from me
i have done many methods to find a solution
mvc fully integrated with autofac, but web api NO and NO! :-(
here is my codes:
AutofacDi
public static class AutofacDi
{
public static ValueTuple<IContainer, HttpConfiguration> Initialize()
{
var assembly = Assembly.GetExecutingAssembly();
var builder = new ContainerBuilder();
var config = GlobalConfiguration.Configuration;
builder.RegisterControllers(assembly);
builder.RegisterApiControllers(assembly).PropertiesAutowired();
builder.RegisterHttpRequestMessage(config);
builder.RegisterAssemblyModules(assembly);
builder.RegisterAssemblyTypes(assembly).PropertiesAutowired();
builder.RegisterFilterProvider();
builder.RegisterWebApiFilterProvider(config);
builder.RegisterModelBinders(assembly);
builder.RegisterWebApiModelBinderProvider();
builder.RegisterModelBinderProvider();
builder.RegisterModule<AutofacWebTypesModule>();
builder.RegisterSource(new ViewRegistrationSource());
builder.RegisterType<T4MVC.Dummy>().AsSelf();
builder.RegisterType<FoodDbContext>()
.As<IUnitOfWork>()
.InstancePerLifetimeScope();
builder.Register(context => (FoodDbContext)context.Resolve<IUnitOfWork>())
.As<FoodDbContext>()
.InstancePerLifetimeScope();
builder.RegisterType<ApplicationDbContext>().As<DbContext>().InstancePerLifetimeScope();
builder.RegisterType<UserStore<ApplicationUser>>().As<IUserStore<ApplicationUser>>();
builder.RegisterType<ApplicationUserManager>();
builder.RegisterType<ApplicationSignInManager>();
builder.Register(c => new IdentityFactoryOptions<ApplicationUserManager>()
{
DataProtectionProvider = new DpapiDataProtectionProvider("FoodBaMa")
});
builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).InstancePerLifetimeScope();
builder.RegisterType<RoleStore<IdentityRole>>().As<IRoleStore<IdentityRole, string>>();
builder.RegisterAssemblyTypes(typeof(MvcApplication).Assembly)
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
return new ValueTuple<IContainer, HttpConfiguration>(container, config);
}
}
OWIN Startup
[assembly: OwinStartup(typeof(FoodBaMa.Startup))]
namespace FoodBaMa
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var iOc = AutofacDi.Initialize();
app.UseAutofacMiddleware(iOc.Item1);
app.UseAutofacMvc();
app.UseWebApi(iOc.Item2);
app.UseAutofacWebApi(iOc.Item2);
WebApiConfig.Register(iOc.Item2);
app.UseCors(CorsOptions.AllowAll);
ConfigureAuth(app);
}
}
}
Global
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());
ModelBinders.Binders.Add(typeof(string), new PersianModelBinder());
MvcHandler.DisableMvcResponseHeader = true;
DbInterception.Add(new ElmahEfInterceptor());
DbInterception.Add(new YeKeInterceptor());
GlobalConfiguration.Configuration.EnsureInitialized();
}
}
ApiController
[AutofacControllerConfiguration]
[WebApiCompress]
[RoutePrefix("api/v1")]
public class AppController : ApiController
{
private readonly IApiV1Service _apiService;
public AppController(
IApiV1Service apiService
)
{
_apiService = apiService;
}
[HttpPost]
[Route("app/mainview")]
public virtual async Task<IHttpActionResult> MainView([FromBody] Request model)
{
var Result = new Models.API.V1.App.MainView.Response { Status = CheckTokenEnum.Error };
try
{
if (ModelState.IsValid)
Result = await _apiService.MainView(model).ConfigureAwait(false);
}
catch (Exception ex)
{
ErrorLog.GetDefault(null).Log(new Error(ex));
}
return Json(Result, R8.Json.Setting);
}
}
WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.JsonIntegration();
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
config.MessageHandlers.Add(new CachingHandler(new InMemoryCacheStore()));
config.MessageHandlers.Add(new PreflightRequestsHandler());
config.Filters.Add(new ElmahHandleErrorApiAttribute());
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
RouteConfig
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//routes.IgnoreRoute("{*browserlink}", new { browserlink = #".*/arterySignalR/ping" });
routes.MapMvcAttributeRoutes();
AreaRegistration.RegisterAllAreas();
//routes.LowercaseUrls = true;
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
},
namespaces: new[] { "FoodBaMa.Controllers" }
);
}
}
on each web api request, returns:
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
Module: IIS Web Core
Notification: MapRequestHandler
Handler: StaticFile
Error Code: 0x80070002
It's a killing problem for me because it's two weeks that making my website application unusable.
i don't know what to do.
help me !!!
i fixed that issue by commenting:
builder.RegisterWebApiFilterProvider(config);
and
builder.RegisterHttpRequestMessage(config);
in AutofacDi
It appears you may have gotten past your issue, which I hope is true. There's a lot to digest in here, but I do see a common mistake in the very start with respect to OWIN integration and Web API as documented in the Autofac docs:
A common error in OWIN integration is use of the GlobalConfiguration.Configuration. In OWIN you create the configuration from scratch. You should not reference GlobalConfiguration.Configuration anywhere when using the OWIN integration.
You may run into additional/other challenges in your setup as it sits; if you do, try getting rid of the use of GlobalConfiguration.Configuration.

C# WebApi DI not working

Hello i need some assistance. I'm struggling on this second day and can't find a source of the problem. I'm working on web api with token authorization , identity and ninject.
This is my kernel :
public IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<AppContext>().ToSelf().InRequestScope();
kernel.Bind(x => { x.From(typeof(UserService).Assembly).SelectAllClasses().EndingWith("Service").BindDefaultInterface(); });
kernel.Bind(typeof(IUserStore<AppIdentityUser>)).To(typeof(UserStore<AppIdentityUser>)).InRequestScope()
.WithConstructorArgument("context", kernel.Get<AppContext>());
kernel.Bind(typeof(UserManager<AppIdentityUser>)).To(typeof(UserManager<AppIdentityUser>)).InRequestScope()
.WithConstructorArgument("store", kernel.Get<IUserStore<AppIdentityUser>>());
kernel.Bind(typeof(IRoleStore<IdentityRole, string>)).To(typeof(RoleStore<IdentityRole>)).InRequestScope().WithConstructorArgument("context", kernel.Get<AppContext>());
kernel.Bind(typeof(RoleManager<IdentityRole>)).To(typeof(RoleManager<IdentityRole>)).InRequestScope().WithConstructorArgument("store", kernel.Get<IRoleStore<IdentityRole, string>>());
kernel.Bind<IOAuthAuthorizationServerProvider>().To<AuthorizationServerProvider>();
kernel.Bind<IOAuthAuthorizationServerOptions>().To<MyOAuthAuthorizationServerOptions>();
return kernel;
}
This is my api controller :
public UsersController(IUserService userService)
{
this._userService = userService;
}
public IHttpActionResult Login()
{
//get user method
}
this is my service :
public UserService(UserManager<AppIdentityUser> userMenager, RoleManager<IdentityRole> roleManager)
{
this._userMenager = userMenager;
this._roleManager = roleManager;
}
public AppIdentityUser GetUser(string name, string password)
{
return _userMenager.Find(name, password); // here I recive error on second time
}
Problem is that this works only once. When i open application and perform one get action it works on the second time when i try after few seconds i get exception that Context in user Store is disposed. I suspect that it's problem with my ninject configuration but don't see any error.
Edit: this is my Owin Startup Class
public void Configuration(IAppBuilder app)
{
config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.EnableCors();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
var kernel = ConfigureNinject(app);
ConfigureOAuth(app, kernel);
config.DependencyResolver = new NinjectResolver(kernel);
//app.UseWebApi(config);
app.UseNinjectMiddleware(() => kernel);
app.UseNinjectWebApi(config);
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AutoMapperConfiguration.Configure();
}
public void ConfigureOAuth(IAppBuilder app, IKernel kernel)
{
app.UseOAuthBearerTokens(kernel.Get<IOAuthAuthorizationServerOptions>().GetOptions());
}

Exception when I try to combine Autofac with AutoMapper`s IMappingEngine

Thats my DI and Automapper setup:
[RoutePrefix("api/productdetails")]
public class ProductController : ApiController
{
private readonly IProductRepository _repository;
private readonly IMappingEngine _mappingEngine;
public ProductController(IProductRepository repository, IMappingEngine mappingEngine)
{
_repository = repository;
_mappingEngine = mappingEngine;
}
}
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
//WebApiConfig.Register(GlobalConfiguration.Configuration);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });
// Filter
config.Filters.Add(new ActionExceptionFilter());
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
// DI
// Register services
var builder = new ContainerBuilder();
builder.RegisterType<ProductRepository>().As<IProductRepository>().InstancePerRequest();
builder.RegisterType<MappingEngine>().As<IMappingEngine>();
// AutoMapper
RegisterAutoMapper(builder);
// FluentValidation
// do that finally!
// This is need that AutoFac works with controller type injection
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
private static void RegisterAutoMapper(ContainerBuilder builder)
{
var profiles =
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(GetLoadableTypes)
.Where(t => t != typeof (Profile) && typeof (Profile).IsAssignableFrom(t));
foreach (var profile in profiles)
{
Mapper.Configuration.AddProfile((Profile) Activator.CreateInstance(profile));
}
}
private static IEnumerable<Type> GetLoadableTypes(Assembly assembly)
{
try
{
return assembly.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
return e.Types.Where(t => t != null);
}
}
}
Thats the exception I get when I go to a certain route:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'AutoMapper.MappingEngine' can be invoked with the available services and parameters:
Cannot resolve parameter 'AutoMapper.IConfigurationProvider configurationProvider' of constructor 'Void .ctor(AutoMapper.IConfigurationProvider)'.
Cannot resolve parameter 'AutoMapper.IConfigurationProvider configurationProvider' of constructor 'Void .ctor(AutoMapper.IConfigurationProvider, AutoMapper.Internal.IDictionary`2[AutoMapper.Impl.TypePair,AutoMapper.IObjectMapper], System.Func`2[System.Type,System.Object])'.
QUESTION
What is wrong with my code?
The error come from this line :
builder.RegisterType<MappingEngine>().As<IMappingEngine>();
This line tell Autofac to instanciate a MappingEngine when you need a IMappingEngine. If you look at the available constructor of MappingEngine you will see that Autofac can't use any of them because it can't inject required parameters.
Here are the available constructor of MappingEngine
public MappingEngine(IConfigurationProvider configurationProvider)
public MappingEngine(IConfigurationProvider configurationProvider,
IDictionary<TypePair, IObjectMapper> objectMapperCache,
Func<Type, object> serviceCtor)
One of the solution to fix this issue is to tell Autofac how to create your MappingEngine you can do it by using a delegate registration.
builder.Register(c => new MappingEngine(...)).As<IMappingEngine>();
You can also register a IConfigurationProvider by doing so, Autofac will be able to automatically find the good constructor.
The easiest way to fix this issue is to register a IConfigurationProvider in Autofac
builder.Register(c => new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers))
.As<IConfigurationProvider>()
.SingleInstance();
builder.RegisterType<MappingEngine>()
.As<IMappingEngine>();
You can also find further information here : AutoMapper, Autofac, Web API, and Per-Request Dependency Lifetime Scopes

Web API: Odata route always returning a 404 response

I am new to OData. I have built an ASP.NET Web API controller as shown below:
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Web.OData.Routing;
namespace HelloWebApi.Controllers
{
public class TestsController : ODataController
{
ProductsContext db = new ProductsContext();
private bool TestExists(int key)
{
return db.tests.Any(p => p.key== key);
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
[EnableQuery]
public IQueryable<test> Get()
{
return db.tests;
}
}
}
The model is as shown below:
public class Test
{
[Key]
public int key { get; set; }
public string aaa { get; set; }
}
I have also configured the RouteConfig, ODdataConfig, and WebApiConfig as shown below:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.Ignore("{resource}.axd/{*pathInfo}");
routes.MapHttpRoute(
name: "Default",
routeTemplate: "{controller}/{action}/{id}"
);
}
}
public class ODataConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Test>("Tests");
config.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
}
}
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
As well as the global.asax file:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(config =>
{
ODataConfig.Register(config); //this has to be before WebApi
WebApiConfig.Register(config);
});
//FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
I tried making a number of modifications in order to resolve this. But I am consistently getting an HTTP 404 Not Found response. I also tried explicitly adding an [ODataRoute] attribute to the action method name; when doing that I instead get an HTTP 406 Not Acceptable response.
The URL I am trying to configure is:
http://localhost:6701/odata/tests/
Where odata is the suffix and tests is the controller name. Please point out what I am doing wrong.
The routes configured by the ODataConventionModelBuilder are case-sensitive. In your code, you have defined:
builder.EntitySet<Test>("Tests");
Based on this, the endpoint will be:
http://localhost:6701/odata/Tests/
Note the upper-case T in Tests.
This is by design, in order to maintain compatibility with the OData specification.
That said, as of Web API OData 5.4, you can optionally enable case-insensitive routes using the HttpConfiguration class's EnableCaseInsensitive() method. E.g., in your ODataConfig.Register() method you could add:
config.EnableCaseInsensitive(caseInsensitive: true);
For more information, see Basic Case Insensitive Support under Microsoft's ASP.NET Web API for OData V4 Docs.

Using Autofac with Web Api 2 and Owin

Im new to DI libraries and trying to use Autofac in a WebApi 2 project with Owin. This is my Owin Startup class,
[assembly: OwinStartup(typeof(FMIS.SIGMA.WebApi.Startup))]
namespace FMIS.SIGMA.WebApi
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
var config = new HttpConfiguration();
WebApiConfig.Register(config);
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseWebApi(config);
ConfigureOAuth(app);
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
}
When I call a Api method I get this error
An error occurred when trying to create a controller of type
'MyController'. Make sure that the controller has a
parameterless public constructor.
What am I missing here?
MyController code is something like this
public class MyController : ApiController
{
ISomeCommandHandler someCommanHandler;
public MyController(ISomeCommandHandler SomeCommandHandler)
{
this.someCommanHandler = SomeCommandHandler;
}
// POST: api/My
public void Post([FromBody]string value)
{
someCommanHandler.Execute(new MyCommand() {
Name = "some value"
});
}
// GET: api/My
public IEnumerable<string> Get()
{
}
// GET: api/My/5
public string Get(int id)
{
}
}
You have set DependencyResolver to AutofacWebApiDependencyResolver, so Autofac comes into play and instantiates dependencies for you. Now you have to explicitly tell Autofac which concrete implementations should be used when an instance of interface is required.
Your controller requires an instance of ISomeCommandHandler:
MyController(ISomeCommandHandler SomeCommandHandler)
So you need to configure types that expose that interface:
builder.RegisterType<CommandHandler>.As<ISomeCommandHandler>();
Have a look at this documentation section for more examples about Autofac registration concepts.

Categories

Resources