This blog post exposes a way to extend the default logic of the Image/Video/Document upload of Sitefinity's content blocks. Lately there have been some requests for different users with different permissions to have a predefined library selected when an upload is made. The case this blog post will cover is to select the first library the current user has permissions to and upload all content there.
In order for us to be able to add additional logic to the dialog loaded by the Content Block, we will need to override three dialogs - MediaContentManagerDialog, SingleMediaContentSelectorView and finally, MediaContentManagerDialog.
First off, the primary dialog loaded is the MediaContentManagerDialog. This is the one we need to replace with a custom one in the Unity Container through ObjectFactory. First we create a class that inherits from the MediaContentManagerDialog one. The one I created is called CustomMediaContentManagerDialog and is registered as per this documentation article in the Global.asax file:
protected void Application_Start(object sender, EventArgs e) { Bootstrapper.Initialized += Bootstrapper_Initialized; } void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e) { if (e.CommandName == "Bootstrapped") { ObjectFactory.Container.RegisterType(typeof(DialogBase), typeof(CustomMediaContentManagerDialog), typeof(MediaContentManagerDialog).Name, new HttpRequestLifetimeManager()); } }Once done we need to override the base template of the MediaContentManagerDialog along with its script descriptors and its SelectorView.LayoutTemplatePath:
public class CustomMediaContentManagerDialog : MediaContentManagerDialog { protected override void InitializeControls(GenericContainer container) { base.InitializeControls(container); this.ContentSelectorView.LayoutTemplatePath = "~/CustomSingleMediaContentItemView.ascx"; } public override IEnumerable<ScriptDescriptor> GetScriptDescriptors() { var descriptor = (ScriptControlDescriptor)base.GetScriptDescriptors().Last(); descriptor.Type = "Telerik.Sitefinity.Web.UI.MediaContentManagerDialog"; descriptor.AddComponentProperty("contentSelectorView", this.ContentSelectorView.ClientID); descriptor.AddComponentProperty("itemSettingsView", this.ItemSettingsView.ClientID); descriptor.AddElementProperty("saveLink", this.SaveLink.ClientID); descriptor.AddElementProperty("cancelLink", this.CancelLink.ClientID); descriptor.AddElementProperty("buttonArea", this.ButtonArea.ClientID); descriptor.AddProperty("dialogMode", this.DialogMode); descriptor.AddProperty("videoTag", Config.Get<LibrariesConfig>().ContentBlockVideoTag.ToString()); descriptor.AddComponentProperty("titleTextField", this.TitleTextField.ClientID); descriptor.AddComponentProperty("altTextField", this.AltTextField.ClientID); var thumbnailsServiceUrl = string.Format("~/{0}", LibrariesModule.ThumbnailsServiceUrl); descriptor.AddProperty("thumbnailServiceUrl", VirtualPathUtility.ToAbsolute(thumbnailsServiceUrl)); descriptor.AddProperty("thumbnailExtensionPrefix", this.ThumbnailExtensionPrefix); return new[] { descriptor }; } private readonly string layoutTemplatePath = "~/CustomMediaContentManagerDialog.ascx"; }CustomMediaContentManagerDialog.ascx:
<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI.ControlDesign" TagPrefix="sf" %><%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" TagPrefix="sf" %><%@ Register Assembly="Telerik.Sitefinity" TagPrefix="sfFields" Namespace="Telerik.Sitefinity.Web.UI.Fields" %><%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Modules.Libraries.Web.UI.Designers" TagPrefix="sf" %><%@ Register Assembly="SitefinityWebApp" Namespace="SitefinityWebApp" TagPrefix="test" %><sfFields:FormManager id="formManager" runat="server"/> <sf:SitefinityLabel runat="server" id="titleLabel" WrapperTagName="h1" CssClass="sfSepTitle"></sf:SitefinityLabel><div class="sfBasicDim"> <div runat="server" id="mediaContentManagerWrapper" class="sfContentViews"> <%--<sf:SingleMediaContentItemView id="contentSelectorView" runat="server" UseSmallItemPreview="true" SkipBlankItemView="true" ShowCropResizeRotateButton="true"></sf:SingleMediaContentItemView> this is commented out --%> <test:CustomSingleMediaContentItemView id="contentSelectorView" runat="server" UseSmallItemPreview="true" SkipBlankItemView="true" ShowCropResizeRotateButton="true"></test:CustomSingleMediaContentItemView> <sfFields:TextField ID="titleTextField" runat="server" DisplayMode="Write" CssClass="sfFormCtrl sfW335" ShowCharacterCounter="true" RecommendedCharactersCount="35" CharacterCounterDescription="<%$Resources:PageResources, CharacterCounterDescription%>" Title="<%$Resources:Labels, ImageTitleWithNote %>" /> <sfFields:TextField ID="altTextField" runat="server" DisplayMode="Write" CssClass="sfFormCtrl sfW335" ShowCharacterCounter="true" RecommendedCharactersCount="35" CharacterCounterDescription="<%$Resources:PageResources, CharacterCounterDescription%>" Title="<%$Resources:Labels, AlternativeTextWithNote %>" /> <sf:SingleMediaContentItemView id="itemSettingsView" ShowAlignmentOptions="true" runat="server"></sf:SingleMediaContentItemView> </div></div><div id="buttonArea" class="sfButtonArea sfSelectorBtns" runat="server"> <asp:HyperLink runat="server" id="saveLink" class="sfLinkBtn sfSave sfDisabledLinkBtn"> <sf:SitefinityLabel runat="server" id="saveLinkTitle" class="sfLinkBtnIn" Text="<%$Resources:Labels, Save %>" WrapperTagName="strong"/> </asp:HyperLink> <asp:Literal runat="server" ID="lOr" Text="<%$Resources:Labels, or %>" /> <asp:HyperLink id="cancelLink" class="sfCancel" runat="server" NavigateUrl="javascript:void(0);"> <sf:SitefinityLabel runat="server" id="cancelLinkTitle" Text="<%$Resources:Labels, Cancel %>"></sf:SitefinityLabel> </asp:HyperLink></div><sf:ClientLabelManager id="clientLabelManager" runat="server"> <Labels> <sf:ClientLabel ClassId="Labels" Key="Save" runat="server" /> <sf:ClientLabel ClassId="Labels" Key="Upload" runat="server" /> <sf:ClientLabel ClassId="Labels" Key="Done" runat="server" /> <sf:ClientLabel ClassId="ImagesResources" Key="EditImage" runat="server" /> <sf:ClientLabel ClassId="LibrariesResources" Key="InsertAItem" runat="server" /> <sf:ClientLabel ClassId="ImagesResources" Key="ImageWithArticle" runat="server" /> <sf:ClientLabel ClassId="ImagesResources" Key="SelectAnImage" runat="server" /> </Labels></sf:ClientLabelManager>CustomSingleMediaContentItemView.ascx:
<%@ Control Language="C#" %><%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %><%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" TagPrefix="sf" %><%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI.Fields" TagPrefix="sf" %><%@ Register TagPrefix="sitefinity" Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" %><%@ Register TagPrefix="Images" Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Modules.Libraries.Web.UI.Images" %><%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Modules.Libraries.Web.UI.Videos" TagPrefix="sfLibraries" %><%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI.Fields" TagPrefix="sfFields" %><%@ Register Assembly="SitefinityWebApp" Namespace="SitefinityWebApp" TagPrefix="test" %> <sf:ResourceLinks ID="resourcesLinks" runat="server"> <sf:ResourceFile Name="Styles/Window.css" /> <sf:ResourceFile Name="Styles/MaxWindow.css" /></sf:ResourceLinks> <div class="sfDim360"> <div id="sf_imgIsSelected" style="display: none;"> <div id="img_container"> <div class="sfSelImgWrp"> <div id="sf_imgSelected" class="sfSelImg sfMTop15" style="display: none;"> <sf:SfImage ID="thumbnailImage" runat="server" /> </div> <div id="sf_videoSelected" class="sfPreviewVideoFrame sfSelImg sfMTop15" style="display: none;"> <sfFields:MediaField id="mediaField" runat="server" ItemName = "Video" ItemNamePlural = "Videos" DisplayMode="Read" HideCommandBar="true" /> </div> <div id="sf_docSelected" class="sfSelDoc sfMTop15" style="display: none;"> <i class="sfext"></i> <sf:SitefinityHyperLink ID="documentHyperLink" runat="server" target="_blank" /> </div> <div id="sf_unpublishedMediaItemMessage" class="sfSelDoc sfMTop15" style="display: none;"> <p class="sfUnpublishedItm"><b><asp:Literal ID="unpublishedMediaItemMessage" runat="server" /></b></p> </div> <div class="sfSelImgProps sfMTop15"> <ul> <li><strong> <asp:Literal ID="Literal4" runat="server" Text="<%$Resources:Labels, Title %>" />:</strong> <asp:Label ID="lblTitle" runat="server" /> </li> <li id="alternativeTextLabelWrapper"><strong> <asp:Literal ID="Literal5" runat="server" Text="<%$Resources:ImagesResources, AlternativeText %>" />:</strong> <asp:Label ID="lblAltText" runat="server" /> </li> <li><strong> <asp:Literal ID="Literal1" runat="server" Text="<%$Resources:Labels, Type %>" />:</strong> <asp:Label ID="lblExtension" runat="server" /> </li> <li><strong> <asp:Literal ID="Literal2" runat="server" Text="<%$Resources:Labels, FileSize %>" />:</strong> <asp:Label ID="lblSize" runat="server" /> </li> <li><strong> <asp:Literal ID="Literal3" runat="server" Text="<%$Resources:LibrariesResources, Library %>" />:</strong> <asp:Label ID="lblLibrary" runat="server" /> </li> </ul> <asp:LinkButton runat="server" ID="changeImageButton" OnClientClick="return false;" style="display:none" CssClass="sfLinkBtn sfChange"> <strong class="sfLinkBtnIn"> <asp:Literal ID="changeButtonTitle" runat="server"/></strong> </asp:LinkButton> <asp:LinkButton runat="server" ID="editImageButton" OnClientClick="return false;" style="display:none" CssClass="sfLinkBtn sfChange"> <strong class="sfLinkBtnIn"> <asp:Literal ID="editButtonTitle" runat="server"/></strong> </asp:LinkButton> <asp:LinkButton runat="server" ID="cropResizeRotateImageButton" OnClientClick="return false;" style="display:none" CssClass="sfLinkBtn sfChange"> <strong class="sfLinkBtnIn"> <asp:Literal ID="Literal8" runat="server" Text="<%$Resources:Labels, CropResizeRotateDotDotDot %>" /></strong> </asp:LinkButton> </div> </div> </div> </div> <div id="sf_imgIsEmpty" class="sfNoMediaItem"> <div class="sfPTop100"> <span class="sfMediaItemViewIcn"></span> <b class="sfDisplayBlock sfMTop10"><sf:SitefinityHyperLink ID="selectImageButton" runat="server" target="_blank" /></b> <sf:SitefinityHyperLink ID="uploadImageButton" runat="server" target="_blank" CssClass="sfSmallerTxt" /> </div> </div> <%--<sf:SingleMediaContentItemDialog ID="imageSelector" runat="server" HostedInRadWindow="false" /> This is commented out-- %> <test:CustomSingleMediaContentItemDialog ID="imageSelector" runat="server" HostedInRadWindow="false" /><-- this is the custom dialog--> <telerik:RadWindowManager id="windowManager" runat="server" Height="100%" Width="100%" Behaviors="None" Skin="Default" InitialBehaviors="Maximize" ShowContentDuringLoad="false" VisibleStatusBar="false"> <Windows> <telerik:RadWindow ID="imageEditor" runat="server" Height="100" Width="100" ReloadOnShow="true" OnClientShow="OnClientShow" OnClientClose="OnClientClose" /> <telerik:RadWindow ID="cropResizeRotateDialog" runat="server" Height="100" Width="100" Modal="true" NavigateUrl="~/Sitefinity/Dialog/ImageEditorDialog" ReloadOnShow="true" Behaviors="None" /> </Windows> </telerik:RadWindowManager></div><sitefinity:ClientLabelManager id="clientLabelManager" runat="server"> <labels> <sitefinity:ClientLabel ClassId="LibrariesResources" Key="Kb" runat="server" /> <sitefinity:ClientLabel ClassId="LibrariesResources" Key="Mb" runat="server" /> </labels></sitefinity:ClientLabelManager> <script type="text/javascript"> function GetRadWindow() { var oWindow = null; if (window.radWindow) oWindow = window.radWindow; else if (window.frameElement.radWindow) oWindow = window.frameElement.radWindow; return oWindow; } function OnClientShow(oWnd, eventArgs) { var containerWnd = GetRadWindow(); //Maximize the container window containerWnd.maximize(); //Maximize the designer's property editor dialog var propertyEditor = dialogBase.get_radWindow().get_contentFrame().contentWindow.top.$find("PropertyEditorDialog"); if (propertyEditor) { var propertyEditorRadWindow = propertyEditor.AjaxDialog.get_radWindow(); propertyEditorRadWindow.maximize(); //Prevent locking of the screen, if a previous dialog has been closed with error propertyEditorRadWindow.set_modal(false); } //Remove the class to display properly the dialog and save the elements as global variables selectorDialogs = $(".sfSelectorDialog").removeClass("sfSelectorDialog"); window.parent.selectorDialogs = window.parent.jQuery(".sfSelectorDialog").removeClass("sfSelectorDialog"); } function OnClientClose(oWnd, eventArgs) { //Restore the container window var containerWnd = GetRadWindow(); containerWnd.restore(); //Restore the designer's property editor dialog var propertyEditor = dialogBase.get_radWindow().get_contentFrame().contentWindow.top.$find("PropertyEditorDialog"); if (propertyEditor) { var propertyEditorRadWindow = propertyEditor.AjaxDialog.get_radWindow(); propertyEditorRadWindow.restore(); propertyEditorRadWindow.set_modal(true); } //Return the class to the previously saved elements selectorDialogs.addClass("sfSelectorDialog"); window.parent.selectorDialogs.addClass("sfSelectorDialog") }</script>Next up we need to override the SingleMediaContentItemView such that it uses our own control for its imageSelector. Below is the code of my CustomSingleMediaContentItemView class.
public class CustomSingleMediaContentItemView : SingleMediaContentItemView { protected virtual SingleMediaContentItemDialog ImageSelector { get { return this.Container.GetControl<CustomSingleMediaContentItemDialog>("imageSelector", true); } } }<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI.ControlDesign" TagPrefix="sf" %><%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" TagPrefix="sf" %><%@ Register Assembly="Telerik.Sitefinity" TagPrefix="sfFields" Namespace="Telerik.Sitefinity.Web.UI.Fields" %><%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Modules.Libraries.Web.UI.Designers" TagPrefix="sf" %><%@ Register Assembly="SitefinityWebApp" Namespace="SitefinityWebApp" TagPrefix="test" %><sfFields:FormManager id="formManager" runat="server"/> <sf:SitefinityLabel runat="server" id="titleLabel" WrapperTagName="h1" CssClass="sfSepTitle"></sf:SitefinityLabel><div class="sfBasicDim"> <div runat="server" id="mediaContentManagerWrapper" class="sfContentViews"> <sf:SingleMediaContentItemView id="contentSelectorView" runat="server" UseSmallItemPreview="true" SkipBlankItemView="true" ShowCropResizeRotateButton="true"></sf:SingleMediaContentItemView> <sfFields:TextField ID="titleTextField" runat="server" DisplayMode="Write" CssClass="sfFormCtrl sfW335" ShowCharacterCounter="true" RecommendedCharactersCount="35" CharacterCounterDescription="<%$Resources:PageResources, CharacterCounterDescription%>" Title="<%$Resources:Labels, ImageTitleWithNote %>" /> <sfFields:TextField ID="altTextField" runat="server" DisplayMode="Write" CssClass="sfFormCtrl sfW335" ShowCharacterCounter="true" RecommendedCharactersCount="35" CharacterCounterDescription="<%$Resources:PageResources, CharacterCounterDescription%>" Title="<%$Resources:Labels, AlternativeTextWithNote %>" /> <sf:SingleMediaContentItemSettingsView id="itemSettingsView" ShowAlignmentOptions="true" runat="server"></sf:SingleMediaContentItemSettingsView> </div></div><div id="buttonArea" class="sfButtonArea sfSelectorBtns" runat="server"> <asp:HyperLink runat="server" id="saveLink" class="sfLinkBtn sfSave sfDisabledLinkBtn"> <sf:SitefinityLabel runat="server" id="saveLinkTitle" class="sfLinkBtnIn" Text="<%$Resources:Labels, Save %>" WrapperTagName="strong"/> </asp:HyperLink> <asp:Literal runat="server" ID="lOr" Text="<%$Resources:Labels, or %>" /> <asp:HyperLink id="cancelLink" class="sfCancel" runat="server" NavigateUrl="javascript:void(0);"> <sf:SitefinityLabel runat="server" id="cancelLinkTitle" Text="<%$Resources:Labels, Cancel %>"></sf:SitefinityLabel> </asp:HyperLink></div><sf:ClientLabelManager id="clientLabelManager" runat="server"> <Labels> <sf:ClientLabel ClassId="Labels" Key="Save" runat="server" /> <sf:ClientLabel ClassId="Labels" Key="Upload" runat="server" /> <sf:ClientLabel ClassId="Labels" Key="Done" runat="server" /> <sf:ClientLabel ClassId="ImagesResources" Key="EditImage" runat="server" /> <sf:ClientLabel ClassId="LibrariesResources" Key="InsertAItem" runat="server" /> <sf:ClientLabel ClassId="ImagesResources" Key="ImageWithArticle" runat="server" /> <sf:ClientLabel ClassId="ImagesResources" Key="SelectAnImage" runat="server" /> </Labels></sf:ClientLabelManager>public class CustomSingleMediaContentItemDialog : SingleMediaContentItemDialog { protected override void InitializeControls(GenericContainer container) { base.InitializeControls(container); UserManager manager = UserManager.GetManager(); RoleManager roleManager = RoleManager.GetManager(SecurityManager.ApplicationRolesProviderName); LibrariesManager libMan = LibrariesManager.GetManager(); BlogsManager blogsManager = BlogsManager.GetManager(); var theUser = manager.GetUser(SecurityManager.GetCurrentUserId()); var theRoles = roleManager.GetRolesForUser(theUser.Id); if (this.DialogMode == EditorExternalDialogModes.Document) { var theUserLibrary = libMan.GetDocumentLibraries().Where(l => l.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Master); foreach (var role in theRoles) { if (role.Name == "Editors") { var specifiedRole = roleManager.GetRole("Editors"); var principalId = specifiedRole.Id; var objectId = (libMan.GetDocumentLibraries().Where(l => l.Title == "Default Library").First() as ISecuredObject).Id; foreach (var item in theUserLibrary) { Telerik.Sitefinity.Security.Model.Permission permission = libMan.GetPermission(SecurityConstants.Sets.DocumentLibrary.SetName, objectId, principalId); var editorPermissions = item.GetActivePermissionActionsForCurrentUser(); if (permission != null && permission.SetName == "DocumentLibrary" && editorPermissions.Contains("DocumentLibrary.ViewDocumentLibrary")) { base.UploaderView.TargetLibraryId = item.Id; } } } } } } public override IEnumerable<ScriptDescriptor> GetScriptDescriptors() { base.GetScriptDescriptors(); var descriptor = (ScriptControlDescriptor)base.GetScriptDescriptors().Last(); descriptor.AddComponentProperty("uploaderView", this.UploaderView.ClientID); descriptor.AddElementProperty("uploaderSection", this.UploaderSection.ClientID); if (SystemManager.CurrentContext.AppSettings.Multilingual) { descriptor.AddProperty("uiCulture", this.UICulture); } descriptor.AddComponentProperty("selectorView", this.SelectorView.ClientID); descriptor.AddElementProperty("saveLink", this.SaveLink.ClientID); descriptor.AddElementProperty("cancelLink", this.CancelLink.ClientID); descriptor.AddElementProperty("backLink", this.BackLink.ClientID); descriptor.AddElementProperty("titleLabel", ((Control)this.TitleLabel).ClientID); descriptor.AddElementProperty("cancelLinkTitle", ((Control)this.CancelLinkTitle).ClientID); descriptor.AddElementProperty("backLinkTitle", ((Control)this.BackLinkTitle).ClientID); descriptor.AddElementProperty("buttonArea", this.ButtonArea.ClientID); descriptor.AddElementProperty("selectorSection", this.SelectorSection.ClientID); descriptor.AddElementProperty("filterSection", this.FilterSection.ClientID); descriptor.AddComponentProperty("clientLabelManager", this.ClientLabelManager.ClientID); descriptor.AddProperty("_bodyCssClass", this.BodyCssClass); descriptor.AddProperty("dialogMode", this.DialogMode); descriptor.AddProperty("mediaDialogOpenMode", this.MediaDialogOpenMode); descriptor.AddProperty("_useOnlyUploadMode", this.UseOnlyUploadMode); descriptor.AddProperty("_useOnlySelectMode", this.UseOnlySelectMode); descriptor.AddProperty("_sourceLibraryId", this.SourceLibraryId); descriptor.Type = "Telerik.Sitefinity.Web.UI.SingleMediaContentItemDialog"; return new[] { descriptor }; } }
this.DialogMode == EditorExternalDialogModes.Image
var theUserAlbum = libMan.GetAlbums().Where(l => l.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Master);Here is a sample picture for better understanding:
Before:
After:
You can find the complete code sample in in GitHub.