Base solution for your next web application

Activities of "mcmaestro"

Hello,

We have decided to take our login/page and make it more angular. However when we did this we noticed some weird responses from the server whenever we are trying to make API calls from the login page. For example, we submit the login details(using $http.post) and the server would response with an html page not a jsonresult as we expect from the action. When we login successfully, we will 302 response from the api call.

We are using MVC with angular

Here is the Login Action controller we are trying to call:

[HttpPost]
        [UnitOfWork]
        [DisableAuditing] 
        [DontWrapResult]
        public virtual async Task<JsonResult> Login(LoginViewModel loginModel, string returnUrl = "", string returnUrlHash = "", string service= "", string serviceReturnUrl = "")
        {
            CheckModelState();

            if (loginModel.LogIntoHost)
            {
                loginModel.TenancyName = null;
            }

            _unitOfWorkManager.Current.DisableFilter(AbpDataFilters.MayHaveTenant);

            var loginResult = await GetLoginResultAsync(loginModel.UsernameOrEmailAddress, loginModel.Password, loginModel.TenancyName);

            if (loginResult.User.ShouldChangePasswordOnNextLogin)
            {
                loginResult.User.SetNewPasswordResetCode();

                return Json(new AjaxResponse
                {
                    TargetUrl = Url.Action(
                        "ResetPassword",
                        new ResetPasswordViewModel
                        {
                            UserId = SimpleStringCipherProvider.Encrypt(loginResult.User.Id.ToString()),
                            ResetCode = loginResult.User.PasswordResetCode
                        })
                });
            }

            await SignInAsync(loginResult.User, loginResult.Identity, loginModel.RememberMe);

            var userRoles = await _userManager.GetRolesAsync(loginResult.User.Id);
            try
            {
                var token = await _ssoManager.Login(loginResult.User, loginResult.Tenant.Id, string.Join(",", userRoles));
                await _cacheManager.GetCache<string, string>(string.Format("{0}{1}UserSSO", loginResult.User.Id, loginResult.Tenant.Id)).SetAsync("token", token);                

                if (!service.IsNullOrEmpty() && returnUrl.Contains("http"))
                {
                    var appendQuery = returnUrl.Contains("?") ? string.Format("&authToken={0}&returnUrl={1}", token, serviceReturnUrl) : string.Format("?authToken={0}&returnUrl={1}", token, serviceReturnUrl);
                    returnUrl = returnUrl + appendQuery;

                    returnUrl = Url.Action("SSO", "Application", new { returnUrl = returnUrl });
                }
            }
            catch(Exception exp)
            {
                _logger.Error("Error Logging into SSO Server", exp);
            }

            if (string.IsNullOrWhiteSpace(returnUrl))
            {
                returnUrl = Url.Action("Index", "Application");
            }

            if (!string.IsNullOrWhiteSpace(returnUrlHash))
            {
                returnUrl = returnUrl + returnUrlHash;
            }            

            return Json(new AjaxResponse { TargetUrl = returnUrl });
        }

Here is the login js call

var CurrentPage = function () {

    var handleLogin = function () {

        var $loginForm = $('.login-form');

        $loginForm.validate({
            errorElement: 'span', //default input error message container
            errorClass: 'help-block', // default input error message class
            focusInvalid: false, // do not focus the last invalid input
            rules: {
                username: {
                    required: true
                },
                password: {
                    required: true
                }
            },

            invalidHandler: function (event, validator) {
                $loginForm.find('.alert-danger').show();
            },

            highlight: function (element) {
                $(element).closest('.form-group').addClass('has-error');
            },

            success: function (label) {
                label.closest('.form-group').removeClass('has-error');
                label.remove();
            },

            errorPlacement: function (error, element) {
                error.insertAfter(element.closest('.input-icon'));
            },

            submitHandler: function (form) {
                $loginForm.find('.alert-danger').hide();
            }
        });

        $loginForm.find('input').keypress(function (e) {
            if (e.which == 13) {
                if ($('.login-form').valid()) {
                    $('.login-form').submit();
                }
                return false;
            }
        });

        $loginForm.submit(function (e) {
            e.preventDefault();

            if (!$('.login-form').valid()) {
                return;
            }

            abp.ui.setBusy(
                $('.login-form'),
                abp.ajax({
                    contentType: app.consts.contentTypes.formUrlencoded,
                    url: $loginForm.attr('action'),
                    data: $loginForm.serialize()
                }).done(function (response) {
                    console.log('response: ', typeof response);
                })
            );
        });

        $('a.social-login-icon').click(function() {
            var $a = $(this);
            var $form = $a.closest('form');
            $form.find('input[name=provider]').val($a.attr('data-provider'));
            $form.submit();
        });

        $loginForm.find('input[name=returnUrlHash]').val(location.hash);

        $('input[type=text]').first().focus();
    }

    return {
        init: function () {
            handleLogin();
        }
    };

}();

