EPiServer Commerce – Redirect old URL to new URL job

This is a scheduled job I had to put together for a client. The client had a lot of product content cross referenced between each other using the /link/{Insert GUID here}.aspx. Since the database had received direct database manipulated my hand was forced to reimport all the product in the catalog. A side effect of this is that all the content is regenerated and new Guids are made. Productblock and other items had been using the link field in EPiServer and so there were lots of broken links related to products. Since I had the database of the who’d received the manipulations and the now new database I could use the Code field, which contains special information related to a given product, such as an external ID, to get out all GUID’s, go through one by one and get the Code tied to the given GUID and do a Code lookup in my now new current data and to get the new GUID and build a redirect with all this information. This redirect is then stored in the BVN 404 Custom Redirect Handler module and then resolve the given request.

This made it easy for to set up redirects to the new content because

public class RedirectJob: ScheduledJobBase {
    private readonly ILogger _log;
    private readonly CancellationTokenSource _cancellationTokenSource;
    private readonly CancellationToken _cancellationToken;
    private readonly string _connectionStringName = ConfigurationManager.ConnectionStrings["EcfSqlConnectionOld"].ConnectionString;

    public RedirectJob() {
        _log = LogManager.GetLogger();
        _cancellationTokenSource = new CancellationTokenSource();
        _cancellationToken = _cancellationTokenSource.Token;
        IsStoppable = true;
    }

    public override void Stop() {
        _cancellationTokenSource.Cancel();
    }

    public override string Execute() {
        OnStatusChanged($ "Starting execution of {GetType()}");
        try {
            var count = CreateRedirectBasedOnOldUrlItems();
            CustomRedirectHandler.ClearCache();
            _log.Information("Successfully created or skipped existing redirects.");
            return "Successfully went through " + count + " items.";
        } catch (Exception ex) {
            _log.Error("Failed to create redirects based on old products", ex);
            throw;
        }
    }

    private static void CheckCancellationToken(CancellationToken ct) {
        if (ct.IsCancellationRequested) {
            throw new JobCancelledException("Cancelled redirect job.");
        }
    }

}
private int CreateRedirectBasedOnOldUrlItems() {
   var oldUrlItems = GetOldUrlItems();
   var urlResolver = ServiceLocator.Current.GetInstance<UrlResolver>();
   var dsHandler = new DataStoreHandler();
   var index = 0;
   var skippedItems = 0;
   OnStatusChanged($ "Redirecting {oldUrlItems.Count} old products");

   foreach(var oldItem in oldUrlItems) {
     CheckCancellationToken(_cancellationToken);
     OnStatusChanged("Handled: " + index + "/" + oldUrlItems.Count + " and skipped: " + skippedItems);
     var oldUrl = $ "/link/{oldItem.Guid.Replace(" - ", string.Empty)}.aspx";

     if (dsHandler.SearchCustomRedirects(oldUrl).Count > 0) {
       skippedItems++;
     } else {
       var contentLink = GetCatalogContentReferenceFromCode(oldItem.Code);
       if (contentLink == null) {
         continue;
       }
       var newUrl = urlResolver.GetUrl(contentLink);
       dsHandler.SaveCustomRedirect(new CustomRedirect(oldUrl.Trim(), newUrl.Trim(), false));
     }
     index++;
     }
  return oldUrlItems.Count;
}
private List<UrlItem> GetOldUrlItems() {
  const string codeCol = "Code";
  const string guidCol = "ContentGuid";
  var oldUrlItems = new List<UrlItem>();

        using(var connection = new SqlConnection(_connectionStringName)) {
            connection.Open();
            var command = new SqlCommand {
                CommandText = $ @ "Select {codeCol}, {guidCol} 
                                   FROM [CatalogEntry] 
                                   UNION SELECT {codeCol}, {guidCol} 
                                   FROM [CatalogNode]", 
                CommandType = CommandType.Text,
                Connection = connection
            };

            var reader = command.ExecuteReader();

            try {
                while (reader.Read()) {
                    CheckCancellationToken(_cancellationToken);
                    oldUrlItems.Add(new UrlItem {
                        Code = reader[codeCol].ToString(), 
                        Guid = reader[guidCol].ToString()
                    });
                }
            } finally {
                reader.Close();
                connection.Close();
            }
        }
        return oldUrlItems;
}
private static ContentReference GetCatalogContentReferenceFromCode(string code) {
    var referenceConverter = ServiceLocator
                               .Current
                               .GetInstance<ReferenceConverter>();
    var contentLink = referenceConverter
                        .GetContentLink(code, CatalogContentType.CatalogNode);

    if (contentLink.ID == 0) {
        contentLink = referenceConverter
                        .GetContentLink(code, CatalogContentType.CatalogEntry);
    }

    return contentLink;
}
public class UrlItem {
    public string Code { get; set; }
    public string Guid { get; set; }
    public ContentReference ContentReference { get; set; }
    public EntryContentBase Content { get; set; }
}
Alf Hammerseth Written by:

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *