With the old VPP file system you could create a new version of a file by right click the file and select Create new version. With the new file system this function has disappeared. You can however update a file by uploading a new file with the same name. A customer to us needed the old method back because of various reasons.
We wanted a quick solution for this feature, so we decided to add a custom template to our GenericMedia-type (inherited from MediaData) where the editor could upload a new version of the file. To accomplish this we needed to go through three steps.
- Create a view
- Create a Controller with a TemplateDescriptor
- Create a UIDescriptor that tells GenericMedia to use OnPageEditView
1. View
First we create a view. We know that this View will get a model of GenericMedia, and that we need a form where we can upload a file. We also add a way to send feedback from the Controller via ViewData.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@model Project.Web.Models.Files.GenericMedia @{ Layout = null; } <form method="post" enctype="multipart/form-data"> <h2>Update file</h2> <p>To update files metadata, click in the <i>All Properties</i>-button.</p> @if (ViewData["message"] != null) { <h3 style="color: green;">@ViewData["message"].ToString()</h3> } <input type="file" name="file" /> <br/><br/> <input type="submit" value="Update file" onclick="return confirm('Are you sure you want to update this file?');" /> </form> |
2. Controller with TemplateDescriptor
Now we create a controller to the View. The Controller needs a Index-method where we can pass in a HttpPostedFileBase if this is posted from the View. If this is passed into the method we add some logic to update the file-data of the current content.
We also need to add a TemplateDescriptor-attribute to this controller. In the attribute we define that this controller should be used with RenderingTag.Edit, that it’s a MvcController and where we can find the view.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
[TemplateDescriptor( Inherited = true, AvailableWithoutTag = false, Tags = new[] { RenderingTags.Edit }, TemplateTypeCategory = TemplateTypeCategories.MvcController, Path = "/Views/GenericMedia/Index.cshtml" )] public class GenericMediaController : ActionControllerBase, IRenderTemplate<GenericMedia> { public ActionResult Index(GenericMedia currentBlock, HttpPostedFileBase file) { if (file != null) { var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>(); var blobFactory = ServiceLocator.Current.GetInstance<BlobFactory>(); var media = (GenericMedia)currentBlock.CreateWritableClone(); media.BinaryData = blobFactory.CreateBlob(media.BinaryDataContainer, Path.GetExtension(file.FileName)); media.BinaryData.Write(file.InputStream); contentRepository.Save(media, SaveAction.Publish); ViewData.Add("message", "The file has been updated."); } return View(currentBlock); } } |
3. UIDescriptor
Finally we need an UIDescriptor to say that when editing a GenericMedia, we need to see the OnPageEditView. Otherwise we will always see the AllPropertiesView when editing the media. The UIDescriptor is defined by creating a class that inherits from UIDescriptor and with the attribute [UIDescriptorRegistration].
1 2 3 4 5 6 7 8 9 10 |
[UIDescriptorRegistration] public class GenericMediaUIDescriptor : UIDescriptor<GenericMedia> { public GenericMediaUIDescriptor() : base("icon-document") { DefaultView = CmsViewNames.OnPageEditView; DisabledViews = new string[] { }; } } |
At last
If you know a smoother way of doing this, please leave a reply in the comments. 🙂