Base solution for your next web application
Open Closed

AbpSession is NULL #563


User avatar
0
doubledp created

Hi,

When calling GetCurrentUser defined within ApplicationServiceBase from my application service that inherits from my ApplicationServiceBase it fails as all AbpSession properties is null.

appService.user is set correctly in the client side code within the AngularJS controller.

Need help urgently please!


20 Answer(s)
  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    There are many code in the application use IAbpSession properties and it's working properly. Can you send your code to understand what's the difference (are you creating a new Thread?).

  • User Avatar
    0
    doubledp created

    Hi,

    Here is the ApplicationServiceBase:

    using Abp.Application.Services;
    using Abp.IdentityFramework;
    using Abp.MultiTenancy;
    using Abp.Runtime.Session;
    using Caerus.Authorization.Locations;
    using Caerus.Authorization.Users;
    using Caerus.MultiTenancy;
    using Microsoft.AspNet.Identity;
    using System;
    using System.Configuration;
    using System.Threading.Tasks;
    
    namespace Caerus
    {
        /// <summary>
        /// All application services in this application is derived from this class.
        /// We can add common application service methods here.
        /// </summary>
        public abstract class CaerusAppServiceBase : ApplicationService
        {
            public TenantManager TenantManager { get; set; }
    
            public UserManager UserManager { get; set; }
    
            private LocationManager _locationManager { get; set; }
    
            protected CaerusAppServiceBase()
            {
                LocalizationSourceName = CaerusConsts.LocalizationSourceName;
            }
    
            protected virtual Task<User> GetCurrentUserAsync()
            {
                var user = UserManager.FindByIdAsync(AbpSession.GetUserId());
                if (user == null)
                {
                    throw new ApplicationException("There is no current user!");
                }
    
                return user;
            }
    
            protected virtual User GetCurrentUser()
            {
                var user = UserManager.FindById(AbpSession.GetUserId());
                if (user == null)
                {
                    throw new ApplicationException("There is no current user!");
                }
    
                return user;
            }
    
            protected virtual Task<Tenant> GetCurrentTenantAsync()
            {
                return TenantManager.GetByIdAsync(AbpSession.GetTenantId());
            }
    
            protected virtual Tenant GetCurrentTenant()
            {
                return TenantManager.GetById(AbpSession.GetTenantId());
            }
    
            protected virtual CommaDelimitedStringCollection GetCurrentUserAssignedLocations()
            {
                var assignedLocations = new CommaDelimitedStringCollection();
                var user = GetCurrentUser();
    
                if (user == null)
                {
                    throw new ApplicationException("There is no current user!");
                }
    
                if (user.Locations.Count == 0)
                {
                    throw new ApplicationException("There is no location assigned to the user!");
                }
    
                foreach (var userLocation in user.Locations)
                {
                    var location = _locationManager.GetLocationById(userLocation.LocationId);
    
                    if (location == null)
                    {
                        throw new ApplicationException("There is no location with id: " + userLocation.LocationId);
                    }
    
                    assignedLocations.Add(location.Code);
                }
    
                return assignedLocations;
            }
    
            protected virtual void CheckErrors(IdentityResult identityResult)
            {
                identityResult.CheckErrors(LocalizationManager);
            }
        }
    }
    

    and here is the ApplicationService:

    using Abp.Application.Services.Dto;
    using Abp.Authorization;
    using Abp.AutoMapper;
    using Caerus.Authorization;
    using Caerus.Tenants.Workshop.Servicing.Dto;
    using Caerus.Workshop.Servicing.Repositories;
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Threading.Tasks;
    
    namespace Caerus.Tenants.Workshop.Servicing
    {
        [AbpAuthorize(AppPermissions.Pages_Tenant_Workshop_Servicing_Reports_ServicesDue)]
        public class WorkshopServicingServicesDueAppService : CaerusAppServiceBase, IWorkshopServicingServicesDueAppService
        {
            private readonly IServicesDueAggregateRepository _servicesDueAggregateRepository;
            private readonly IServicesDueDetailRepository _servicesDueDetailRepository;
            private CommaDelimitedStringCollection _assignedLocations { get; set; }
    
            public WorkshopServicingServicesDueAppService(IServicesDueAggregateRepository servicesDueAggregateRepository)
            {
                _servicesDueAggregateRepository = servicesDueAggregateRepository;
                var user = GetCurrentUser();
                _assignedLocations = GetCurrentUserAssignedLocations();
            }
    
            public WorkshopServicingServicesDueAppService(IServicesDueDetailRepository servicesDueDetailRepository)
            {
                _servicesDueDetailRepository = servicesDueDetailRepository;
                var user = GetCurrentUser();
                _assignedLocations = GetCurrentUserAssignedLocations();
            }
    
            public async Task<ListResultOutput<ServicesDueAggregateListDto>> GetServicesDueAggregationByType(ServicesDueAggregateInput input)
            {
                var servicesDueAggregate = _servicesDueAggregateRepository.GetServicesDueAggregationByType(_assignedLocations.ToString(), input.StartDate, input.EndDate);
    
                return new ListResultOutput<ServicesDueAggregateListDto>(servicesDueAggregate.MapTo<List<ServicesDueAggregateListDto>>());
            }
    
            public Task<ListResultDto<ServicesDueDetailListDto>> GetServicesDueDetailByType(ServicesDueDetailInput input)
            {
                throw new NotImplementedException();
            }
        }
    }
    

    Any help will be greatly appreciated, I know it works as I had a look at ProfileAppService, but I can't figure out what I am doing wrong.

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    Do not call GetCurrentUser() in constructor. Because, session properties are not obtained from cookie when your service is created. Just use GetCurrentUser() in service methods whenever you need. (Even you can call multiple times, don't worry EF will perform only one query thanks to it's UnitOfWork Cache.)

    While this is not related to problem, I see you have 2 constructor. Why? You should normally have only one constructor takes 2 repositories:

    public WorkshopServicingServicesDueAppService(IServicesDueAggregateRepository servicesDueAggregateRepository, IServicesDueDetailRepository servicesDueDetailRepository)
    {
        ...
    }
    

    If you have 2 constructor, you can not know which is used by DI framework.

  • User Avatar
    0
    doubledp created

    Ah thank you very much, I am going to try this.

    Reason why I have to constructors is because the dashboard calls a stored procedure for aggregated data and the detailed report displaying the data in the grid is related. I thought it would make sense to keep it in the same AppService, obviously I am doing it wrong. Pardon me for doing things the wrong way, I am still learning.

    I have a problem still with the multiple dbContext too. The context is not set correctly in the the custom repository and it still referring to the 1st context connectionstring defined in the web.config.

    Any chance you could help me on that? Should I asked this on a different thread? I am really desperate at this stage as I am struggling very much and have lost a lot of hair.

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    Can you check your DbContext's Constructors. In the template you have 3 constructors as shown below:

    public class AbpZeroTemplateDbContext : AbpZeroDbContext<Tenant, Role, User>
        {
            /* Define an IDbSet for each entity of the application */
    
            public virtual IDbSet<BinaryObject> BinaryObjects { get; set; }
    
            /* Setting "Default" to base class helps us when working migration commands on Package Manager Console.
             * But it may cause problems when working Migrate.exe of EF. ABP works either way.         * 
             */
            public AbpZeroTemplateDbContext()
                : base("Default")
            {
    
            }
    
            /* This constructor is used by ABP to pass connection string defined in AbpZeroTemplateDataModule.PreInitialize.
             * Notice that, actually you will not directly create an instance of AbpZeroTemplateDbContext since ABP automatically handles it.
             */
            public AbpZeroTemplateDbContext(string nameOrConnectionString)
                : base(nameOrConnectionString)
            {
    
            }
    
            /* This constructor is used in tests to pass a fake/mock connection.
             */
            public AbpZeroTemplateDbContext(DbConnection dbConnection)
                : base(dbConnection, true)
            {
    
            }
        }
    

    With this constructors, Default conn string is used for the dbcontext. I suggest you to remove 2. and 3. constructors. Also change 'Default' to your second conn string name or directly conn string.

    Have a nice day.

  • User Avatar
    0
    doubledp created

    Hi,

    I have tried that but was unsuccessful in my attempt. I then reverted back to the way it was before.

    Here is my 2nd dbContext:

    using Abp.EntityFramework;
    using Caerus.Workshop.Servicing;
    using System.Data.Common;
    using System.Data.Entity;
    
    namespace Caerus.EntityFramework
    {
        public class AutolineDbContext : AbpDbContext
        {
            public virtual IDbSet<ServicesDueAggregate> ServicesDueAggregate { get; set; }
    
            public AutolineDbContext()
                : base("Autoline")
            {
    
            }
    
            public AutolineDbContext(string nameOrConnectionString)
                : base(nameOrConnectionString)
            {
    
            }
    
            /* This constructor is used in tests to pass a fake/mock connection.
             */
            public AutolineDbContext(DbConnection dbConnection)
                : base(dbConnection, true)
            {
    
            }
        }
    }
    

    Here is my repository base for my 2nd dbContext:

    using Abp.Domain.Entities;
    using Abp.EntityFramework;
    using Abp.EntityFramework.Repositories;
    
    namespace Caerus.EntityFramework.Repositories
    {
        public abstract class AutolineRepositoryBase<TEntity, TPrimaryKey> : EfRepositoryBase<AutolineDbContext, TEntity, TPrimaryKey>
            where TEntity : class, IEntity<TPrimaryKey>
        {
            protected AutolineRepositoryBase(IDbContextProvider<AutolineDbContext> dbContextProvider)
                : base(dbContextProvider)
            {
    
            }
        }
    
        public abstract class AutolineRepositoryBase<TEntity> : AutolineRepositoryBase<TEntity, int>
            where TEntity : class, IEntity<int>
        {
            protected AutolineRepositoryBase(IDbContextProvider<AutolineDbContext> dbContextProvider)
                : base(dbContextProvider)
            {
    
            }
        }
    }
    

    Here is my custom repository's interface:

    using Abp.Dependency;
    using Abp.Domain.Repositories;
    using Caerus.Workshop.Servicing;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Caerus.Workshop.Servicing.Repositories
    {
        public interface IServicesDueAggregateRepository : IRepository<ServicesDueAggregate>, ITransientDependency
        { 
            List<ServicesDueAggregate> GetServicesDueAggregationByType(string Type, DateTime? startDate, DateTime? endDate);
        }
    }
    

    Here is my implementation of custom repository:

    using System;
    using System.Collections.Generic;
    using Abp.EntityFramework;
    using Caerus.Workshop.Servicing;
    using System.Linq;
    using System.Data.SqlClient;
    using Caerus.Workshop.Servicing.Repositories;
    
    namespace Caerus.EntityFramework.Repositories.Workshop.Servicing
    {
        public class ServicesDueAggregateRepository : AutolineRepositoryBase<ServicesDueAggregate>, IServicesDueAggregateRepository
        {
            public ServicesDueAggregateRepository(IDbContextProvider<AutolineDbContext> dbContextProvider)
                : base(dbContextProvider)
            {
    
            }
    
            public List<ServicesDueAggregate> GetServicesDueAggregationByType(string locationCode, DateTime? startDate, DateTime? endDate)
            {
                var LocationCode = new SqlParameter { ParameterName = "@locationCode", SqlDbType = System.Data.SqlDbType.VarChar, Size = 3, Value = locationCode };
                var StartDate = new SqlParameter { ParameterName = "@startDate", SqlDbType = System.Data.SqlDbType.Date, Value = startDate };
                var EndDate = new SqlParameter { ParameterName = "@endDate", SqlDbType = System.Data.SqlDbType.Date, Value = endDate };
    
                var result =  Context.Database.SqlQuery<ServicesDueAggregate>(
                    "EXEC dbo.sp_FK_Agreement_ServicesDue_By_Type_Count @LocationCode, @StartDate, @EndDate",
                    LocationCode,
                    StartDate,
                    EndDate
                    ).ToList();
    
                return result;
            }
        }
    }
    

    I ended up implementing it as follows and there is communication with the database now:

    using Caerus.Workshop.Servicing;
    using Caerus.Workshop.Servicing.Repositories;
    using System;
    using System.Collections.Generic;
    using System.Data.SqlClient;
    using System.Linq;
    
    namespace Caerus.EntityFramework.Repositories.Workshop.Servicing
    {
        public class ServicesDueAggregateRepository : IServicesDueAggregateRepository
        {
            private AutolineDbContext _autolineDbContext;
    
            public ServicesDueAggregateRepository()
            {
                _autolineDbContext = new AutolineDbContext("Autoline");
            }
    
            public List<ServicesDueAggregate> GetServicesDueAggregationByType(string locationCode, DateTime? startDate, DateTime? endDate)
            {
                var LocationCode = new SqlParameter { ParameterName = "@locationCode", SqlDbType = System.Data.SqlDbType.VarChar, Size = 3, Value = locationCode };
                var StartDate = new SqlParameter { ParameterName = "@startDate", SqlDbType = System.Data.SqlDbType.Date, Value = startDate };
                var EndDate = new SqlParameter { ParameterName = "@endDate", SqlDbType = System.Data.SqlDbType.Date, Value = endDate };
    
                var result = _autolineDbContext.Database.SqlQuery<ServicesDueAggregate>(
                    "EXEC dbo.sp_FK_Agreement_ServicesDue_By_Type_Count @LocationCode, @StartDate, @EndDate",
                    LocationCode,
                    StartDate,
                    EndDate
                    ).ToList();
    
                return result;
            }
        }
    }
    

    But I would very much like to implement it rather using your brilliant method via dependency injection. I must admit I don't fully understand how the dependency injection works within your framework and try to follow how you have done it in the hope that I will get the same results.

    It would be very helpful if you could maybe do some detailed documentation explaining how and why some of these concepts in the framework is being implemented in the way it does. I think it will go a long way in reducing the number of questions one might have.

    By the way I just want you thank you for all the help and for providing such an awesome framework and template. You are an inspiration to me after seeing how things really should be done and the techniques that should be implemented.

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    As I understand, your final ServicesDueAggregateRepository is like that:

    using Caerus.Workshop.Servicing;
    using Caerus.Workshop.Servicing.Repositories;
    using System;
    using System.Collections.Generic;
    using System.Data.SqlClient;
    using System.Linq;
    
    namespace Caerus.EntityFramework.Repositories.Workshop.Servicing
    {
        public class ServicesDueAggregateRepository : IServicesDueAggregateRepository
        {
            private AutolineDbContext _autolineDbContext;
    
            public ServicesDueAggregateRepository()
            {
                _autolineDbContext = new AutolineDbContext("Autoline");
            }
    
            public List<ServicesDueAggregate> GetServicesDueAggregationByType(string locationCode, DateTime? startDate, DateTime? endDate)
            {
                var LocationCode = new SqlParameter { ParameterName = "@locationCode", SqlDbType = System.Data.SqlDbType.VarChar, Size = 3, Value = locationCode };
                var StartDate = new SqlParameter { ParameterName = "@startDate", SqlDbType = System.Data.SqlDbType.Date, Value = startDate };
                var EndDate = new SqlParameter { ParameterName = "@endDate", SqlDbType = System.Data.SqlDbType.Date, Value = endDate };
    
                var result = _autolineDbContext.Database.SqlQuery<ServicesDueAggregate>(
                    "EXEC dbo.sp_FK_Agreement_ServicesDue_By_Type_Count @LocationCode, @StartDate, @EndDate",
                    LocationCode,
                    StartDate,
                    EndDate
                    ).ToList();
    
                return result;
            }
        }
    }
    

    I think this is not true. Because, you are violating Dependency Injection with creating AutolineDbContext manually. Instead, your first implementation was correct:

    using System;
    using System.Collections.Generic;
    using Abp.EntityFramework;
    using Caerus.Workshop.Servicing;
    using System.Linq;
    using System.Data.SqlClient;
    using Caerus.Workshop.Servicing.Repositories;
    
    namespace Caerus.EntityFramework.Repositories.Workshop.Servicing
    {
        public class ServicesDueAggregateRepository : AutolineRepositoryBase<ServicesDueAggregate>, IServicesDueAggregateRepository
        {
            public ServicesDueAggregateRepository(IDbContextProvider<AutolineDbContext> dbContextProvider)
                : base(dbContextProvider)
            {
    
            }
    
            public List<ServicesDueAggregate> GetServicesDueAggregationByType(string locationCode, DateTime? startDate, DateTime? endDate)
            {
                var LocationCode = new SqlParameter { ParameterName = "@locationCode", SqlDbType = System.Data.SqlDbType.VarChar, Size = 3, Value = locationCode };
                var StartDate = new SqlParameter { ParameterName = "@startDate", SqlDbType = System.Data.SqlDbType.Date, Value = startDate };
                var EndDate = new SqlParameter { ParameterName = "@endDate", SqlDbType = System.Data.SqlDbType.Date, Value = endDate };
    
                var result =  Context.Database.SqlQuery<ServicesDueAggregate>(
                    "EXEC dbo.sp_FK_Agreement_ServicesDue_By_Type_Count @LocationCode, @StartDate, @EndDate",
                    LocationCode,
                    StartDate,
                    EndDate
                    ).ToList();
    
                return result;
            }
        }
    }
    

    The problem was on DbContext. It should be like that:

    using Abp.EntityFramework;
    using Caerus.Workshop.Servicing;
    using System.Data.Common;
    using System.Data.Entity;
    
    namespace Caerus.EntityFramework
    {
        public class AutolineDbContext : AbpDbContext
        {
            public virtual IDbSet<ServicesDueAggregate> ServicesDueAggregate { get; set; }
    
            public AutolineDbContext()
                : base("Autoline")
            {
    
            }
        }
    }
    

    I just removed other constructors (have you seen this sample before: <a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate-samples/tree/master/Others">https://github.com/aspnetboilerplate/as ... ter/Others</a> - MultipleDbContextDemo.zip).

    Actually, ABP's Dependency Injection implementation is not much different and documented on <a class="postlink" href="http://www.aspnetboilerplate.com/Pages/Documents/Dependency-Injection">http://www.aspnetboilerplate.com/Pages/ ... -Injection</a> ABP has a wide documentation. Surely, there maybe not documented things. I'm improving documentation by time.

    Here, in the DbContext, there is just a simple special case. As you see, sample DbContext has 3 constructors. Why?

    1. MyDbContext() needed since Entity Framework requires default constructor for migration commands.
    2. MyDbContext(string nameOrConnectionString) is used by ABP to pass connection string defined in configuration (which is defined in your EntityFrameworkModule class).
    3. MyDbContext(DbConnection dbConnection) is used in unit tests to pass a fake DbConnection.

    Thank you very much :)

  • User Avatar
    0
    doubledp created

    Yes I did think that my approach of instantiating the dbContext the manually is not really correct, but it was desperate times for me :oops:

    I have run into a problem now with that approach in that when reading data using the 1st dbContext and reading data using the 2nd dbContext causes an error which requires me to have MSDTC running on my local machine (which hosts the database of the 1st dbContext) and MSDTC running on the remote machine (which hosts the database of the 2nd dbContext).

    I don't think it will be an option to allow MSDTC network access on the remote machine.

    I am going to try your suggested approach again (I am almost sure I did try that before and it didn't work).

    Question I have is, do I have to enable migrations on the 2nd dbContext for this to work? The reason I ask is because I won't be migrating my entities to the database as this database is used only for read purposes.

  • User Avatar
    0
    doubledp created

    Thank you Halil, that worked beautifully! Not sure why it didn't work the 1st time, maybe I did something wrong during my many fiddles to try and get it working.

    Now I am still faced with the TransactionScope issue that requires me to have MSDTC enabled. Like I said I don't think it will be an option.

    Is there any other way around this?

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    Multiple DbContext required MSDTC is running. That's about EF. You can disable transaction but I don't suggest normally. Why this is a problem for you?

    Thanks.

  • User Avatar
    0
    doubledp created

    Ok I understand that is now a requirement due to the way EF works.

    Because I am currently hosting the application database on my local machine for development purposes, enabling MSDTC is not a problem for me.

    The database that I am reading the data via stored procedures is remote though and for me to enable network access for MSDTC to allow coordination between local and remote, firewall settings needs to be changed, which the network administrator is very reluctant to do.

    I will try and convince him that that is what needs to be done for this to work.

  • User Avatar
    0
    fastsoft created

    I have same problem.

    I have to AppService. When ı call service methot from angular client ı can see current user base.GetCurrentUser(). But ı call service method from another service base.GetCurrentUser() return null. Please help. thanks.

  • User Avatar
    0
    fastsoft created

    there is no one to answer? I need to solve this problem. please

  • User Avatar
    0
    aaron created
    Support Team

    Hi, can you show where you are doing that?

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @fastsoft,

    You say that when you call an app service (let's say AppService2) from another app service (let's name this AppService1), you get GetCurrentUser() as null.

    How do you call AppService1 in your application like @aaron asked ? Do you use it in a windows service, console app or web app ?

    By the way, it is not a good practice to call an app service from another app service. You can create a private method or domain service for common code parts and call it from both app services. Just a notice :).

  • User Avatar
    0
    fastsoft created

    Hi.

    Yes How can i call AppService1 in your application like @aaron asked ? I'm using web app(angular).

    For Example: ı have a PersonAppService. İt has insert,update,delete,get methodts for using clients. Same time I need to use the organizationId to which the session user belongs when I register.

    Everything is right here. I can that when ı call insert or update method from client. I can see user from base.GetCurrentUser();

    But, I have a second app service. It name is StudentService(has insert,update,delete, get methods). Student table is relasionship to person table with PersonId. When I want to save the student I will add the person first and then add the PersonId to student. So ı have to use PersonServiceApp in SetudentServiceApp. I think this way bast way for this demand.

    as a result have can i get CurrentUser when user AppService in another AppService.

    Thanks.

  • User Avatar
    0
    aaron created
    Support Team

    Can you show actual code of how you inject and use PersonAppService in UserAppService?

  • User Avatar
    0
    fastsoft created

    PersonAppService.cs

    namespace OKYS.Person.Services
    {
        public class PersonAppService : OKYSFastAppServiceBase, IPersonAppService
        {
            private readonly IRepository<VPersonInfo> _personRepository;
    
            public PersonAppService() : base()
            {
                _personRepository = new Repository<VPersonInfo>();
            }
            //Methods
            [HttpPost]
            public async Task<PagedResultDto<VPersonInfo>> GetData(FGetEntityExpression searchParams)
            {
                return await _personRepository.GetDataWithPaging(searchParams);
            }
    
            public async Task<VPersonInfo> SelectById(int pkId)
            {
                return await _personRepository.Select(pkId);
            }
    
            public async Task<VPersonInfo> Select(List<FSearchExpression> expressionList)
            {
                return await _personRepository.Select(expressionList);
            }
    
            [HttpDelete]
            public async Task<ProcessResult> DeleteById(int pkId)
            {
                return await _personRepository.Delete(pkId);
            }
    
            [HttpPost]
            public async Task<ProcessResult> Delete(VPersonInfo personInfo)
            {
                return await _personRepository.Delete(personInfo);
            }
    
            public async Task<VPersonInfo> Insert(VPersonInfo personInfo)
            {
    
                long? userId = base.AbpSession.UserId; //when called from web app userId is not null. But when ı call from StudentAppService.cs userId gets null.
    
                personInfo.OrganizationId = new OrganizationAppService().GetUserOrganizationData(userId);
    
                return await _personRepository.Insert(personInfo);
            }
    
            [HttpPost]
            public async Task<VPersonInfo> Update(VPersonInfo personInfo)
            {
                return await _personRepository.Update(personInfo);
            }
    
    
        }
    }
    

    StudentRegisterService.cs

    namespace OKYS.Student.Services
    {
        public class StudentAppService : OKYSFastAppServiceBase, IStudentAppService
        {
            private readonly IRepository<VStudentInfo> _StudentRepository;
    
            public StudentAppService() : base()
            {
                _StudentRepository = new Repository<VStudentInfo>();
            }
            //Methods
            [HttpPost]
            public async Task<PagedResultDto<VStudentInfo>> GetData(FGetEntityExpression searchParams)
            {
                return await _StudentRepository.GetDataWithPaging(searchParams);
            }
    
            public async Task<VStudentInfo> SelectById(int pkId)
            {
                return await _StudentRepository.Select(pkId);
            }
    
            public async Task<VStudentInfo> Select(List<FSearchExpression> expressionList)
            {
                return await _StudentRepository.Select(expressionList);
            }
    
            [HttpDelete]
            public async Task<ProcessResult> DeleteById(int pkId)
            {
                return await _StudentRepository.Delete(pkId);
            }
    
            [HttpPost]
            public async Task<ProcessResult> Delete(VStudentInfo StudentInfo)
            {
                return await _StudentRepository.Delete(StudentInfo);
            }
    
            public async Task<VStudentInfo> Insert(VStudentInfo StudentInfo)
            {
                return await _StudentRepository.Insert(StudentInfo);
            }
    
            [HttpPost]
            public async Task<VStudentInfo> Update(VStudentInfo StudentInfo)
            {
                return await _StudentRepository.Update(StudentInfo);
            }
    
            public async Task<ProcessResult> RegisterStudent(StudentInpuOutputDto input)
            {
                ProcessResult result = new ProcessResult(true);
    
                input.StudentPerson = await new PersonAppService().Insert(input.StudentPerson);
                input.Student.PersonId = input.StudentPerson.PersonId;
                input.Student = await new StudentAppService().Insert(input.Student);
                result.RecordID = input.Student.StudentId;
                return result;
            }
    
        }
    }
    
  • User Avatar
    0
    aaron created
    Support Team

    Use dependency injection for AbpSession to be initialized properly.

    public class StudentAppService : OKYSFastAppServiceBase, IStudentAppService
    {
        private readonly IRepository<VStudentInfo> _StudentRepository;
        private readonly IPersonAppService _PersonAppService;
    
        public StudentAppService(
            IRepository<VStudentInfo> studentRepository,
            IPersonAppService personAppService)
            : base()
        {
            _StudentRepository = studentRepository;
            _PersonAppService = personAppService;
        }
    
        public async Task<ProcessResult> RegisterStudent(StudentInpuOutputDto input)
        {
            ProcessResult result = new ProcessResult(true);
    
            input.StudentPerson = await _PersonAppService.Insert(input.StudentPerson);
            input.Student.PersonId = input.StudentPerson.PersonId;
            input.Student = await Insert(input.Student);
            result.RecordID = input.Student.StudentId;
            return result;
        }
    }
    

    Read more in ABP documentation:

    • Dependency Injection: <a class="postlink" href="https://aspnetboilerplate.com/Pages/Documents/Dependency-Injection#DocConstructorInjection">https://aspnetboilerplate.com/Pages/Doc ... rInjection</a>
  • User Avatar
    0
    fastsoft created

    thank you very much aaron. I solved problem.