Hello Baslessi75,
You cannot use any functions which use the localtime of the machine, because when deploying to the cloud this could be different. I have personally witnessed this issue with my own projects too.
In general the guideline is that you manage everything in UTC until it is displayed to the user. This means using Javascript to detect the users timezone in the browser https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
There is a Blazor library that can also take care of this for you. https://github.com/dustout/BlazorTime
Could you show your code please?
For better performance I can answer.
There is a concept of access patterns and it is especially important for any kind of lists of data you are displaying. Lists of data, for the large use case, should have the data itself clustered together on the database disk. This means having the clustered index (usually the primary key, but it can be changed) of one that is (TenantId, Id) which will force all data to be togethered on disk.
However, the other issue will be joins. If any of the data you are retrieving in the list requires data from other tables, it will be retrieving the data for each item in the list in the other tables one by one. So Ideally all of the data in the other tables that may be joined, is also physically close together - which means clustered on something related to the top level entity you are trying to list. TenantId may be enough is most cases, but if it is not an aggregate root, then perhaps something based on the FK to the top level entitiy.
I recommend you instead do this in a normal API controller instead of an App service as you want to return a file rather than some wrapped ajax/json response - which is what the dynamic API part of ABP will do with the AppServices.
Here is an example returning and ICS file.
[HttpGet]
[AllowAnonymous]
public FileResult ICS(Guid id)
{
var appointment = _attendanceRepo.GetAllIncluding(c => c.CalendarEvent, d => d.CalendarEvent.OwnerCalendar.Owner).First(d => d.Id == id);
string output = $"BEGIN:VCALENDAR" + rt +
$"VERSION:2.0" + rt +
$"BEGIN:VEVENT" + rt +
$"UID: calendr-" + appointment.Id + rt +
$"DTSTART:" + string.Format("{0:yyyyMMddTHHmmssZ}", appointment.CalendarEvent.Start) + rt +
$"DTEND:" + string.Format("{0:yyyyMMddTHHmmssZ}", appointment.CalendarEvent.End) + rt +
$"SUMMARY:" + appointment.CalendarEvent.EventName + " with " + appointment.CalendarEvent.OwnerCalendar.Owner.FullName + rt +
$"LOCATION:" + appointment.CalendarEvent.Location + rt +
$"END:VEVENT" + rt +
$"END:VCALENDAR" + rt
;
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new MemoryStream(Encoding.UTF8.GetBytes(output ?? ""));
result.Content = new StreamContent(stream);
return File(stream, "text/ics", fileDownloadName: appointment.CalendarEvent.EventName + ".ics");
}
@sraman, I think what you mean is to customize the "features" availablef or a tenant and then have only the features that are enabled to be displayed on the menu. Is this correct?