Search code examples
c#asp.net-mvcasp.net-mvc-5episerverepiserver-10

In Episerver CMS, how to create a property to display the source URL of an uploaded image or PDF asset (in the Episerver editor interface)?


Annoyingly, the MediaData class in Episerver doesn't have any basic properties like source URL, alt text, etc. I'm trying to implement a class to inherit from MediaData and provide specific properties for a certain type of media asset (PDF in this example).

I've tried manually setting the property values and also overriding the SetDefaultValues event, to no avail. Although, I do see either a textbox or a URL picker based on the type I use for "SrcUrl", however it is blank and never populates the uploaded PDF's URL.

[ContentType(
    DisplayName = "PDF File",
    GUID = "xxxxxxx-xxxx-xxxxxx-xxxx-xxxxxxxxxxx")]
[MediaDescriptor(ExtensionString = "pdf")]
public class PdfFile : MediaData
{
    [UIHint(UIHint.MediaFile)]
    [Display(Name = "PDF URL",
        Description = "Link to view or reference PDF",
        GroupName = SystemTabNames.Content,
        Order = 10)]
    public virtual string SrcUrl
    {
        get { return UrlResolver.Current.GetUrl(this.ContentLink); }
        set { value = UrlResolver.Current.GetUrl(this.ContentLink); }
    }

    // Sets the default property values
    public override void SetDefaultValues(ContentType contentType)
    {
        base.SetDefaultValues(contentType); 

        this.SrcUrl = UrlResolver.Current.GetUrl(this.ContentLink) ?? "Default";
    }
}

PDF URL property rendering blank in Episerver editor interface when viewing a PDF

****Disclaimer: I'm new to the Episerver CMS and may be missing something stupidly simple (ok with being shamed if appropriate).*


Solution

  • I was able to resolve this with the help of Epi support, essentially I needed to create an Initializable Module - this then allowed me to hook into the needed life cycle events of content creation.

    [InitializableModule]
    [ModuleDependency(typeof(InitializationModule))]
    public class ModelDefaultValuesInitialization : IInitializableModule
    {
        public void Initialize(InitializationEngine context)
        {
            var contentEvents = ServiceLocator.Current.GetInstance<IContentEvents>();
            contentEvents.CreatedContent += MediaBlocksDefaultValues;
        }
    
        private void MediaBlocksDefaultValues(object sender, ContentEventArgs e)
        {
            PopulateAssetURL(e);
        }
    
        /// <summary>
        /// Get the URL path of the uploaded asset and set it to the SrcUrl field which is easily visible to editors
        /// </summary>
        /// <param name="e"></param>
        private void PopulateAssetURL(ContentEventArgs e)
        {
            var mediaTypeBlock = e.Content as PdfFile;
            if (mediaTypeBlock != null)
            {
                string result = ServiceLocator.Current.GetInstance<UrlResolver>().GetUrl(mediaTypeBlock.ContentLink);
                if (!string.IsNullOrEmpty(result))
                {
                    var srvcLoc = ServiceLocator.Current.GetInstance<IContentRepository>();
                    var contentClone = mediaTypeBlock.CreateWritableClone() as PdfFile;
                    contentClone.SrcUrl = result;
                    srvcLoc.Save(contentClone, SaveAction.Publish, EPiServer.Security.AccessLevel.Administer);
                }
            }            
        }
    
        public void Uninitialize(InitializationEngine context)
        {
            var contentEvents = ServiceLocator.Current.GetInstance<IContentEvents>();
            contentEvents.CreatedContent -= MediaBlocksDefaultValues;
        }
    }
    
    • Note: I posted the above to be consistent, but in reality I refactored the code to set the SrcUrl property on a class called BaseMediaData, which inherits from the MediaData class. In this way, all files types (powerpoints, pdfs, etc.) can have this property, since it is relevant to all of them. Images inherit from a different base class (ImageData), so I also had to make a new class called ImageFile which inherits from ImageData and applies the same property. I was lazy but it would probably be a good idea to use an interface to standardize this implementation across the two classes.