Base solution for your next web application
Starts in:
01 DAYS
01 HRS
01 MIN
01 SEC

Activities of "carelearning"

Hello,

We are trying to get the tenant.Id in the Seed(AbpZeroTemplateTenantDbContext context) method. We are currently doing it as below:

protected override void Seed(AbpZeroTemplateTenantDbContext context)
{
//Data Source=(localdb)\projectsv13; Initial Catalog=abp_tenant_name;
var tenancyName = new SqlConnectionStringBuilder(context.Database.Connection.ConnectionString)
.InitialCatalog.TrimStart(CustomConsts.DatabasePrefix.ToCharArray());

// prefix: abp_ so tenant name is tenant_name
var hostContext = new AbpZeroTemplateDbContext();
var tenant = hostContext.Tenants.SingleOrDefault(t => t.TenancyName == tenancyName);

        var tenantId = 0;
        if (tenant != null)
            tenantId = tenant.Id;

        var initialTenantDbBuilder = new InitialTenantDbBuilder(context);
        initialTenantDbBuilder.Create(tenantId);

        context.SaveChanges();
    }

Is there a better or more simple way to do this?

Thank you for your time and effort.

Question

Hello,

Using a multi-tenant system, we are trying to create a new area for just the host. We tried to duplicate the _Layout.cshtml file and it throws an error on '@ApplicationPath' saying it does not exist in the current context. Is there some documentation or tutorial on how to create a new area?

Hello,

When we try to create a database like this:

[UnitOfWork(false)]
        public bool Create()
        {
            DatabaseUpgradeResult result;
            try
            {
                EnsureDatabase.For.SqlDatabase(ConnectionString);//fails here with error below

                var upgrader =
                    DeployChanges.To
                        .SqlDatabase(ConnectionString)
                        .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly())
                        .LogToConsole()
                        .Build();

                result = upgrader.PerformUpgrade();
            }
            catch (Exception exception)
            {
                throw;
            }
            return result.Successful;
        }

This throws the error: CREATE DATABASE statement not allowed within multi-statement transaction.

We see the post here [http://forum.aspnetboilerplate.com/viewtopic.php?f=5&t=4103&p=9404]) and the article here [http://www.aspnetboilerplate.com/Pages/Documents/Unit-Of-Work#DocUowNoTransaction]). We tried to follow these instructions by converting our our class library to a console application and setting Program.cs as the startup class:

namespace MyCompanyName.AbpZeroTemplate.LegacyDatabaseService
{
    using Abp;

    public class Program
    {
        public static void Main(string[] args)
        {
            using (var bootstrapper = AbpBootstrapper.Create<AbpZeroTemplateLegacyDatabaseServiceModule>())
            {
                bootstrapper.Initialize();
            }
        }

    }
}

We then created AbpZeroTemplateLegacyDatabaseServiceModule.cs as a module to set the initializer to null like the migrator project :

namespace MyCompanyName.AbpZeroTemplate.LegacyDatabaseService
{
    using System.Data.Entity;
    using Abp.Modules;
    using System.Reflection;
    using EntityFramework;
    
    [DependsOn(typeof(AbpZeroTemplateDataModule))]
    public class AbpZeroTemplateLegacyDatabaseServiceModule: AbpModule
    {
        public override void PreInitialize()
        {
            Database.SetInitializer<AbpZeroTemplateTenantDbContext>(null);
        }

        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
        }
    }
}

We also tried to turn off transactions by using: [UnitOfWork(isTransactional: false)] but the error still occurs.

Is this the correct way to turn off transactions?

Or is there another possible solution for this error?

Thank you

Question

Hello,

We are trying to migrate a database using this code:

namespace MyCompanyName.AbpZeroTemplate.Web.Controllers.Api
{
    using System;
    using System.Web.Http;
    using Abp.Domain.Repositories;
    using Abp.MultiTenancy;
    using AbpZeroTemplate.MultiTenancy;

    public class MigrationController : ApiController
    {
        private readonly IAbpZeroDbMigrator _abpZeroDbMigrator;
        private readonly IRepository<Tenant> _tenantRepository;

        public MigrationController(IAbpZeroDbMigrator abpZeroDbMigrator,
                                   IRepository<Tenant> tenantRepository)
        {
            _abpZeroDbMigrator = abpZeroDbMigrator;
            _tenantRepository = tenantRepository;
        }

        [HttpPost]
        public IHttpActionResult Schema(int id)
        {
            var tenant = _tenantRepository.Get(id);
            if (tenant == null)
                return NotFound();

            try
            {
                _abpZeroDbMigrator.CreateOrMigrateForTenant(tenant);
            }
            catch (Exception exception)
            {
                return InternalServerError(exception);
            }

            return Ok(tenant.TenancyName);
        }
    }
}