We have tenant users that will need to login and have another filter that filters all of the "companies" they are allowed to access.

I have seen examples of the data filter boilerplate uses work for a specific value but not for a range and I want to know if it is possible.

Question

I need to extend the AbpSession to keep up with a value that I can use through out the system. We have an another level the user can fall into. (lets say a Company) so when the user logs in under a company I want to save that information in the AbpSessions so I can apply filters to based on that value.

Is there a way I can add that field to the ABPSession object?

Question

I may be missing something but I have a few long running processes that are failing to complete because the transaction is timing out.

I have tried to set the transaction timeout to an extremely large number but it always fails after ten minutes regardless.

Here is the error message I receive after letting the process run longer than ten minutes.

System.AggregateException

One or more errors occurred.

System.AggregateException: One or more errors occurred. ---> Hangfire.BackgroundJobClientException: Background job creation failed. See inner exception for details. ---> System.Transactions.TransactionException: The operation is not valid for the state of the transaction. ---> System.TimeoutException: Transaction Timeout
   --- End of inner exception stack trace ---
   at System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction, Guid promoterType)
   at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Guid promoterType)
   at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification)
   at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
   at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.Open()
   at Hangfire.SqlServer.SqlServerStorage.CreateAndOpenConnection()
   at Hangfire.SqlServer.SqlServerStorage.UseConnection[T](Func`2 func)
   at Hangfire.SqlServer.SqlServerConnection.CreateExpiredJob(Job job, IDictionary`2 parameters, DateTime createdAt, TimeSpan expireIn)
   at Hangfire.Client.CoreBackgroundJobFactory.Create(CreateContext context)
   at Hangfire.Client.BackgroundJobFactory.&lt;&gt;c__DisplayClass7_0.&lt;CreateWithFilters&gt;b__0()
   at Hangfire.Client.BackgroundJobFactory.InvokeClientFilter(IClientFilter filter, CreatingContext preContext, Func`1 continuation)
   at Hangfire.Client.BackgroundJobFactory.Create(CreateContext context)
   at Hangfire.BackgroundJobClient.Create(Job job, IState state)
   --- End of inner exception stack trace ---
   at Hangfire.BackgroundJobClient.Create(Job job, IState state)
   at Abp.Hangfire.HangfireBackgroundJobManager.EnqueueAsync[TJob,TArgs](TArgs args, BackgroundJobPriority priority, Nullable`1 delay)
   at NMI.SmartMarketBusiness.MarketServices.MarketServiceExportBackgroundJob.&lt;&gt;c__DisplayClass10_1.&lt;&lt;Execute&gt;b__3>d.MoveNext()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at NMI.SmartMarketBusiness.MarketServices.MarketServiceExportBackgroundJob.Execute(MarketServiceExportBackgroundJobArgs args)
