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

Activities of "marble68"

My MVC dev environment is pointed at https://mvc. My Public dev environment is pointed at https://public

I did this to avoid cookie authentication cross contamination.

In dev, I'm doing this, and it works. However, this does NOT work in production.

using Abp.Domain.Repositories;
using okto.work.Survey;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Abp.Domain.Uow;
using Hangfire.Annotations;

namespace okto.work.Web.Survey
{
    public class EmployeeTakeManager : workDomainServiceBase, IEmployeeTakeManager
    {
        private readonly IRepository<Employee, Guid> _employeeRepository;
        private readonly IRepository<Department, Guid> _departmentRepository;
        private readonly IRepository<SurveyScript, Guid> _surveryscriptRepository;

        public EmployeeTakeManager(
            IRepository<Employee, Guid> employeeRepository, 
            IRepository<Department, Guid> departmentRepository,
            IRepository<SurveyScript, Guid> surveryscriptRepository
            )
        {
            _employeeRepository = employeeRepository;
            _departmentRepository = departmentRepository;
            _surveryscriptRepository = surveryscriptRepository;
        }

        [UnitOfWork]
        public async Task<Employee> GetEmployeeForTakeAsync(Guid id)
        {
            Logger.Debug($"TakeManager GetEmployeeForTakeAsync {id}");

            Employee employee;
            using (var uow = UnitOfWorkManager.Begin())
            {
                using (CurrentUnitOfWork.SetTenantId(null))
                {
                    using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.MayHaveTenant))
                    {

                        try
                        {
                            Logger.Debug($"TakeManager _employeeRepository.GetAsync(id) {id}");

                            employee = await _employeeRepository.GetAsync(id);
                        }
                        catch (Exception ex)
                        {

                            throw ex;
                        }


                        uow.Complete();
                    }
                }
            }
            return employee;
        }
    }
}

Connections all work - everything is connecting.

I have my environment variable set to Production.

In my TakeController, I'm doing:

                Employee employee;
                employee = (await _employeeTakeManager.GetEmployeeForTakeAsync(_id));

Any ideas?

I think my issue is related to trying to get an entity across tenants from the public website.

Because they have differnet URLs, it was breaking in production (admin.domain.com vs domain.com).

In dev, they were both localhost.

To recreate, I added two host entries for localhost (mvc & public) - and modified settings to use those urls in development.

The result allowed me to recreate the problem in dev.

I've now made a Take Manager, and from there, call the original service

The only way I've gotten this to work is by modifying my EmployeeTakeService to expose custom methods, and set Tenant id to null and to clear the filter of MayHaveTenant.

Only in this circumstance am I able to get to an entity, regardless of Tenant.

But per your answer, I should not do this, correct?

It turns out I didn't have this working - the public website was getting the MVC cookie.

I added a host entry for the public website so it's a different domain, and it now fails.

Attempt to create a domain service, I've added a Manager to the web.core project.

Here is my EmployeeTakeManager.cs:

using Abp.Domain.Repositories;
using okto.work.Survey;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace okto.work.Web.Survey
{
    public class EmployeeTakeManager : workDomainServiceBase, IEmployeeTakeManager
    {
        private readonly IRepository<Employee, Guid> _employeeRepository;

        public EmployeeTakeManager(IRepository<Employee, Guid> employeeRepository)
        {
            _employeeRepository = employeeRepository;
        }

        public async Task<Employee> GetEmployeeForTakeAsync(Guid id)
        {
            var employee = await _employeeRepository.GetAsync(id);
            return employee;
        }

        Task IEmployeeTakeManager.UpdateEmployeeForTake()
        {
            throw new NotImplementedException();
        }
    }
}

My IEmployeeTakeManager.cs:

using System;
using System.Collections.Generic;
using System.Text;
using Abp;
using Abp.Domain.Services;
using System.Threading.Tasks;
using okto.work.Survey;

namespace okto.work.Web.Survey
{
    public interface IEmployeeTakeManager : IDomainService
    {
        Task<Employee> GetEmployeeForTakeAsync(Guid id);

        Task UpdateEmployeeForTake();

    }
}

My goal is to get a user by ID (Guid) from the repository.

I've been able to recreate this in dev by adding a localhost file entry for my public site.

Am I correct that it is not finding the entity because it belongs to Tenant 1, and since I'm requesting it from the public website, there is no tenant? Am I gorrect that using the EmployeeRepository, it is going to check the request to determine the tenant making the request?

