Autofac service not registered but it is - autofac

Lately I have some issues with Autofac.
I have an aggregate service like this:
public interface ICommonServices
{
IQueryBus QueryBus { get; }
ICommandBus CommandBus { get; }
INotificationBus NotificationBus { get; }
ILoggerFactory LoggerFactory { get; }
}
And I am registering it like this:
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAggregateService<ICommonServices>();
}
}
And when I do:
var services = container.Resolve<ICommonServices>();
I am getting this error:
"The requested service 'Infrastructure.ICommonServices' has not been registered.
To avoid this exception, either register a component to provide the service, check for service
registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency."
I have many assemblies and I use Autofac modules. If I put a breakpoint in the module I see that it is called and registered. Also if I inspect Container registrations, I see that there is a registration for ICommonServices:
Activator = Object (DelegateActivator), Services = [Infrastructure.ICommonServices],
Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = OwnedByLifetimeScope,
Pipeline = Autofac.Core.Pipeline.ResolvePipeline
If I move the registration out from AutofacModule to the main assembly, jst before the builder.Build() then all works and Autofac is abble to resolve it.
Why then the error if the service is registered? And this is not the only one.

The issue was Assembly scanning in .net core 3.1.
The old - non working way:
var assemblies= Assembly.GetExecutingAssembly()
.GetAllAssemblies()
.ToArray();
the new - WORKING one:
var l2Assemblies = Assembly.GetExecutingAssembly()
.GetAllAssembliesWithContext()
.ToArray();

Related

System.TypeInitializationException occurs

I've started to learn Entity Framework recently and I'm new. I wrote the first simple program, but it doesn't work. I tried to find solution on Google, but without result. I hope to find answer here.
ApplicationContext.cs
using Microsoft.EntityFrameworkCore;
namespace HelloApp
{
class ApplicationContext: DbContext
{
public DbSet<User> Users { get; set; }
public ApplicationContext()
{
Database.EnsureCreated();
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=helloappdb;Trusted_Connection=True;");
}
}
}
Program.cs
using System;
using System.Linq;
namespace HelloApp
{
class Program
{
static void Main(string[] args)
{
using (ApplicationContext db = new ApplicationContext())
{
User user1 = new User { Name = "Tom", Age = 33 };
User user2 = new User { Name = "Alice", Age = 26 };
db.Users.Add(user1);
db.Users.Add(user2);
db.SaveChanges();
Console.WriteLine("Successfully saved!");
var users = db.Users.ToList();
Console.WriteLine("List of objects:");
foreach (User u in users)
{
Console.WriteLine($"{u.Id}.{u.Name} - {u.Age}");
}
}
}
}
}
Thanks for your help!!!
[Update] I realised that System.TypeInitializationException clarifies me, what problem happened:
The type initializer for 'Microsoft.Data.SqlClient.SNINativeMethodWrapper' threw an exception. ---> System.ComponentModel.Win32Exception: Failed to load C:\Users\Босс\Desktop\x86\SNI.dll
I was looking for on Google, but could find only one posibble explanation:
"That makes me suspect that you build it on a 64 bit system and then just transferred the files to the other machine. You need to publish the project for an x86 target to get the right native dependency resolved. Give it a try."
I have 64-bit Windows 10 on 64-bit CPU and i can't understand how to publish my project in another bit rate?
Okay, it can sound ridiculous, but all what i need was updating of NuGet package Microsoft.Data.SqlClient

Can we use ASP.NET Boilerplate with Dapper instead of Entity Framework Core?

