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("~/");
}
No, that did not work resolve the issue.
I refactors my async call to use await instead of .Result, yet that did not address issue. I'm working to add more logging to determine what's failing.
I see - so, for the public website to be able to retreive entities I should bypass the MVC site altogether?
Deploying to production now.
Yes - the employee entity is multi-tenant.
thabk you - i will try that