Modifying existing name URL generation?

Vote:
 

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
Vote:
 

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
Vote:
 

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
Vote:
 

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.