I'm new to ASP.NET Boilerplate and Dapper. From the tutorial I got to know that ASP.NET Boilerplate works with Entity Framework Core. Can we use another Data Access Layer instead of EF Core? Is ASP.NET Boilerplate compatible with Dapper?
Sure! you can use Dapper.
Installation
Before you start, you need to install https://www.nuget.org/packages/Abp.Dapper, either EF Core, EF 6.x or the NHibernate ORM NuGet packages into the project you want to use.
Module Registration
First, you need to add the DependsOn attribute for the AbpDapperModule on your application module where you register it
[DependsOn(
typeof(AbpEntityFrameworkCoreModule),
typeof(AbpDapperModule)
)]
public class MyApplicationModule: AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(MyApplicationModule).GetAssembly());
}
}
Entity to Table Mapping
You can configure mappings. For example, the Person class maps to the Person table in the following example:
public class PersonMapper: ClassMapper<Person>
{
public PersonMapper()
{
Table("Persons");
Map(x => x.Roles).Ignore();
AutoMap();
}
}
Sample Application Module:
[DependsOn(
typeof(AbpEntityFrameworkModule),
typeof(AbpDapperModule)
)]
public class SampleApplicationModule: AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(SampleApplicationModule).GetAssembly());
DapperExtensions.SetMappingAssemblies(new List<Assembly> { typeof(SampleApplicationModule).GetAssembly() });
}
}
Usage
After registering AbpDapperModule, you can use the Generic IDapperRepository interface (instead of standard IRepository) to inject dapper repositories.
public class SomeApplicationService : ITransientDependency
{
private readonly IDapperRepository<Person> _personDapperRepository;
private readonly IRepository<Person> _personRepository;
public SomeApplicationService(
IRepository<Person> personRepository,
IDapperRepository<Person> personDapperRepository)
{
_personRepository = personRepository;
_personDapperRepository = personDapperRepository;
}
public void DoSomeStuff()
{
var people = _personDapperRepository.Query("select * from Persons");
}
}
Check out these links:
https://aspnetboilerplate.com/Pages/Documents/Dapper-Integration
https://github.com/aspnetboilerplate/aspnetboilerplate/pull/1854#issuecomment-284511423
https://github.com/aspnetboilerplate/aspnetboilerplate/pull/1854#issuecomment-284639277
Trying to set up a Dapper-based Data Access Layer. ABP.Dapper documentation is confusing and incomplete

How can I use IWantToRunBeforeConfigurationIsFinalized , inject propertys into the handlers *and* continue using the Nservicebus test framework?

Nervicebus 4.6 Unit Testing issue
I recently discovered IWantToRunBeforeConfigurationIsFinalized to inject propertys into a handler, changed all my service code and now suddenly all my NserviceBus.Test fails.
public void run {
Configure.Instance.Configurer.ConfigureProperty<MyMessage_Handler>(h => h.MyProperty, "somevalue");
}
When i atttempt a unit test
var message = new MyMessage
{
...
...
};
Test.Handler<MyMessage_Handler>().WithExternalDependencies(m =>
{
m.PropertyA = aValue;
m.PropertyB = bValue;
})
.ExpectPublish<MyEvent>(m =>
{
Assert.That(...);
return true;
})
.OnMessage<MyMessage>(message);
I receive the following exception
TestFixture failed: SetUp : System.InvalidOperationException : Cannot
configure properties for a type that hasn't been configured yet:
at
NServiceBus.ObjectBuilder.Autofac.AutofacObjectBuilder.ConfigureProperty(Type
component, String property, Object value) in
y:\BuildAgent\work\31f8c64a6e8a2d7c\src\NServiceBus.Core\ObjectBuilder\Autofac\AutofacObjectBuilder.cs:line
114
However if i configure the bus like this, calling configurecomponent on the handler. The test framework works
This was my original method, it works fine but i prefer the approach of IWantToRunBeforeConfigurationIsFinalized to cleanly seperate the logic.
Configure.With()
.DefaultBuilder()
.PurgeOnStartup(false)
.RunCustomAction(() => Configure.Instance.Configurer.ConfigureComponent<MyMessage_Handler>(DependencyLifecycle.InstancePerUnitOfWork))
.RunCustomAction(() => {
Configure.Instance.Configurer.ConfigureProperty<MyMessage_Handler>(h => h.MyProperty, "myValue");
}
...
How can I use IWantToRunBeforeConfigurationIsFinalized , inject propertys into the handlers and continue using the Nservicebus test framework?
It seems odd to try to configure properties directly on handlers. If it's only needed by one handler, then it should be dealt with in that handler, perhaps in a static constructor in that handler class.
At any rate, you're putting yourself at the mercy of when types are loaded up and registered into the container, which isn't necessarily deterministic across different versions of NServiceBus, and clearly not when dealing with the testing framework.
Instead, what if you created a new class:
public class ReferenceValues
{
public string MyProperty { get; set; }
}
Then, you could register this type normally, from any point in the endpoint startup. Preferably, as an INeedInitialization since most of the extensibility points go away in NServiceBus 5.x and INeedInitialization is really the only game in town.
// V4 code
public class SetupReferenceValues : INeedInitialization
{
public void Init()
{
Configure.Component<ReferenceValues>(DependencyLifecycle.SingleInstance)
.ConfigureProperty(rv => rv.MyProperty, "myValue");
}
}
Then, in your handler:
public class MyHandler : IHandleMessages<MyMessage>
{
public ReferenceValues Values { get; set; }
public void Handle(MyMessage message)
{
Console.WriteLine(Values.MyProperty);
}
}
I believe this should work from the testing framework as well.

ASP.net Identity, IoC and sharing DbContext

Have anyone been successful in attaching an IoC with OWIN ASP.NET Identity to share the same DbContext as the WebApi (or MVC) application?
I would like that if ASP.Net identity loads the user, it loads in the same dbcontext as used in the rest of the application.
(using AutoFac as IoC - but wouldn't mind an example with other container)
Edit:
06/Jan/2014: Just to be a bit more specific, when the ASP.Net identity attempts to use a DbContext it needs to be the same DbContext instance as the rest of the application. Otherwise it will create two instances of the same DbContext. I am already using the .PerHttpApiRequest() extension.
The problem I found is that when setting up OWIN classes I couldn't find a way to:
1) attach the container to the OWIN pipeline;
2) tell OWIN to resolve the classes it needs using that container so it can share the same scope (i.e. OAUthServerOptions or any other that may contain other dependencies)
Having said that, how can you setup the ASP.Net Identity resolving the two points above?
EDIT: added instantiating the OWIN pipeline as per comment.
As the IdentityDbContext used by ASP.NET Identity inherits from DbContext, you can simply create your own implementation inheriting from IdentityDbContext like so
public class ApplicationContext : IdentityDbContext<ApplicationUser>
{
//additional DbSets
public DbSet<OtherEntity> OtherEntities { get; set; }
}
public class ApplicationUser : IdentityUser
{
//any custom properties you want for your user.
}
public class OtherEntity
{
[Key]
public int Id { get; set; }
}
now as far as using IoC, from a unity perspective, I register an instance of the UserStore like so
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new InjectionConstructor(typeof(ApplicationContext)));
}
then create a wrapper around the user manager
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store) : base(store)
{
}
}
and inject that wherever I need a user manager.
As for the OWIN pipeline, you need to instantiate the OAuthAuthorizationProvider through your container, like so.
container.RegisterType<IOAuthAuthorizationServerProvider, ApplicationOAuthProvider>(new InjectionConstructor("self", typeof(ApplicationUserManager)));
then for example in WebApi, you need to simply get the instance from the container in startup.
static Startup()
{
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = (IOAuthAuthorizationServerProvider)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IOAuthAuthorizationServerProvider)),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(5),
AllowInsecureHttp = true,
RefreshTokenProvider = new SimpleRefreshTokenProvider()
};
}

