Tested version: Latest Tested app: Demo Project type: ASP.NET Core & Angular
Hi guys, We are facing an issue in abp/zero. We consider build as failure when all tests does not pass so we had to skip only one test of yours for now. use case:
Assertion error occurs:
Shouldly.ShouldAssertException : currentLanguages.Any(l => l.Name == randomLanguage.Name) should be False but was True
I guess problem is that instance of deleted ApplicationLanguage is not removed from cache. I had to admit I don't have time to research why now but I guess IEventHandler<in TEventData>.HandleEvent is not called.
Thanks.
Thanks for answer. But when we convert users from already existing database from another system than Abp this synchronizer is unable to done it's job right? Of course if synchronizer is not registered as some continuous repeated service/task right? So question is - for already existing records in User table(we renamed it from AbpUsers to User using Table attribute) should we insert records to UserAccount table manually or it is not necessary?
Well we tried to disable Multitenancy but it caused problems so we decided to rather enable multitenancy. - Reason is probably hidden in already existing User table from another application and some missing configuration need by Abp system to make it run - that's the reason why I am asking for all of this.
Hi guys, I just want to make it clear for me. I read this: https://support.aspnetzero.com/QA/Questions/2248 If I understand it well UserAccount is used only when Multitenancy is enabled? Otherwise this table can be empty? I am asking because we have to connect Zero to the existing DB which does not have UserAccount table and it is not desired to have one. For now we don't want to use multitenancy so if I am right this should not be a problem.
Second question:
We have existing DB and try to run Zero against it so we must initialize all necessary tables for Zero/Abp correctly - which we are unable for now.
If we disable Multitenancy we have to store Default Tenant to DB? I am asking because we are facing an issue because your default Seeder always creates Host and Tenant user and Default tenant is added to DB too. During logon (to swagger) is generated SQL query like this:
exec sp_executesql N'SELECT TOP(1) [user].[Id], [user].[AccessFailedCount], [user].[AuthenticationSource], [user].[ConcurrencyStamp], [user].[Created], [user].[CreatorUserId], [user].[DeleterUserId], [user].[DeletionTime], [user].[EmailAddress], [user].[EmailConfirmationCode], [user].[GoogleAuthenticatorKey], [user].[IsActive], [user].[IsDeleted], [user].[IsEmailConfirmed], [user].[IsLockoutEnabled], [user].[IsPhoneNumberConfirmed], [user].[IsTwoFactorEnabled], [user].[LastModificationTime], [user].[LastModifierUserId], [user].[LockoutEndDateUtc], [user].[Name], [user].[NormalizedEmailAddress], [user].[NormalizedUserName], [user].[StoredPassword], [user].[PasswordResetCode], [user].[Person], [user].[PhoneNumber], [user].[ProfilePictureId], [user].[SecurityStamp], [user].[ChangePasswordOnFirstLogon], [user].[SignInToken], [user].[SignInTokenExpireTimeUtc], [user].[Surname], [user].[TenantId], [user].[UserName] FROM [User] AS [user] WHERE (((@__ef_filter__IsSoftDeleteFilterEnabled_0 = 0) OR ([user].[IsDeleted] = 0)) AND ((@__ef_filter__IsMayHaveTenantFilterEnabled_1 = 0) OR ([user].[TenantId] = @__ef_filter__CurrentTenantId_2))) AND (([user].[NormalizedUserName] = @__normalizedUserNameOrEmailAddress_0) OR ([user].[NormalizedEmailAddress] = @__normalizedUserNameOrEmailAddress_0))',N'@__ef_filter__IsSoftDeleteFilterEnabled_0 bit,@__ef_filter__IsMayHaveTenantFilterEnabled_1 bit,@__ef_filter__CurrentTenantId_2 int,@__normalizedUserNameOrEmailAddress_0 nvarchar(256)',@__ef_filter__IsSoftDeleteFilterEnabled_0=1,@__ef_filter__IsMayHaveTenantFilterEnabled_1=1,@__ef_filter__CurrentTenantId_2=1,@__normalizedUserNameOrEmailAddress_0=N'ATTN'
The problem part is in WHERE clause: ((@__ef_filter__IsMayHaveTenantFilterEnabled_1 = 0) OR ([user].[TenantId] = @__ef_filter__CurrentTenantId_2))
where @__ef_filter__CurrentTenantId_2 = 1
expected is null
Same happens when we have our table with Navigation property of type User and try to Include - same where clause is added so nothing is returned from database.
I guess it is about to configure application somehow but I can not find in your documentation how to make it work without multitenancy for now. In future we want to enable multitenancy so maybe we try switch the MultitenancyEnabled to true now and will see what happens.
But still it would be nice to have all the informations on how to make application run both ways: Host and Multitenancy without problems.
I tried today enable OData - I am able successfully communicate using OData but odata url is not visible in swagger. Used https://aspnetboilerplate.com/Pages/Documents/OData-AspNetCore-Integration Is it possible to use nswag with OData in zero?
Sorry for delayed answer. I'm overhelmed by porting our current solution to aspnet zero. We solve it that way we inherit our ViewModels from Entity<TPrimaryKey> for these ViewModels we create DbQuery in DbContext (otherwise exception is thrown from Abp) and our repositories works with ViewModels and inside concrete implementation of Repository we map Entity to ViewModel - for now using AppServices without OData - this will come later we now need to quickly port base functionality. Idea behind Odata is to create OData controller and using DI we will inject concrete AppService to this controller thanks to this we will have all previously created functionality with support for OData - just idea not tested if possible.
Thanks I thought it will be something like that what cause the problem. Is there some way how to obtain this functionality and be able to use Repository without IEntity and keep your functionality behind the scenes? We don't know much about your structures yet but I presume Repository has some hidden functionality which we can loose when we start to create and register our own custom repositories and do not use yours IRepository or am I mistaken?
We are thinking about something like this:
public class TaskRepository : CustomRepo<TaskDto> {
public TaskRepository(IDbContextProvider<AttisDemoDbContext> dbContextProvider) : base(dbContextProvider) {
}
}
public abstract class CustomRepo<TDto, TPrimaryKey>
where TDto : IDto<TPrimaryKey> {
protected readonly AttisDemoDbContext Ctx;
protected CustomRepo(IDbContextProvider<AttisDemoDbContext> dbContextProvider) {
Ctx = dbContextProvider.GetDbContext();
}
public virtual Task<IQueryable<TDto>> GetAllAsync() {
return Task.FromResult(GetAll());
}
public abstract IQueryable<TDto> GetAll();
.
.
.
etc.
}
public interface IDto<TPrimaryKey> : IDto {
TPrimaryKey Id { get; set; }
}
public interface IDto {
object KeyValue { get; }
}
Structure is similar to yours but with that change TaskDto is not an entity registered to DbContext - now I expect to override GetAll method get desired DbSet join another DBSets if desired, filter record/s I want and return them in structure of my choice. So I think the only problem is part of code you posted as answer the rest is OK I think. What I dont know is where to get MultitenancySIte for GetDbContext method. I guess this parameter is necessary if we want to support multitenancy and keep DbContext works correctly with tenancy.
Hope you understand why we need this.
Hi guys, We try to implement our own Repository (https://aspnetboilerplate.com/Pages/Documents/EntityFramework-Integration) but we are facing an issue. When I use piece of code above (TaskAppService) exception is raised, but when we change generic to TaskEntity type (EfCore entity) everything works fine. Unfortunately we need to use TaskDto instead of TaskEntity. TaskDto inherits from IEntity<TPrimaryKey> Exception is raised when we try to execute action GetTasks. WebAPI starts as usual without any problem. AutorepositoryTypes registration:
[AutoRepositoryTypes(
typeof(ICustomRepository<>)
, typeof(ICustomRepository<,>)
, typeof(AttisDemoRepository<>)
, typeof(AttisDemoRepository<,>)
, WithDefaultRepositoryInterfaces = true
)]
Raised exception:
'AttisDemo.Tasks.TaskAppService' is waiting for the following dependencies:
- Service 'AttisDemo.ICustomRepository`1[[AttisDemo.Tasks.Dto.TaskDto, AttisDemo.Application.Shared, Version=7.1.0.0, Culture=neutral, PublicKeyToken=null]]' which was not registered.
TaskAppService:
public class TaskAppService : AttisDemoAppServiceBase, ITaskAppService {
[NotNull]
private readonly ICustomRepository<TaskDto> _taskRepo;
public TaskAppService([NotNull] ICustomRepository<TaskDto> taskRepo) {
_taskRepo = taskRepo;
}
public async Task<ListResultDto<TaskDto>> GetTasks() {
var tasks = await _taskRepo.GetAll().ToListAsync();
return new ListResultDto<TaskDto>(tasks);
}
public async Task<TaskDto> GetTaskById(TaskInput filter) {
var task = await _taskRepo.GetAll().WhereIf(filter?.Id != null, tasks => tasks.Id == filter.Id)?.FirstOrDefaultAsync();
return task;
}
public async Task CreateTask(TaskDto input) {
//var taskEntity = ObjectMapper.Map<TaskEntity>(input);
await _taskRepo.InsertAsync(input);
}
public async Task UpdateTask(int taskId, TaskDto input) {
var taskEntity = await _taskRepo.GetAsync(taskId);
taskEntity.Description = input.Description;
taskEntity.Identification = input.Identification;
await _taskRepo.UpdateAsync(taskEntity);
}
}
TaskRepo:
public class TaskRepo : AttisDemoRepository<TaskDto> {
public TaskRepo(IDbContextProvider<AttisDemoDbContext> dbContextProvider) : base(dbContextProvider) {
}
public override IQueryable<TaskDto> GetAsQuearyable(Expression<Func<TaskDto, bool>> criteria) {
var taskDtos = Context.Tasks.Select(a => new TaskDto {
Id = a.Id,
Description = a.Description,
Identification = a.Identification
});
if (criteria != null) {
return taskDtos.Where(criteria);
}
return taskDtos;
}
public override Task<TaskDto> GetByKeyAsync(int id) {
return GetAll().FirstOrDefaultAsync(a => a.Id == id);
}
}
Thanks in advance.
@ismcagdas Yes, We have implemented such functionality (code from my initial post). Question is if exists such possibility with asp.net zero. Reasons to do it is same as for common controller - security, not to show all properties from entity and that ViewModel can be different from Entity of course which is our reason why we need such functionality.
Yes I sucessfully implemented approach 2, but question was quite different. I asked how can we use OData in ASP.NET Zero with DTOs/ViewModels instead of Entities.
P.S.: Can you please update your documentation for ASP.NET Core v2.2 it is necessary to registee MvcCore pipe like this: https://github.com/OData/WebApi/issues/1707
services.AddMvcCore(options => { options.EnableEndpointRouting = false; foreach (var outputFormatter in options.OutputFormatters.OfType<ODataOutputFormatter>().Where(_ => _.SupportedMediaTypes.Count == 0)) { outputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/prs.odatatestxx-odata")); } foreach (var inputFormatter in options.InputFormatters.OfType<ODataInputFormatter>().Where(_ => _.SupportedMediaTypes.Count == 0)) { inputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/prs.odatatestxx-odata")); } }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
Hi guys, I tried to implement OData support for ASPNet Zero template but I am facing problem. I guess we can not use ApplicationService when we want to use OData right? I followed this article but the problem is we want to use Dtos/ViewModels instead of Entities, but AbpODataEntityController force us to use (and return) Entities. Idea is that repos will work with Entities and controller will transform entities to ViewModels and return ViewModel. So something like this: ` [AbpMvcAuthorize] public class ODataController<TEntity, TViewModel> : AbpODataController where TEntity : class, IEntity where TViewModel : class, new() {
[NotNull] private readonly IRepository _repository;
[NotNull] private readonly IMapper _mapper;
public ODataController([NotNull] IRepository
For ODataConventionModelBuilder we will register Dtos/ViewModels instead of Entities too. In our one of our applications we have something similar. We must specify TEntity too just for sake of Repository. Question is when we implement this will we be able to use nswag for generating proxies in angular? What about permissions in angular? Do you see some problems with this solution? Do we have to rework generated AppServices to controllers to be able to use them with OData too?
Thanks in advance.