I am attempted to load an entity, regardles of tenant, to provide content for that entity, and update it based on response. Using GUIDs, I'm ensured the IDs are unique (and can accomodate multiple database GUID conflicts if necessary).

Will a domain service even work?

I'm trying to create a domain service.

I created a new application service in Applications project, called EmployeeTakeAppService, and for testing have not put any authentication on the methods.

I duplicated the IEmployeesTakeAppService and inherit from that for my EmployeeTakeAppService. I don't wish to have a delete method there.

It still doesn't find the entity in the database.

So, what I did did not work.

If I create a domain service - do I put this in the Shared project?

My goal is, from the TakeController, with the GUID id passed in the URL, get an employee to determine the last time they took a survey. From that, I determine their department. From that, I retreive that Department's employee survey.

The employee takes the survey.

The answers are posted back, and the results of the survey are processed, and the Employee entity is updated with when they took the survey.

If the Employee refreshes the page, they are shown that they've taken the survey and cannot take it again (until the results expire).

My multi-tenant solution allows companies to put their employees in the database, under their tenant instance, and ask them to complete surveys.

The URL for the employees is not tenant specific; but it a url generated that is specific to the Employee. All employees, regardless of tenant, are sent to the public website.

This is why I need to start with the employee to determine the department, to determine which survey to send them.

Thanks for your help, and I appologize for asking for help with my difficulty in implementing this likely simple thing.

ismcagdas - I've reviewed the documentation on creating a domain service.

Are you saying I should take the code from the controller where I use DTOs, move that to my custom service, and only return the entity?

However, in production, it does not get an entity even though the GUID for the entity is valid.

I added some debug logging and it is successfully pulling the id (guid) and parsing it.

when it tries to pull the entity by ID (regardless of Tenant) - it fails.

EmployeeDto employee = (await _employeesAppService.GetEmployeeForView(_id)).Employee;

Demirmusa - this is how I get the entity in the controller without issue (in development)


    public async Task<ActionResult> Index(string id)
        {
            Logger.Debug($"TakeController Index id: {id}");


            if (Guid.TryParse(id, out Guid _id))
            {
                Logger.Debug($"TakeController {id} parsed");
                // We get the taker, determine which tenant
                EmployeeDto employee = (await _employeesAppService.GetEmployeeForView(_id)).Employee;
                int TenantId = employee.TenantId;
                ViewBag.takerId = employee.Id;

                ViewBag.isclear = employee.isclear;
                if (employee.isclear)
                {
                    Logger.Debug($"TakeController {id} clear");
                    ViewBag.Takername = employee.firstName + " " + employee.lastName;
                    ViewBag.takerExpires = employee.dateClearExpires;
                    ViewBag.takerDateCleared = employee.dateCleared;
                    ViewBag.takerDateLastSurvey = employee.dateLastSurvey;

                }
                else
                {
                    Logger.Debug($"TakeController {id} not clear");
                    // then the active survey for that Tenant
                    GetAllDepartmentsInput input = new GetAllDepartmentsInput();
                    input.activeFilter = 1;
                    input.MaxResultCount = 1;
                    List<GetDepartmentForViewDto> s = _departmentsAppService.GetAll(input).Result.Items.ToList();
                    // No active list - bail.
                    if (s.Count < 1) return RedirectToAction("/");
                    
                    DepartmentDto cs = s.FirstOrDefault().Department;
                    ExpiresInDays = 7;
                    string surveyScriptID = cs.SurveyScriptId.ToString();
                    Logger.Debug($"TakeController {id} survey id {surveyScriptID}");

                    if (Guid.TryParse(surveyScriptID, out Guid _csid))
                    {
                        //    // then the survey itself
                        GetSurveyScriptForViewDto surveyScriptDTO = _surveyscriptssAppService.GetSurveyScriptForView(_csid).Result;
                        SurveyScriptDto surveyScript = surveyScriptDTO.SurveyScript;
                        Logger.Debug($"TakeController {id} survey id {surveyScriptID} retrieved");
                        Logger.Debug($"TakeController {id} survey id {surveyScriptID} lenth: {surveyScript.surveyscript.Length}");

                        var _surveyScript = surveyScript.surveyscript;
                        SurveyObject = JObject.Parse(_surveyScript);
                        //    // then the json and get that ID - send it down
                        ViewBag.surveyscript = SurveyObject;
                        Logger.Debug($"TakeController {id} survey id {surveyScriptID} Set To Viewbag");

                    }
                }
                return View();

            }

            return Redirect("~/");
        }

Showing 131 to 140 of 170 entries