private async Task ValidateAndSetDefaultsAsync()
        {
            //Check https://www.bricelam.net/2016/12/13/validation-in-efcore.html
            var entities = from e in ChangeTracker.Entries()
                           where e.State == EntityState.Added ||
                           e.State == EntityState.Modified
                           select e.Entity;
            string ipAddresses      = String.Empty;
            string assemblyFullName = String.Empty;
            string rowCretionUser   = String.Empty;

            if (entities.Any(p => p is IOriginatorInfo))
            {
                ipAddresses      = String.Join(",", await IpAddressProvider.GetCurrentHostIPv4AddressesAsync());
                assemblyFullName = System.Reflection.Assembly.GetEntryAssembly().FullName;
                rowCretionUser   = this.CurrentUserProvider.GetUsername();
            }
            foreach (var entity in entities)
            {
                if (entity is IOriginatorInfo)
                {
                    IOriginatorInfo entityWithOriginator = entity as IOriginatorInfo;
                    if (String.IsNullOrWhiteSpace(entityWithOriginator.SourceApplication))
                    {
                        entityWithOriginator.SourceApplication = assemblyFullName;
                    }
                    if (String.IsNullOrWhiteSpace(entityWithOriginator.OriginatorIpaddress))
                    {
                        entityWithOriginator.OriginatorIpaddress = ipAddresses;
                    }
                    if (entityWithOriginator.RowCreationDateTime == DateTimeOffset.MinValue)
                    {
                        entityWithOriginator.RowCreationDateTime = DateTimeOffset.UtcNow;
                    }
                    if (String.IsNullOrWhiteSpace(entityWithOriginator.RowCreationUser))
                    {
                        entityWithOriginator.RowCreationUser = rowCretionUser;
                    }
                }
                var validationContext = new ValidationContext(entity);
                Validator.ValidateObject(
                    entity,
                    validationContext,
                    validateAllProperties: true);
            }
        }
        public async Task <VisitorTracking> TrackVisitAsync(VisitorTrackingModel visitorTrackingModel)
        {
            try
            {
                var httpContext     = HttpContextAccessor.HttpContext;
                var remoteIpAddress = httpContext.Connection.RemoteIpAddress.ToString();
                if (remoteIpAddress == "::1")
                {
                    var ipAddresses = await IpAddressProvider.GetCurrentHostIPv4AddressesAsync();

                    remoteIpAddress = ipAddresses.First();
                }
                var parsedIpAddress   = System.Net.IPAddress.Parse(remoteIpAddress);
                var ipGeoLocationInfo = await IpDataService.GetIpGeoLocationInfoAsync(ipAddress : parsedIpAddress);

                //var ipGeoLocationInfo = await IpStackService.GetIpGeoLocationInfoAsync(ipAddress: parsedIpAddress);
                string          country    = ipGeoLocationInfo.country_name;
                var             host       = httpContext.Request.Host.Value;
                var             userAgent  = httpContext.Request.Headers["User-Agent"].First();
                ApplicationUser userEntity = null;
                if (!String.IsNullOrWhiteSpace(visitorTrackingModel.UserAzureAdB2cObjectId))
                {
                    userEntity = await this.FairplaytubeDatabaseContext.ApplicationUser.SingleOrDefaultAsync(p => p.AzureAdB2cobjectId.ToString() == visitorTrackingModel.UserAzureAdB2cObjectId);
                }
                var visitedPage = new DataAccess.Models.VisitorTracking()
                {
                    ApplicationUserId = userEntity?.ApplicationUserId,
                    Country           = country,
                    Host            = host,
                    RemoteIpAddress = remoteIpAddress,
                    UserAgent       = userAgent,
                    VisitDateTime   = DateTimeOffset.UtcNow,
                    VisitedUrl      = visitorTrackingModel.VisitedUrl,
                    SessionId       = visitorTrackingModel.SessionId
                };
                await this.FairplaytubeDatabaseContext.VisitorTracking.AddAsync(visitedPage);

                await this.FairplaytubeDatabaseContext.SaveChangesAsync();

                var pageUri     = new Uri(visitedPage.VisitedUrl);
                var lastSegment = pageUri.Segments.Last().TrimEnd('/');
                if (!String.IsNullOrWhiteSpace(lastSegment))
                {
                    var videoInfoEntity = await this.FairplaytubeDatabaseContext.VideoInfo.SingleOrDefaultAsync(p => p.VideoId == lastSegment);

                    if (videoInfoEntity != null)
                    {
                        visitedPage.VideoInfoId = videoInfoEntity.VideoInfoId;
                        await this.FairplaytubeDatabaseContext.SaveChangesAsync();
                    }
                }
                return(visitedPage);
            }
            catch (Exception ex)
            {
                try
                {
                    await this.FairplaytubeDatabaseContext.ErrorLog.AddAsync(new ErrorLog()
                    {
                        FullException = ex.ToString(),
                        Message       = ex.Message,
                        StackTrace    = ex.StackTrace
                    });

                    await this.FairplaytubeDatabaseContext.SaveChangesAsync();
                }
                catch (Exception)
                {
                    throw;
                }
            }
            return(null);
        }