Using Autofac for WebForms and n-tier architecture

I am introducing unit testing to an existing webforms application. I am using Moq and Autofac. I'm trying to keep code changes to a minimum, but need to implement the unit testing.
So I have a presentation assembly, a business layer, and a data access layer. My business layer looks something like this:
public class EmployeeBL
{
public Employee SelectById(int id)
{
return new EmployeeDA().SelectById(id);
}
}
My Data access looks something like this:
public class EmployeeDA
{
// unitOfWork defined in the constructor
public Employee SelectById(int id)
{
return unitOfWork.Employees.Where(e => e.id == id);
}
}
Autofac's webforms assembly allows you to declare a public property and specify web.config settings to automatically inject a dependency via HttpModule. To test the EmployeeBL, I made the changes to web.config and declared EmployeeDA as a property:
// Modified for testing
[InjectProperties]
public class EmployeeBL
{
// public property to allow Autofac property injection
public IEmployeeDA EmployeeDA { get; set; }
public Employee SelectById(int id)
{
return EmployeeDA.SelectById(id);
}
}
This works for running the webforms application, but the problem is I need to unit test the business layer independently of a webforms instance. I would like to keep the [InjectProperties] attribute on my EmployeeBL, but I can't tell by the documentation how I can get the EmployeeDA to have its properties injected.
public class EmployeeBLTest
{
private static IContainer { get; set; }
[TestInitialize]
public void Initialize()
{
var builder = new ContainerBuilder();
// Use my fake employeeDA for testing
builder.RegisterType<FakeEmployeeDA>().As<IEmployeeDA>();
// Something magical happens
}
[TestMethod]
public void SelectByIdTest(int id) { /* testing stuff */ }
}
What about:
builder.RegisterType<EmployeeDA>().AsSelf().PropertiesAutowired();
see here:
http://code.google.com/p/autofac/wiki/PropertyInjection