I am evaluating ABP 3.9 currently and tenant creation is not working.
It's failing while executing this code:
CheckErrors(await _roleManager.CreateStaticRoles(tenant.Id));
This is the exception that I am getting:
Mvc.ExceptionHandling.AbpExceptionFilter - Format of the initialization string does not conform to specification starting at index 0.
System.ArgumentException: Format of the initialization string does not conform to specification starting at index 0.
at System.Data.Common.DbConnectionOptions.GetKeyValuePair(String connectionString, Int32 currentPosition, StringBuilder buffer, Boolean useOdbcRules, String& keyname, String& keyvalue)
at System.Data.Common.DbConnectionOptions.ParseInternal(Dictionary`2 parsetable, String connectionString, Boolean buildChain, Dictionary`2 synonyms, Boolean firstKey)
at System.Data.Common.DbConnectionOptions..ctor(String connectionString, Dictionary`2 synonyms)
at System.Data.SqlClient.SqlConnectionString..ctor(String connectionString)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnectionOptions(String connectionString, DbConnectionOptions previous)
at System.Data.ProviderBase.DbConnectionFactory.GetConnectionPoolGroup(DbConnectionPoolKey key, DbConnectionPoolGroupOptions poolOptions, DbConnectionOptions& userConnectionOptions)
at System.Data.SqlClient.SqlConnection.ConnectionString_Set(DbConnectionPoolKey key)
at System.Data.SqlClient.SqlConnection.set_ConnectionString(String value)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.CreateDbConnection()
The same Entity Framework connection works with other ApplicationService
classes that I have added. Don't know why only for tenant creation this fails. I am extending the sample template, which is available freely on ASP.NET Boilerplate site.
Thanks a lot for the help. Regards, Zainu
I didn't realize till the code was deployed in Azure that it would end up with exception "System.ApplicationException: Could not find content root folder".
Lucky for me that there was a discussion on the same here https://github.com/aspnetboilerplate/aspnetboilerplate-templates/issues/43 and the fix was the same
var startupPath = System.IO.Directory.GetCurrentDirectory(); var configuration = AppConfigurations.Get(startupPath); tenant.ConnectionString = SimpleStringCipher.Instance.Encrypt(configuration.GetConnectionString(OneCloudConsts.ConnectionStringName));
In TenantAppService class under Create method commented out the code which created encrypted connection string from input DTO. Added a way to read connection string from configuration and this worked in my case since I have a single database for all tenants.This database would be very small and it would store only metadata about Tenants while majority of Application data would be in Azure storage.
public override async Task<TenantDto> Create(CreateTenantDto input)
{
CheckCreatePermission();
// Create tenant
var tenant = ObjectMapper.Map<Tenant>(input);
//this code is commented since we have single database for all tenants
//tenant.ConnectionString = input.ConnectionString.IsNullOrEmpty()
// ? null
// : SimpleStringCipher.Instance.Encrypt(input.ConnectionString);
//This would read connection string from configuration and pass it to
//connectionstring property of AbpTenant
var configuration =
AppConfigurations.Get(WebContentDirectoryFinder.CalculateContentRootFolder());
tenant.ConnectionString = SimpleStringCipher.Instance.Encrypt(configuration.GetConnectionString(OneCloudConsts.ConnectionStringName));