Save new variant of page when the page is being sa...
# help-with-umbraco
b
I'm trying to implement a functionality in which I automatically set some fields for a different language based on what is entered for the published language. When I'm saving a page I use a NotificationHandler and set the fields in a new culture based on the input. However, whenever I save the page I get database write lock errors, even though I'm using a IScopedProvider. Is anyone familiair with this or has someone perhaps done something similar before? I can't seem to get rid of the write locks
j
Will be easier to help if you include the code you wrote 🙂
b
Thanks for your reply! This is the code, there is a lot of logic going on here so i've abbreviated it a bit. To clarify: this will actually work (i.e. all code is run), however, the regular publish call in Umbraco will throw an error because of a database lock so the new version still won't exist.
Copy code
public async Task HandleAsync(ContentPublishedNotification notification, CancellationToken cancellationToken)
  {
        foreach (var content in notification.PublishedEntities)
        {
            if (content.ContentType.VariesByCulture())
            {
                var allLanguages = _localizationService.GetAllLanguages();
                var allCultures = allLanguages.Select(l => l.IsoCode).ToList();
                var currentCulture = content.CultureInfos?.Values.FirstOrDefault()?.Culture;

                foreach (var culture in allCultures)
                {
                    // do logic for each

                    CreateNewVersion()
                }
            }
        }
  }
And the function CreateNewVersion:
Copy code
private void CreateNewCultureVersion(IContent content, string culture, Dictionary<string, string> newValues)
    {
        using (var scope = _scopeProvider.CreateScope())
        {

            try
            {

                // Retrieve existing content in the target culture, if it exists
                var existingContent = _contentService.GetById(content.Id);
                if (existingContent == null)
                {
                    // Handle case where content does not exist
                    return;
                }

                // Update properties with altered versions
                foreach (var property in existingContent.Properties)
                {  
                  existingContent.SetValue(property.Alias, newValues[property.Alias], culture);   
                }

                // Save the updated content for the target culture
                _contentService.Save(existingContent);
                scope.Complete();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Could not create new page variant");
                throw;
            }
        }
    }
j
I often get the database scope issues when mixing async methods and the Umbraco services - I know you said you slimmed it down, but are you sure your HandleAsync method needs to be async?
b
another thing that could potentially help, is right now you go through each culture, and change/save the node for each culture. However on an
IContent
you can potentially just make the changes for all languages, and do 1 save operation instead of however many cultures you have. It would speed up the handler, and potentially you would have less points of failure for DB locks as well.
b
Perhaps i should try and make it not async. I'm doing an API call in the omitted parts, hence the async
Thanks! I'll definitely try that. I'm also thinking of perhaps not using the published event but instead going for the saving event, perhaps something is breaking because the save operation has already executed
j
You have to be careful if switching to a save event as you also save through the notification. You can easily end up hitting the notification, performing a save within it that triggers a new notification which triggers a save, and on and on.. In that case you probably want to suppress raising notifications: https://docs.umbraco.com/umbraco-cms/reference/notifications/contentservice-notifications#what-happened-to-raiseeventmethod-parameters
b
I've rewritten everything to now use the ContentSaving notification, i had some struggles before i figured out that it is a requirement to set the CultureName using
IContent.SetCultureName(string value, string culture)
but now i've created a new version of my page! Thanks a lot for the help
7 Views