The error we get is:

An error has occurred.","exceptionMessage":"Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration.","exceptionType":"System.Data.Entity.Migrations.Infrastructure.AutomaticMigrationsDisabledException","stackTrace":" at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)\r\n at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)\r\n at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)\r\n at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)\r\n at System.Data.Entity.MigrateDatabaseToLatestVersion`2.InitializeDatabase(TContext context)\r\n at Abp.Zero.EntityFramework.AbpZeroDbMigrator`2.CreateOrMigrate(AbpTenantBase tenant) in D:\\Halil\\GitHub\\module-zero\\src\\Abp.Zero.EntityFramework\\Zero\\EntityFramework\\AbpZeroDbMigrator.cs:line 72\r\n at MyCompanyName.AbpZeroTemplate.Web.Controllers.Api.MigrationController.Schema(Int32 id) in C:\\projects\\port\\src\\MyCompanyName.AbpZeroTemplate.Web\\Controllers\\Api\\MigrationController.cs:line 30

When we open the database, it appears to have added some tables, but not the correct tables.

If we open the project and run "add-migration" then we get a message that no migrations are found.

If we open the project and run "update-database -verbose -projectname MyCompanyName.AbpZeroTemplate.EntityFramework -configuration MyCompanyName.AbpZeroTemplate.AbpZeroTemplateTenant.Configuration" then it works.

We pulled down the latest abp as of the morning of 11/29.

Since this will work in the package manager console but not in the code, maybe our code is not correct. Is there some method we should use to specify which dbcontext or something like that? We can't figure out what is causing this error. Any insight or thoughts would be appreciated.

Thank you for your time.

When we try to resolve ILocalizationManager in a test it fails. If we change our test class to inherit from AbpIntegratedTestBase then it runs, but the tests take many, many times longer to run. What is the best way to resolve ILocalizationManager in the test project without incurring the time penalty of the AppTestBase class?

We are using moq to work around the issue we had here 8888. The code we are trying to write looks like:

public class MigrationAppService_Tests
{
    private readonly ILocalizationManager _localizationManager;
    private readonly Mock<IRepository<Tenant>> _mockReposistory;        
    
    public MigrationAppService_Tests()
    {
        _mockReposistory = new Mock<IRepository<Tenant>>();
        _mockReposistory.Setup(x => x.GetAsync(1))
                        .Returns(Task.FromResult((Tenant)new TenantBuilder()));

        _localizationManager = IocManager.Instance.Resolve<ILocalizationManager>();
    }

    [Fact]
    public async Task IfTenantIdParameterIsMissingSaveZipAsyncReturnsExpectedErrorMessage()
    {
        var expected = "Tenant id was not found.";

        MigrationAppService sut = new MigrationAppServiceBuilder()
                                        .WithLocalizationManager(_localizationManager)
                                        .WithTenantRepository(_mockReposistory.Object);

        var result = await sut.SaveZipAsync(-1, null);
        result.ErrorMessage.ShouldBe(expected);
    }
}

When run, we get this error:

Castle.MicroKernel.ComponentNotFoundException
No component for supporting the service Abp.Localization.ILocalizationManager was found
   at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy)
   at Castle.Windsor.WindsorContainer.Resolve[T]()
   at MyCompanyName.AbpZeroTemplate.Tests.Migration.MigrationAppService_Tests..ctor() in C:\projects\port\src\Tests\MyCompanyName.AbpZeroTemplate.Tests\Migration\MigrationAppService_Tests.cs:line 36

When we try to mock around this issue with something like this:

[Fact]
       public async Task IfTenantIdParameterIsMissingSaveZipAsyncReturnsExpectedErrorMessage()
       {
           const string Expected = "Tenant id was not found.";

           var mockLocalizationSource = new Mock<ILocalizationSource>();
           mockLocalizationSource.Setup(x => x.GetString(It.IsAny<string>()))
                                  .Returns(Expected);

           _mockLocalizationManager.Setup(x => x.GetSource(It.IsAny<string>()))
                       .Returns(mockLocalizationSource.Object);

           MigrationAppService sut = new MigrationAppServiceBuilder()
                                           .WithLocalizationManager(_mockLocalizationManager.Object)
                                           .WithTenantRepository(_mockReposistory.Object);

           var result = await sut.SaveZipAsync(-1, null);
           _mockLocalizationManager.Verify(x => x.GetSource("Custom"), Times.Once);
           mockLocalizationSource.Verify(x => x.GetString(MigrationError.TenantIdMissing.ToString()), Times.Once());

           result.ErrorMessage.ShouldBe(Expected);
       }