---> (Inner Exception #0) Hangfire.BackgroundJobClientException: Background job creation failed. See inner exception for details. ---> System.Transactions.TransactionException: The operation is not valid for the state of the transaction. ---> System.TimeoutException: Transaction Timeout
   --- End of inner exception stack trace ---
   at System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction, Guid promoterType)
   at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Guid promoterType)
   at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification)
   at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
   at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.Open()
   at Hangfire.SqlServer.SqlServerStorage.CreateAndOpenConnection()
   at Hangfire.SqlServer.SqlServerStorage.UseConnection[T](Func`2 func)
   at Hangfire.SqlServer.SqlServerConnection.CreateExpiredJob(Job job, IDictionary`2 parameters, DateTime createdAt, TimeSpan expireIn)
   at Hangfire.Client.CoreBackgroundJobFactory.Create(CreateContext context)
   at Hangfire.Client.BackgroundJobFactory.<>c__DisplayClass7_0.<CreateWithFilters>b__0()
   at Hangfire.Client.BackgroundJobFactory.InvokeClientFilter(IClientFilter filter, CreatingContext preContext, Func`1 continuation)
   at Hangfire.Client.BackgroundJobFactory.Create(CreateContext context)
   at Hangfire.BackgroundJobClient.Create(Job job, IState state)
   --- End of inner exception stack trace ---
   at Hangfire.BackgroundJobClient.Create(Job job, IState state)
   at Abp.Hangfire.HangfireBackgroundJobManager.EnqueueAsync[TJob,TArgs](TArgs args, BackgroundJobPriority priority, Nullable`1 delay)

Hello all,

We are developing multiple applications that are use the boilerplate but I would like for the user to be able to have one login and be able to login or use a service from a different applications.

Kind of like google login process for it's services.

Any help would be great!

Thanks,

For some reason when I try to delete an entity object it will not actually delete from the database.

For Example here is my Application Service TemplateAppService, I have a method that called DeleteTemplate and after it runs successfully, I know in the database that the record is not actually delete.

I have even tried to run SaveChanges method manually.

Any help would be appreciated.

Thanks,

