November Happy Hour will be moved to Thursday December 5th.

Converting Media Types

Vote:
 

We have several thousands of PDF files in our CMS environment and until now, we did not have a specific Media Type for these files. Now we have created a type for PDFs that contains all the properties of the GenericMedia type and some additional properties but we need to figure out a way to convert the existing PDF files to the new type.

I found this article which addresses pretty much the same scenario but I'm wondering if there's a better way than manipulating the DB directly?

https://robertlinde.se/episerver%207.5/mediadata/plugin/2014/05/01/converting-mediadata-contenttype-in-episerver-75.html

#197933
Oct 17, 2018 14:37
Vote:
 

manipulating db directly wil definitely be the fastest way to do it. another option is to do it programmatically - meaning that you read pdf media types and convert to proper newly created media type in code.

#198021
Oct 19, 2018 4:53
Vote:
 

The converting to new media type in code is basically the part I'm struggling with. I'm currently getting all the PDF files for processing with this method:

 

private List<BasicContent> GetPdfs()
        {
            var pdfs = new List<BasicContent>();
            var assets = ContentRepository.GetDescendents(SiteDefinition.Current.GlobalAssetsRoot);

            OnStatusChanged("Found " + assets.Count() + " assets");

            foreach (var asset in assets)
            {
                BasicContent pdf = null;
                if (ContentRepository.TryGet(asset, out pdf) && pdf.Name.EndsWith(".pdf"))
                {
                    pdfs.Add(pdf);
                }
            }

            return pdfs;
        } 

I'm using BasicContent because if I use the new PdfFile media type, nothing gets added to the list. I'm then processing the list in a scheduled job where I check whether the ContentTypeID matches the new media types ID and if not, I try to change the content type.

protected override string ExtendedExecute()
        {
            var pdfs = GetPdfs();

            var output = new StringBuilder();

            //Get a suitable MediaData type from extension
            var mediaType = MediaDataResolver.GetFirstMatching(".pdf");
            var contentType = ContentTypeRepository.Load(mediaType);

            foreach (var pdf in pdfs)
            {
                if (pdf.ContentTypeID != contentType.ID)
                {
                    try
                    {
                        var writable = pdf.CreateWritableClone() as BasicContent;

                        if (writable != null)
                        {
                            writable.ContentTypeID = contentType.ID;

                            ContentRepository.Save(
                            writable,
                            SaveAction.Publish,
                            AccessLevel.NoAccess);
                        } else
                        {
                            output.AppendLine(string.Format("Create clone resulted in null: {0}",pdf.ContentLink.ID));
                        }
                    }
                    catch (Exception ex)
                    {
                        output.AppendLine(string.Format("ID: {0}, Error: {1}",
                            pdf.ContentLink.ID,
                            ex.Message));
                    }
                }
            }

            return string.Format(
                "Fixed {0} pdfs. \n Errors:\n{1}",
                i,
                output);
        }


This however does not convert the the type for the files but there are no exceptions either. So it seems that the conversion should be done some other way?

#198064
Oct 19, 2018 13:19
Vote:
 

I just had a case where a duplicate Image-type had been added and think I hopefully solved it the database way.

It's a bit weird how uploaded images had been distributed between the types by the way... It would've been nicer if first type in had gotten the upper hand.

Don't try this! Warning!!! Warning!!! Be sure to be backed up etc. You might break something. Risk is yours!!!

It would've also been nice to have this and block types built-in to the convert type tool... The Stored Procedures seem to work fine so this code might help someone but please be aware this is on your own risk.

BEGIN TRANSACTION [ConvertTransaction]
BEGIN TRY
  DECLARE @FromPropertyID1 int
  DECLARE @ToPropertyID1 int
  DECLARE @FromPropertyID2 int
  DECLARE @ToPropertyID2 int
  DECLARE @FromPropertyID3 int
  DECLARE @ToPropertyID3 int
  
  DECLARE @RC int
  DECLARE @PageID int
  DECLARE @FromPageType int
  DECLARE @ToPageType int
  DECLARE @Recursive bit
  DECLARE @IsTest bit

  SELECT @PageID = 1
  SELECT @FromPageType = pkID FROM tblContentType WHERE ContentTypeGUID = '0a89e464-56d4-449f-aea8-2bf774ab8730'
  SELECT @ToPageType = pkID FROM tblContentType WHERE ContentTypeGUID = '40ed0421-2d37-4751-97dc-c7ea7033c3a5'
  
  SELECT @FromPropertyID1 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @FromPageType AND [Name] = 'Copyright'
  SELECT @FromPropertyID2 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @FromPageType AND [Name] = 'Description'
  SELECT @FromPropertyID3 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @FromPageType AND [Name] = 'MediumThumbnail'
  
  SELECT @ToPropertyID1 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @ToPageType AND [Name] = 'Copyright'
  SELECT @ToPropertyID2 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @ToPageType AND [Name] = 'Description'
  SELECT @ToPropertyID3 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @ToPageType AND [Name] = 'MediumThumbnail'
  
  SET @Recursive = 1
  SET @IsTest = 0
  
  print @PageID
  print @FromPageType
  print @ToPageType
  
  DECLARE @MasterLanguageID int

  SET @MasterLanguageID = 8
  
  EXECUTE @RC = [dbo].[netConvertPropertyForPageType]
     @PageID
    ,@FromPageType
    ,@FromPropertyID1
    ,@ToPropertyID1
    ,@Recursive
    ,@MasterLanguageID
    ,@IsTest

  print @RC
  
  EXECUTE @RC = [dbo].[netConvertPropertyForPageType]
     @PageID
    ,@FromPageType
    ,@FromPropertyID2
    ,@ToPropertyID2
    ,@Recursive
    ,@MasterLanguageID
    ,@IsTest

  print @RC

  EXECUTE @RC = [dbo].[netConvertPropertyForPageType]
     @PageID
    ,@FromPageType
    ,@FromPropertyID3
    ,@ToPropertyID3
    ,@Recursive
    ,@MasterLanguageID
    ,@IsTest

  print @RC
  
  EXECUTE @RC = [dbo].[netConvertPageType]
     @PageID
    ,@FromPageType
    ,@ToPageType
    ,@Recursive
    ,@IsTest
  
  print @RC

  COMMIT TRANSACTION [ConvertTransaction]