Then it seems like we are not writing good tests--we are just testing the mocks.

Thank you.

Hello,

I am trying to write unit tests in a situation where we have multiple tenants and each tenant has its own database. Not matter what is tried, this error keeps getting thrown: Castle.MicroKernel.ComponentActivator.ComponentActivatorException ComponentActivator: could not instantiate We start the test like this:

namespace MyCompanyName.AbpZeroTemplate.Tests.Migration
{
    using AbpZeroTemplate.Migration;
    using System;
    using System.IO;
    using System.Threading.Tasks;
    using Xunit;

    public class MigrationAppService_Tests : AppTestBase
    {
        private readonly IMigrationAppService _migrationAppService;

        public MigrationAppService_Tests()
        {
            LoginAsHostAdmin();
            
            _migrationAppService = Resolve<IMigrationAppService>();
        }

        [Fact]
        public async Task IfTenantIsMissingSaveZipAsyncThrowsException()
        {
            await _migrationAppService.SaveZipAsync(1, new MemoryStream(), String.Empty);
        }
    }
}

The "stystem under test" is a service here:

namespace MyCompanyName.AbpZeroTemplate.Migration
{
    using Abp.Domain.Repositories;
    using MultiTenancy;
    using System;
    using System.IO;
    using System.Threading.Tasks;

    public class MigrationAppService : AbpZeroTemplateAppServiceBase, IMigrationAppService
    {
        private readonly IRepository<Tenant> _tenantRepository;

        public MigrationAppService(IRepository<Tenant> tenantRepository)
        {
            _tenantRepository = tenantRepository;
        }

        public async Task SaveZipAsync(int id, Stream stream, string path)
        {
            var tenant = await _tenantRepository.GetAsync(id);
            if (tenant == null)
                throw new Exception($"Tenant with {id} was not found.");
        }
    }
}

The tenant and host DB context is attached. It appears that the error surfaces in AbpZeroTemplateTenantDbContext.AbpZeroTemplateTenantDbContext() and might be trying to use the tenant context instead of the host. The 15 lines of the error is:

