volume_up

A critical vulnerability was discovered in React Server Components (Next.js). Our systems remain protected but we advise to update packages to newest version. Learn More

volume_up

A critical vulnerability was discovered in React Server Components (Next.js). Our systems remain protected but we advise to update packages to newest version. Learn More

Modifying existing name URL generation?

Hi!

If I create a product in the CMS with an already existing name the resulting URL becomes something like "existing-name-e1a22eda" where "e1a22eda" part is dynamically generated.

How would I go about modifying the logic behind the url generation? If I instead would like the resulting url to be "existing-name-1" and if I add yet another it becomes "existing-name-2" etc.?


#227921
Edited, Sep 16, 2020 11:31

Have a look at: 

IUrlSegmentGenerator

https://world.episerver.com/CsClassLibraries/cms/EPiServer.Web.IUrlSegmentGenerator?version=11

I think you will have to handle duplicates yourself. Something like this:

var urlSegmentGenerator = ServiceLocator.Current.GetInstance<IUrlSegmentGenerator>();
var generatedUrlSegment = urlSegmentGenerator.Create("existing-name");

// Handle duplicate URL-segments among siblings
var contentLoader = ServiceLocator.Current.GetInstance<IContentLoeader>();
var contentWithSameUrlSegment = contentLoader.GetBySegment(ParentLink, generatedUrlSegment, Language);
var suffix = 1;
while (contentWithSameUrlSegment != null && contentWithSameUrlSegment.ContentLink.ID != ContentLink.ID)
{
   generatedUrlSegment = generatedUrlSegment + suffix++;
   contentWithSameUrlSegment = contentLoader.GetBySegment(ParentLink, URLSegment, Language);
}

If possible, use constructor injection instead of servicelocator.

#227923
Edited, Sep 16, 2020 11:50

Hi Frans,

You can modify the product's content route segment on the CreatedContent event similar to below e.g.

Note: You need to pass your product variation type instead of the ShirtVartion type.

    [InitializableModule]
    [ModuleDependency(typeof(EPiServer.Commerce.Initialization.InitializationModule))]
    public class UpdateCatalogRouteSegmentInitializationModule : IInitializableModule
    {
        private IContentEvents _contentEvents;

        public void Initialize(InitializationEngine context)
        {
            if (_contentEvents == null)
            {
                _contentEvents = ServiceLocator.Current.GetInstance<IContentEvents>();
            }

            _contentEvents.CreatedContent += ContentEvents_CreatedContent;
        }

        private void ContentEvents_CreatedContent(object sender, ContentEventArgs e)
        {
            var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
            
            if (contentLoader.Get<ShirtVariation>(e.ContentLink).CreateWritableClone() is ShirtVariation
                generatedVariation)
            {
                var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
                var suffix = generatedVariation.RouteSegment.Split('-')?.LastOrDefault();
                var newSegment = suffix != null ? generatedVariation.RouteSegment.Replace(suffix, "") : generatedVariation.RouteSegment;

                var count = 1;
                if (suffix != null && int.TryParse(suffix, out int num))
                {
                    count = num + 1;
                }
                
                generatedVariation.RouteSegment = newSegment + count;
                contentRepository.Save(generatedVariation, SaveAction.Publish, AccessLevel.NoAccess);
            }
        }

        public void Uninitialize(InitializationEngine context)
        {
            if (_contentEvents == null)
            {
                _contentEvents = ServiceLocator.Current.GetInstance<IContentEvents>();
            }

            _contentEvents.CreatedContent -= ContentEvents_CreatedContent;
        }
    }
#227935
Sep 16, 2020 18:53

I tried combining your answers but in the CreatedContent event the name with the randomly generated string is already set. Is there an event that occurs before the name is generated?

#227988
Sep 17, 2020 9:49
Tomas Hensrud Gulla - Sep 17, 2020 9:50
CreatingContent
Frans Bergström - Sep 17, 2020 10:08
How can I get data like ParentLink, Language etc. in CreatingContent? The EventArgs doesn't seem to supply it. I also need to be sure the content is of a certain product type.
Sanjay Kumar - Sep 17, 2020 14:04
You can't use ParentLink, Language etc. in CreatingContent but after creating content we can modify the name, url, seoUrl etc.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.