END TRY
BEGIN CATCH
  ROLLBACK TRANSACTION [ConvertTransaction]
END CATCH

#201567
Feb 22, 2019 13:26
Vote:
 

I was lucky in the sense that our GenericMedia type did not have any custom properties, so I could actually just change the contenttype in the DB and everything worked.

Here's the scheduled job I built for the migration:

    public class FixPdfMediaType : ExtendedJobBase
    {
        private readonly IContentRepository ContentRepository;
        private readonly IContentTypeRepository ContentTypeRepository;
        private readonly ContentMediaResolver MediaDataResolver;

        public FixPdfMediaType()
        {
            ContentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
            ContentTypeRepository = ServiceLocator.Current.GetInstance<IContentTypeRepository>();
            MediaDataResolver = ServiceLocator.Current.GetInstance<ContentMediaResolver>();
        }

        private List<BasicContent> GetPdfs()
        {
            var pdfs = new List<BasicContent>();
            var assets = ContentRepository.GetDescendents(SiteDefinition.Current.GlobalAssetsRoot);

            OnStatusChanged("Found " + assets.Count() + " assets");

            foreach (var asset in assets)
            {
                BasicContent pdf = null;
                if (ContentRepository.TryGet(asset, out pdf) && pdf.Name.EndsWith(".pdf"))
                {
                    pdfs.Add(pdf);
                }
            }

            return pdfs;
        } 

        protected override string ExtendedExecute()
        {
            var pdfs = GetPdfs();

            OnStatusChanged("Handling " + pdfs.Count() + " PDF files");

            var output = new StringBuilder();
            int i = 0;

            //Get a suitable MediaData type from extension
            var mediaType = MediaDataResolver.GetFirstMatching(".pdf");
            var contentType = ContentTypeRepository.Load(mediaType);

            foreach (var pdf in pdfs)
            {
                if (pdf.ContentTypeID != contentType.ID)
                {
                    OnStatusChanged("Changing type for " + pdf.Name);

                    try
                    {
                        using (SqlConnection conn =
                                    new SqlConnection(ConfigurationManager.ConnectionStrings["EPiServerDB"].ConnectionString))
                        {
                            conn.Open();
                            using (SqlCommand cmd =
                                new SqlCommand("UPDATE tblPage SET fkPageTypeID=@ContentTypeID WHERE PkId = @ID", conn))
                            {
                                cmd.Parameters.AddWithValue("@ContentTypeID", contentType.ID);
                                cmd.Parameters.AddWithValue("@ID", pdf.ContentLink.ID);

                                cmd.ExecuteNonQuery();
                                i++;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        output.AppendLine(string.Format("ID: {0}, Error: {1}",
                        pdf.ContentLink.ID,
                        ex.Message));
                    }
                }
            }

            return string.Format(
                "Fixed {0} pdfs. \n Errors:\n{1}", 
                i, 
                output);
        }
    }
#201569
Feb 22, 2019 13:42
Vote:
 

Having to look at a similar issues to this, we have a site where previously we had only MediaFile and now we need to split out PDFs from that into PdfFile (which will still inherit from MediaFile).

Trying to figure out where we'd need to make updates in the database, as we specifically need to target MediaFile which are PDFs only and not all of them. And unfortunately there are some custom prioperties which, despite inheriting from MediaFile, end up needing to be remapped in the database.

I'm thinking best bet at this point may be reverse engineering the netConvert... stored procedures into varients which allow us to just target specific items rather than types as a whole. Am I right in thinking these are the stored procedurers used by the current page type conversion in the UI?

#249913
Mar 11, 2021 16:28
* 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.