public class TemplateAppService : KameleonAppServiceBase, ITemplateAppService
    {
        private readonly IRepository<Template, long> _templateRepository;
        private readonly IRepository<TemplateStatus> _templateStatusRepository;
        private readonly IRepository<TemplateCategory> _templateCategoryRepository;
        private readonly ISvgCreativeAppService _svgCreativeAppService;

        public TemplateAppService(IRepository<Template, long> templateRepository, ISvgCreativeAppService svgCreativeAppService, IRepository<TemplateStatus> templateStatusRepository, IRepository<TemplateCategory> templateCategoryRepository)
        {
            _templateRepository = templateRepository;
            _svgCreativeAppService = svgCreativeAppService;
            _templateStatusRepository = templateStatusRepository;
            _templateCategoryRepository = templateCategoryRepository;
        }

        public async Task<long> CreateTemplate(TemplateInput input)
        {
            var template = new Template();

            input.MapTo(template);

           var id  =  await _templateRepository.InsertAndGetIdAsync(template);

          
               await _svgCreativeAppService.CreateSvgCreative(
                      new SvgCreativeInput
                      {
                          Name = template.Name,
                          TemplateId = id,
                          BaseProductId = input.BaseProductId
                      }
                  );

               await CurrentUnitOfWork.SaveChangesAsync();          

           return id;
        }

        public async Task UpdateTemplate(TemplateInput input)
        {
            var template = await _templateRepository.GetAsync(input.Id);

            if (template == null)
            {
                throw new UserFriendlyException("Product Service Not Found!");
            }

            input.MapTo(template);

            await _templateRepository.UpdateAsync(template);
        }

        public async Task DeleteTemplate(EntityRequestInput<long> input)
        {
            var template = await _templateRepository.GetAsync(input.Id);

            if (template == null)
            {
                throw new UserFriendlyException("Template not found!");
            }

            await _templateRepository.DeleteAsync(template);

            await CurrentUnitOfWork.SaveChangesAsync();
        }

        public async Task<int> CreateTemplateStatus(TemplateStatusInput input)
        {
            var templatestatus = new TemplateStatus();
            
            input.MapTo(templatestatus);

            return await _templateStatusRepository.InsertAndGetIdAsync(templatestatus);

          
        }

        public async Task UpdateTemplateStatus(TemplateStatusInput input)
        {
            var templatestatus = await _templateStatusRepository.GetAsync(input.Id);

            if (templatestatus == null)
            {
                throw new UserFriendlyException("Template Status Not Found!");
            }

            input.MapTo(templatestatus);

            await _templateStatusRepository.UpdateAsync(templatestatus);
        }

        public async Task DeleteTemplateStatus(EntityRequestInput input)
        {
            var templatestatus = await _templateStatusRepository.GetAsync(input.Id);

            if (templatestatus == null)
            {
                throw new UserFriendlyException("Template Status not found!");
            }

            await _templateStatusRepository.DeleteAsync(templatestatus);

            CurrentUnitOfWork.SaveChanges();
        }       
        
        public async Task<TemplateOutput> GetTemplate(EntityRequestInput<long> input)
        {
            var template = await _templateRepository.GetAsync(input.Id);

            if (template == null)
            {
                throw new UserFriendlyException("Template not found!");
            }

            var result = new TemplateOutput();

            template.MapTo(result);

            return result;            
        } 

        public async Task<int> CreateTemplateCategory(TemplateCategoryInput input)
        {
            var templatecategory = new TemplateCategory();

            input.MapTo(templatecategory);

            return await _templateCategoryRepository.InsertAndGetIdAsync(templatecategory);
        }

        public async Task UpdateTemplateCategory(TemplateCategoryInput input)
        {
            var templatecategory = await _templateCategoryRepository.GetAsync(input.Id);

            if (templatecategory == null)
            {
                throw new UserFriendlyException("Template Category Not Found!");
            }

            input.MapTo(templatecategory);

            await _templateCategoryRepository.UpdateAsync(templatecategory);
        }

        public async Task DeleteTemplateCategory(EntityRequestInput input)
        {
            var templatecategory = await _templateCategoryRepository.GetAsync(input.Id);

            if (templatecategory == null)
            {
                throw new UserFriendlyException("Template Category not found!");
            }          

            await _templateCategoryRepository.DeleteAsync(templatecategory);

            await CurrentUnitOfWork.SaveChangesAsync();
        }


        public async Task<TemplateListOutput> GetTemplates(TemplateListInput input)
        {
            var results = await _templateRepository.GetAll().WhereIf(!input.SearchedName.IsNullOrEmpty(), p => p.Name.Contains(input.SearchedName)).OrderBy(x => x.Name)
                            .Skip(input.SkipCount * input.MaxResultCount).Take(input.MaxResultCount).ToListAsync();



            return new TemplateListOutput { Templates = Mapper.Map<List<TemplateOutput>>(results) };
        }

        public async Task<TemplateStatusListOutput> GetTemplatesStatuses(TemplateStatusListInput input)
        {
            var results = await _templateStatusRepository.GetAll().WhereIf(!input.SearchedName.IsNullOrEmpty(), p => p.Name.Contains(input.SearchedName)).OrderBy(x=> x.Name)
                            .Skip(input.SkipCount * input.MaxResultCount).Take(input.MaxResultCount).ToListAsync();



            return new TemplateStatusListOutput { TemplateStatuses = Mapper.Map<List<TemplateStatusOutput>>(results) };
        }

        public async Task<TemplateCategoryListOutput> GetTemplateCategories(TemplateCategoryListInput input)
        {
            var results = await _templateCategoryRepository.GetAll().WhereIf(!input.SearchedName.IsNullOrEmpty(), p => p.Category.Name.Contains(input.SearchedName)).WhereIf(!input.TemplateIdFilter.HasValue, y=> y.TemplateId == input.TemplateIdFilter.Value).OrderBy(x => x.Id)
                            .Skip(input.SkipCount * input.MaxResultCount).Take(input.MaxResultCount).ToListAsync();



            return new TemplateCategoryListOutput { TemplateCategories = Mapper.Map<List<TemplateCategoryOutput>>(results) };
        }
    }

First off, I want to say this framework has saved me hours of development time and I have only been using this for 3 weeks. I have ran into a little issue and I hope you guys can help me out. Most of my application is going to be using the entity framework for database information, however, there is a module that we are building that will work with MongoDB or DocumentsDB to store all the session information. I want to build a custom repository but I am confused as to how to set this up do I need to add a class to the solution and reference the IRepository interface and fill in the concrete methods for accessing the information in the no sql database. Should I build a separate dll entirely?

Thanks!

Showing 1 to 7 of 7 entries