Castle.MicroKernel.ComponentActivator.ComponentActivatorException
ComponentActivator: could not instantiate MyCompanyName.AbpZeroTemplate.EntityFramework.AbpZeroTemplateTenantDbContext
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstanceCore(ConstructorCandidate constructor, Object[] arguments, Type implType)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstance(CreationContext context, ConstructorCandidate constructor, Object[] arguments)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext context)
   at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext context, Burden burden)
   at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.CreateInstance(CreationContext context, Boolean trackedExternally)
   at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy)
   at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden)
   at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired)
   at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy)
   at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy)
   at Abp.EntityFramework.DefaultDbContextResolver.Resolve[TDbContext](String connectionString) in D:\Halil\GitHub\aspnetboilerplate\src\Abp.EntityFramework\EntityFramework\DefaultDbContextResolver.cs:line 30
   at Abp.EntityFramework.Uow.EfUnitOfWork.GetOrCreateDbContext[TDbContext](Nullable`1 multiTenancySide) in D:\Halil\GitHub\aspnetboilerplate\src\Abp.EntityFramework\EntityFramework\Uow\EfUnitOfWork.cs:line 130
   at Castle.Proxies.EfRepositoryBase`3Proxy_14.get_Context_callback()

Can you advise on how to write this simple unit test or how to avoid this error?

Thank you for your help. DBContexts.zip

Hello,

We recently tried to implement signalR change notifications (following [http://www.aspnetboilerplate.com/Pages/Documents/SignalR-Integration]) )with host and tenant dbContexts. When we ran, there were errors: UserFriendsCache: {"Invalid object name 'dbo.AppFriendships'."} and also the same error for table AppChatMessages. A screenshot of this error is attached. I apologize if file is blurry, but it would not let me upload a larger file. If it is hard to read, tell me and I can upload multiple images of error.

When we manually create those tables in the tenant DB, then the error goes away. Is this the correct fix?

<ins>Background Information:</ins> in our layout page:

<script src="~/wwwroot/js/jquery.signalR-2.2.1.js" type="text/javascript"></script>
  <script src="~/signalr/hubs" type="text/javascript"></script>    
  // ..a few other script files
  <script src="~/wwwroot/js/abp.signalr.js" type="text/javascript"></script>

The ChangeNotificationHub.cs file looks like this:

namespace MyCompanyName.AbpZeroTemplate.Web.Hubs
{
    using Abp.Dependency;
    using Microsoft.AspNet.SignalR;
    using Microsoft.AspNet.SignalR.Hubs;
    using System.Threading.Tasks;

    [HubName("changeNotify")]
    public class ChangeNotificationHub: Hub, ITransientDependency
    {
        public Task Deregister(string groupName)
        {
            return Groups.Remove(Context.ConnectionId, groupName);
        }

        public Task Register(string groupName)
        {
            return Groups.Add(Context.ConnectionId, groupName);
        }

        public void Save(string groupName)
        {
            Clients.OthersInGroup(groupName).changePending();
        }
    }
}

and the changeNotification.js file looks like this:

(function () {
    var changeNotifyHub = $.connection.changeNotify;

    // Connected
    abp.event.on('abp.signalr.connected', function () {
        changeNotifyHub.server.register(ams.getCurrentUrl());
    });

    // Disconnected
    abp.event.on('abp.signalr.disconnected', function () {
        changeNotifyHub.server.deregister(ams.getCurrentUrl());
    });

    changeNotifyHub.client.changePending = function () {
        $('#saveAlert').toggleClass('hidden');
        // buttonGroup.state = reset;
    };

    $.connection.hub.start();
})();

Thank you again for your help. Please let me know if you need any more information.

I am trying to stream a file to a service class (import). In this simplified example I am getting an error:

public class DepartmentController : AmsControllerBase
    {
        private readonly IDepartmentAppService _departmentAppService;

        public DepartmentController(IDepartmentAppService departmentAppService)
        {
            _departmentAppService = departmentAppService;
        }

        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Import()
        {
            var data = System.IO.File.ReadAllBytes(@"c:\temp\departments.csv");

            var stream = new MemoryStream(data);
            _departmentAppService.Import(stream);//<--Exception throws here and method is not executed

            return null;
        }
    }

Controller base class is:

public abstract class AmsControllerBase : AbpController
    {
        protected AmsControllerBase()
        {
            LocalizationSourceName = AmsConsts.LocalizationSourceName;
        }

        protected void CheckErrors(IdentityResult identityResult)
        {
            identityResult.CheckErrors(LocalizationManager);
        }
    }

The error I get is:

Timeouts are not supported on this stream

Is there a different way I should be passing a stream around? The file's size is about 1 kb. Thanks again for your time and effort.

Hello,

We have been trying to set up an application using ASP.NET Zero Template where all users log on at 1 location. Then each tenant (more than 1 user per tenant) has their own database. We can log in as the global admin (no tenant ID) with no errors. However, when we try to login as a tenant user, we get:

Invalid object name 'dbo.AbpUsers'.

This table is only in the Host DB. The Tenant DB does not have this information. When we copy over this table from Host DB to Tenant DB then then we get more errors for multiple ABP* Tables. We want to authenticate against the Host DB, but not have all the abp tables duplicated in the tenant. Is this the correct approach?

For more information, here are the two Context classes:

public class TenantDbContext : AbpDbContext
    {
        public virtual IDbSet<Department> Departments { get; set; }

        public TenantDbContext() : 
            base("Tenant")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Configurations.Add(new DepartmentConfiguration());
        }
    }
public class HostDbContext : AbpZeroHostDbContext<Tenant, Role, User>
    {
        public virtual IDbSet<BinaryObject> BinaryObjects { get; set; }
        public virtual IDbSet<Friendship> Friendships { get; set; }
        public virtual IDbSet<ChatMessage> ChatMessages { get; set; }

        public HostDbContext()
            : base("Host")
        {
            
        }

        public HostDbContext(string nameOrConnectionString)
            : base(nameOrConnectionString)
        {

        }


        public HostDbContext(DbConnection dbConnection)
            : base(dbConnection, true)
        {

        }
    }

Thank you for your time and effort.

We are using DevExtreme's dxDatagrid which currently posts back to API controller methods with content-type of "application/x-www-form-urlencoded." If we try to invoke this grid's actions, then we get a 500 server error.

We get this error: nHandling.AbpApiExceptionFilterAttribute - Processing of the HTTP request resulted in an exception. Please see the HTTP response returned by the 'Response' property of this exception for details. System.Web.Http.HttpResponseException: Processing of the HTTP request resulted in an exception. Please see the HTTP response returned by the 'Response' property of this exception for details. at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken) at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable1 formatters, IFormatterLogger formatterLogger) at System.Web.Http.ModelBinding.FormatterParameterBinding.<ExecuteBindingAsyncCore>d__0.MoveNext()

When we invoke the action using Fiddler with JSON then it works perfectly. Is there a way to allow

abp.services.app.[controller].[action]()

to submit as "application/x-www-form-urlencoded"?

We have also asked DevExpress for any way to make their control encode using JSON here (this shows code snippets if needed).

Showing 31 to 40 of 43 entries