Selection Problem with Custom Media Type Content in Umbraco 4

The Problem

You have a custom media type. You want to add a link to it in the WYSIWYG editor. 

You go to add a link as normal, except in the "Insert/Edit Link" pop up, you click on the "Media" tab. You notice that when you click on it, no url is inserted in the Url field. 

 

The problem is due to this method in the Umbraco source:

        private static string findMediaLink(Media dd, string nodeLink)
        {
            Guid uploadGuid = new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c");
            foreach (Property p in dd.getProperties)
            {
                if (p.PropertyType.DataTypeDefinition.DataType.Id == uploadGuid && !String.IsNullOrEmpty(p.Value.ToString()))
                {
                    return p.Value.ToString();
                }
            }
            return "";
        }

 

This method is called from the overrided Render(ref XmlTree tree) method in Umbraco's loadMedia class. Here is the code block:

        string nodeLink = findMediaLink(dd, dd.Id.ToString());
        if (!String.IsNullOrEmpty(nodeLink))
        {
            xNode.Action = "javascript:openMedia('" + nodeLink + "');";
        }
        else
        {
            xNode.Action = null;
            xNode.DimNode();
         }

 

Notice that when findMediaLink() is called, your custom media type is never going to return  "5032a6e6-69e3-491d-bb28-cd31cd11086c" as a Guid. So your media type never gets assiged it's openMedia action, and xNode.DimNode() will always be called.

 

The Work Around

You must replace the Umbraco media tree handler with your own one. We called ours "MediaTree".

Here's how:

  • Create a class (eg. MediaTree) that inherits from loadMedia (see code below)
  • Copy and paste the Render(ref XmlTree tree), and findMediaLink(Media dd, string nodeLink) methods from loadMedia.cs into your new class
  • Modify the findMediaLink(Media dd, string nodeLink) method to get the Guid from your custom media type, and check if it is equal to p.PropertyType.DataTypeDefinition.DataType.Id (see code below)

 

Here's the class:

    public class MediaTree : loadMedia
    {

        public MediaTree(string application) : base(application) { }

        public override void Render(ref XmlTree tree)
        {
            Media[] docs;

            if (m_id == -1)
                docs = Media.GetRootMedias();
            else
                docs = new Media(m_id).Children;

            foreach (Media dd in docs)
            {
                XmlTreeNode xNode = XmlTreeNode.Create(this);
                xNode.NodeID = dd.Id.ToString();
                xNode.Text = dd.Text;

                // Check for dialog behaviour
                if (!this.IsDialog)
                {
                    if (!this.ShowContextMenu)
                        xNode.Menu = null;
                    xNode.Action = "javascript:openMedia(" + dd.Id + ");";
                }
                else
                {
                    if (this.ShowContextMenu)
                        xNode.Menu = new List<IAction>(new IAction[] { ActionRefresh.Instance });
                    else
                        xNode.Menu = null;
                    if (this.DialogMode == TreeDialogModes.fulllink)
                    {
                        string nodeLink = findMediaLink(dd, dd.Id.ToString());
                        if (!String.IsNullOrEmpty(nodeLink))
                        {
                            xNode.Action = "javascript:openMedia('" + nodeLink + "');";
                        }
                        else
                        {
                            xNode.Action = null;
                            xNode.DimNode();
                        }
                    }
                    else
                    {
                        xNode.Action = "javascript:openMedia('" + dd.Id.ToString() + "');";
                    }
                }
                xNode.HasChildren = dd.HasChildren;

                if (this.IsDialog)
                    xNode.Source = GetTreeDialogUrl(dd.Id);
                else
                    xNode.Source = GetTreeServiceUrl(dd.Id);

                if (dd.ContentType != null)
                {
                    xNode.Icon = dd.ContentType.IconUrl;
                    xNode.OpenIcon = dd.ContentType.IconUrl;
                }

                tree.Add(xNode);
            }
        }

        private static string findMediaLink(Media dd, string nodeLink)
        {
            TheFarm.Umbraco.Controls.MultiMediaUploadDT mmDT = new TheFarm.Umbraco.Controls.MultiMediaUploadDT();
            Guid farmUpload = mmDT.Id;

            Guid uploadGuid = new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c");
            foreach (Property p in dd.getProperties)
            {
                if ((p.PropertyType.DataTypeDefinition.DataType.Id == uploadGuid || p.PropertyType.DataTypeDefinition.DataType.Id == farmUpload) && !String.IsNullOrEmpty(p.Value.ToString()))
                {
                    return p.Value.ToString();
                }
            }
            return "";
        }

    }

 

 

Note: For this to work your custom media class must contain a Guid.

eg.

        public override Guid Id
        {
            get { return new Guid("{12345678-ABCD-EFGH-IJKLM-NOPQRSTUVWX}"); }
        }

 

Now go to the database and edit the umbracoAppTree table.

UPDATE umbracoAppTree
SET treeHandlerAssembly = '<your assembly>',
treeHandlerType = 'Umbraco.MediaTree' /* We called ours MediaTree */
WHERE treeAlias LIKE 'media'

 

That's it.

 

 

 

Posted on 3/4/2009 7:41:00 PM by AnthonyDang

Permalink | Comments (2) | Post RSSRSS comment feed |

Categories: Technology

Tags: , ,

 

Comments

March 5. 2009 14:41

Funny, have run into same issue while building a 'protected media' package.

It's just annoying the FindMediaLink is private to the original class, as it would make lot more sense to just override that behaviour in your class.

Cheers,
Dirk

Dirk Belgium

March 19. 2009 14:17

A fix for this has been committed to the Umbraco core.
The method:

private static string findMediaLink(Media dd, string nodeLink)

has been changed to not be a static method and has been declared virtual so that inheritors can simply override only this method.

But better yet, a static method has been added to the loadMedia class so that you can simply add in your custom data types to match on application startup (i.e. global.asax), this way you don't actually have to create your tree class, modify the database or anything.

Shannon Deminick Australia

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading



Copyright © 2010 TheFARM