So, I fixed the mapper initializing issue using IObjectMapper. However, the mappings are not being invoked, because it is returning null after the objectMapper.Map<>().
This is what I have in PreInitialize of webApiModule: //Adding custom AutoMapper mappings Configuration.Modules.AbpAutoMapper().Configurators.Add(mapper => { TrackerMapper.CreateMappings(mapper); });
Is it because I'm configuring mappings in WebApiModule?
So, I took your suggestion to inject IObjectMapper to invoke the map as below: var transformedObject = _objectMapper.Map<Destination>(source);
It failed with the following error:
Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance.
And I have removed all references to static Mapper.Map and replaced them with IObjectMapper reference.
Where can I override this to enable static mapper for my test module?
Does IObjectMapper support mapping of an object of one type to an object of an entirely different type? Why is it that the mappings from WebApiModule not initialized from TestModule class when I use DependsOn attribute?
<cite>aaron: </cite> ABP (and ASP.NET Zero) uses SweetAlert v2, not SweetAlert2 that has the showCloseButton option.
Thank you Aaron for the quick response. Hmm.. then it would be tough. is there a way to add the close button to the modal?
This is the mapper class I have.
using Abp.AutoMapper; using Abp.Modules; using AutoMapper; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;
namespace WebApi.TrackerService {
public static class TrackerMapper
{
private static volatile bool _mappedBefore;
private static readonly object SyncObj = new object();
public static void CreateMappings(IMapperConfigurationExpression mapper)
{
lock (SyncObj)
{
if (_mappedBefore)
{
return;
}
CreateMappingsInternal(mapper);
_mappedBefore = true;
}
}
private static void CreateMappingsInternal(IMapperConfigurationExpression mapper)
{
mapper.CreateMap<Source, Destination>().ConvertUsing<TrackerTypeConverter>();
}
}
#region Mapping source to destination
public class TrackerTypeConverter : ITypeConverter<Source, Destination>
{
public Destination Convert(Source source, Destination destination, ResolutionContext context)
{
return
new Destination
{
//Transforming/mapping source to Destination
};
}
}
#endregion
}
I'm initializing CreateMappings from WebApiModule Initialize method as below: //Adding custom AutoMapper mappings Configuration.Modules.AbpAutoMapper().Configurators.Add(mapper => { TrackerMapper.CreateMappings(mapper); });
Invoking/using the mappings as below: var transformedRequest = Mapper.Map<Source, Destination>(request);
This works fine as a webApi project. But when I write my test cases, the mappings from my mapper class are not getting initialized.
In my test project, I added the attribute DependsOn[TypeOf(WebApiModule)] in TestModule class, but it doesn't seem to initialize the mappings from WebApiModule.
Thank you for your response in advance :) I greatly appreciate it.
Thank you so much ismcagdas. That resolves my confusions and gives me better idea.
I think it's better to save tenant users in tenant databases. I'm thinking of a workaround: first use AbpUserAccounts table (via IRepository<UserAccount, long> userAccountRepository) to determine which tenant the user belongs to and then go to to tenant database to perform login, which includes authentication, logging, etc.
Do you see any downside of doing this?
Thank you,
Hi ismcagdas,
I overwrote the SignInManager class and successfully passed _signInManager.SignInOrTwoFactor(loginResult, loginModel.RememberMe);. Thank you very much for the clue.
But after I returned from Login method (return Json(new AjaxResponse { TargetUrl = returnUrl })), the application went through Tenant.cs and passed the connection string of tenant database into the constructor of host database again:
public HostDbContext(string nameOrConnectionString)
: base(nameOrConnectionString) _<-- error happened when tenantDb's connectionstring got passed in._
{
}
How could I prevent using tenantDb's connectionstring in HostDbContext? Or how could I make sure I'm passing tenant connectionstring to tenant constructor?
Thank you @ismcagdas. Seems couple methods in SettingManager need to be overwritten as well..
Thank you very much Aaron.
After I disable the data filter, I'm able to get the user.
But I'm not sure why when I run the _signInManager.SignInOrTwoFactor with disablefilter
var loginResult= new AbpLoginResult<Tenant, User>(tenant, user, createIdentity);
signInResult = await _signInManager.SignInOrTwoFactor(loginResult, loginModel.RememberMe);
, it still throws me error at hostDb constructor:
public HostDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
Error Message: System.Data.SqlClient.SqlException: 'There is already an object named 'AbpAuditLogs' in the database.'
The pass-in nameOrConnectionString is the connectionstring of tenant database (saved in abpTenants table on Host Database), which is supposed to be the connectionstring of host database. Tenant database doesn't contain any abp table. Seems the application is trying to create entities again because it doesn't find tables in the tenant database.
How could I disable datafilter and user hostDb for _signInManager?
Thank you,