public void Soft_Deleted_BlogItem_Searchable() { // Arrange IBlogItem savedItem = fixture.Blog.Save(RandomBlogItem(false)); String newId = savedItem.Header.Id; // Get the Id Boolean deleteResponse = fixture.Blog.Delete(new List <IBlogHeader>() { savedItem.Header }, false); // Delete // Act IList <IBlogHeader> searchResults = fixture.Blog.List( new BlogListRequest() { Ids = new List <String>() { newId }, States = new List <BlogHeaderState>() { BlogHeaderState.Deleted } // Search specifically for deleted items }); // Assert Assert.Equal(1, searchResults.Count); }
public virtual IActionResult SaveBlogEdit(EditItemViewModel model) { // Get the blog that is for this controller instance if (Current != null) { // Get the item that needs to be saved IBlogItem blogItem = (model.Id == "") ? new BlogItem() : Current.Get(new BlogHeader() { Id = Current.Parameters.Provider.DecodeId(model.Id) }); // Blog item valid? if (blogItem != null) { // Update the properties of the blog item from the incoming model blogItem.Copy(model); // (Re)Save the blog item back to the blog handler blogItem = Current.Save(blogItem); } else { throw new ItemNotFoundBlogException("Item with id '{id}' not found"); } } // Call the common view handler return(EditBlogCommon(model.Id)); }
public void Soft_Deleted_BlogItem_Not_Searchable() { // Arrange IBlogItem savedItem = fixture.Blog.Save(RandomBlogItem(false)); String newId = savedItem.Header.Id; // Get the Id Boolean deleteResponse = fixture.Blog.Delete(new List <IBlogHeader>() { savedItem.Header }, false); // Delete // Act IList <IBlogHeader> searchResults = fixture.Blog.List( new BlogListRequest() { Ids = new List <String>() { newId }, States = new List <BlogHeaderState>() { } // No state list passed so should default to published only }); // Assert Assert.Equal(0, searchResults.Count); }
/// <summary> /// Copys a given item in to this item (so we preserve the object reference) /// Does not copy the file references however /// </summary> /// <returns>The the current item</returns> public IBlogItem Copy(IBlogItem from) { // Copy the items in this.Header.Author = from.Header.Author; this.Header.Description = from.Header.Description; this.Header.Name = from.Header.Name; this.Header.PublishedDate = from.Header.PublishedDate; this.Header.State = from.Header.State; this.Header.Tags = from.Header.Tags; this.Header.SEOTags = from.Header.SEOTags; this.Header.UpdatedDate = from.Header.UpdatedDate; this.Content = from.Content; // Copy the files in (not by reference) this.Files = new List <BlogFile>(); from.Files.ForEach(file => { this.Files.Add(new BlogFile() { Content = file.Content, Filename = file.Filename, Tags = file.Tags, Title = file.Title }); }); // Return itself after the copy in return(this); }
private const String blogUserFilename = "{0}.xml"; // The file name for the user details /// <summary> /// Override for the base delete functionality /// </summary> /// <returns></returns> public override Boolean Delete(IList <IBlogHeader> items, Boolean permanent) { try { // List of filename to remove should it be a hard delete (done before becuase the // items won't exist in the index after the base method call) List <String> filesToDelete = permanent ? ((List <IBlogHeader>)items).Select(x => BlogItemFilename(x.Id)).ToList <String>() : null; // Any files attached to the blogs that might be removed if (permanent) { ((List <IBlogHeader>)items).ForEach( header => { // Get the item to check to see if there are any other files to remove IBlogItem item = base.Load(header); if (item != null) { item.Files.ForEach(file => DeleteFile(header.Id, file)); } } ); } // Call the base implementation to handle the headers etc. if (base.Delete(items, permanent)) { // Hard delete? Remove the files .. if (permanent && filesToDelete != null) { // Remove the blog files itself filesToDelete.ForEach(file => { try { // Attempt to delete the file from disk .. File.Delete(file); } catch { // Move to the next one if failed to delete, it has no real impact on the system } }); } // Save the index regardless on a hard or soft delete return(WriteBlogIndex()); } // Failed if it gets to here return(false); } catch (Exception ex) { throw BlogException.Passthrough(ex, new CouldNotRemoveBlogException(ex)); } }
/// <summary> /// None-helper signature of the blog item blog item editor /// </summary> /// <param name="item"></param> /// <param name="preview"></param> /// <param name="viewModel"></param> /// <returns></returns> public static IHtmlContent BlogAttachments(IBlogItem item, BlogViewModelBase viewModel) => ContentFill(BlogViewTemplatePart.Attachment_View, new List <BlogViewTemplateReplacement>() { new BlogViewTemplateReplacement(BlogViewTemplateField.Common_Controller_Url, viewModel.ControllerUrl, false), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_SEOUrlTitle, SEOUrlTitle(item.Header.Name), false), new BlogViewTemplateReplacement(BlogViewTemplateField.Attachments, EditAttachments(item, viewModel).GetString(), false) }, viewModel);
/// <summary> /// Build the singular attachment editor /// </summary> /// <param name="file">The file (attachment) to be displayed</param> /// <param name="viewModel">The view model that contains the relevant templates</param> /// <returns>The Html Content for the attachment editor</returns> private static IHtmlContent EditAttachment(IBlogItem item, BlogFile file, BlogViewModelBase viewModel) => ContentFill(BlogViewTemplatePart.Attachment_Item, new List <BlogViewTemplateReplacement>() { new BlogViewTemplateReplacement(BlogViewTemplateField.Common_Controller_Url, viewModel.ControllerUrl, false), new BlogViewTemplateReplacement(BlogViewTemplateField.Attachment_Title, file.Title, false), new BlogViewTemplateReplacement(BlogViewTemplateField.Attachment_Url, AttachmentUrl(item, file, viewModel), false) }, viewModel);
/// <summary> /// None-helper signature of the blog item blog item editor /// </summary> /// <param name="item"></param> /// <param name="preview"></param> /// <param name="viewModel"></param> /// <returns></returns> public static IHtmlContent BlogSEOHeader(BlogViewModelBase viewModel, IBlogItem item) => ContentFill(BlogViewTemplatePart.Blog_SEO_Header, new List <BlogViewTemplateReplacement>() { new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_Author, item.Header.Author, true), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_Name, item.Header.Name, true), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_Description, item.Header.Description, true), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_SEOTags, SEOKeywords(viewModel.CurrentBlog.Parameters.SEOSettings.Tags, item.Header.Tags), true) }, viewModel);
public void Save_New_BlogItem() { // Arrange // Act IBlogItem savedItem = fixture.Blog.Save(RandomBlogItem(false)); // Assert Assert.NotNull(savedItem.Header.Id); // Was a new id created for the object? }
public void Save_Existing_BlogItem() { // Arrange IBlogItem savedItem = fixture.Blog.Save(RandomBlogItem(false)); String newId = savedItem.Header.Id; // Get the Id // Act IBlogItem resavedItem = fixture.Blog.Save(savedItem); // Resave String resaveId = resavedItem.Header.Id; // Get the resaved Id // Assert Assert.Equal(newId, resaveId); // Is the origional Id the same as the resaved Id? }
public void Delete_Existing_BlogItem_Soft() { // Arrange IBlogItem savedItem = fixture.Blog.Save(RandomBlogItem(false)); String newId = savedItem.Header.Id; // Get the Id // Act Boolean deleteResponse = fixture.Blog.Delete(new List <IBlogHeader>() { savedItem.Header }, false); // Delete // Assert Assert.True(deleteResponse); }
/// <summary> /// Upload a file to the server /// </summary> /// <param name="blogItem">The blog item the file is attached to</param> /// <param name="title">The title of the attachment</param> /// <param name="file">The raw file to be attached</param> /// <returns>The blog file that was created </returns> public BlogFile UploadFile(IBlog blog, IBlogItem blogItem, String title, IFormFile file) { // The blog file to be returned BlogFile blogFile = null; // Make sure there is actually a file if (file != null) { if (blogItem != null) { // The content of the file ready to pass to the data provider Byte[] fileContent = null; // Empty by default // Create a memory stream to read the file using (MemoryStream memoryStream = new MemoryStream()) { file.CopyTo(memoryStream); // Copy the file in to a memory stream fileContent = memoryStream.ToArray(); // convert the steam of data to a byte array memoryStream.Close(); // It's in a using anyway but just incase } // Something to save? if (fileContent != null && fileContent.Length != 0) { // Get the content header ContentDispositionHeaderValue parsedContentDisposition = ContentDispositionHeaderValue.Parse(file.ContentDisposition); // Create the new blog file for saving blogFile = new BlogFile() { Content = fileContent, Filename = parsedContentDisposition.FileName.Replace("\"", ""), Tags = new List <String>(), Title = title ?? ("File: " + Guid.NewGuid().ToString()) }; // Add the file to the blog file list blogItem.Files.Add(blogFile); // Save the blog item and with it the new file blog.Save(blogItem); } } } // Saved so do the common redirect return(blogFile); }
public virtual IActionResult GetAttachment(String id, String fileId) { // Bytes to send back Byte[] content = null; // No content by default String contentType = BlogFile.DefaultMimeType; // Default content type is plain text String fileName = ""; // Default filename // Get the blog that is for this controller instance if (Current != null) { // Get the blog item IBlogItem blogItem = Current.Get(new BlogHeader() { Id = Current.Parameters.Provider.DecodeId(id) }); // Did the "Get" actually work? if (blogItem != null && blogItem.Header.Id != "") { // Get the blog item related to the request BlogFile blogFile = blogItem.Files.Where(file => file.Id == fileId).FirstOrDefault(); // Does this file exist under this blog item? if (blogFile != null) { // Populate the file class with the data from the provider blogFile = Current.Parameters.Provider.LoadFile(blogItem.Header.Id, blogFile); // Content was returned for this request? if (blogFile != null && blogFile.Id != "") { // Assign the varaibles for the return stream contentType = blogFile.ContentType; // Work out the content type for the header fileName = blogFile.Filename; // Get the origional filename content = blogFile.Content; // Get the returned content type // Return the content here return(File(content, contentType, fileName)); } } } } // Must have failed to have arrived here return(File((Byte[])null, BlogFile.DefaultMimeType, "")); }
/// <summary> /// Build the edit button for the blog item /// .. and determine whether it should even be visible for the user /// </summary> /// <param name="viewModel"></param> /// <returns>The html content for the edit button</returns> private static IHtmlContent BlogItemEditButton(IBlogItem item, BlogViewModelBase viewModel) { // Do we have someone logged in and are they an admin user? if (viewModel.CurrentUser != null && viewModel.CurrentUser.IsAdmin) { // Return the content as there is a user logged in and they are an admin user return(ContentFill(BlogViewTemplatePart.Blog_EditItem_Button, new List <BlogViewTemplateReplacement>() { new BlogViewTemplateReplacement(BlogViewTemplateField.Common_Controller_Url, viewModel.ControllerUrl, false), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_Id, item.Header.Id, true) }, viewModel)); } else { return(new HtmlContentBuilder()); // No content as not logged in } }
/// <summary> /// None-helper signature of the blog item rendered (picks up the template for the item from the current view) /// </summary> /// <param name="item"></param> /// <param name="preview"></param> /// <param name="viewModel"></param> /// <returns></returns> public static IHtmlContent BlogItem(IBlogItem item, BlogViewModelBase viewModel) => ContentFill(BlogViewTemplatePart.Blog_Item, new List <BlogViewTemplateReplacement>() { new BlogViewTemplateReplacement(BlogViewTemplateField.Common_Controller_Url, viewModel.ControllerUrl, false), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_Author, item.Header.Author, true), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_Description, item.Header.Description, true), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_Id, item.Header.Id, true), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_Name, item.Header.Name, true), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_PublishedDate, item.Header.PublishedDate.ToCustomDate(viewModel.DisplaySettings.DateFormat), true), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_State, item.Header.State.GetDescription(), true), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_UpdatedDate, item.Header.UpdatedDate.ToCustomDate(viewModel.DisplaySettings.DateFormat), true), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_Content, item.Content, false), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_EditButton, BlogItemEditButton(item, viewModel).GetString(), false), new BlogViewTemplateReplacement(BlogViewTemplateField.BlogItem_SEOUrlTitle, SEOUrlTitle(item.Header.Name), false) }, viewModel);
public void Deserialize_Provides_AdditionalData() { // Arrange // What property are we going to add / check is put in the right place? KeyValuePair <String, JToken> propertyToCheck = new KeyValuePair <String, JToken> ( "AddedProperty", JToken.FromObject("Added Value") ); // Set up the dictionary of properties we expect to see IDictionary <String, JToken> expectedAdditionalData = new Dictionary <String, JToken>() { { propertyToCheck.Key, propertyToCheck.Value } }; // Generate the new blog to use to save blog items IBlog blog = new Blog( new BlogParameters() { Id = "TestBlogId", Provider = new BlogMemoryProvider() }); IBlogItem blogItem = blog.Save(new BlogItem() { }); // Save the blog item to make sure it is safe String output = JsonConvert.SerializeObject(blogItem, Formatting.Indented); // Serialize it JObject jsonObject = JObject.Parse(output); // Parse the output back as a generic JObject JObject header = (JObject)jsonObject["Header"]; // Get the header section to work with // Act header.Property("State") .AddAfterSelf(new JProperty(propertyToCheck.Key, propertyToCheck.Value)); // Add the new property in BlogHeader deserializedItem = JsonConvert.DeserializeObject <BlogHeader>(header.ToString()); // Deserialize // Assert Assert.Equal(expectedAdditionalData, deserializedItem.AdditionalData); // Are the dictionaries equal to what we expect? }
/// <summary> /// Build the attachment editing content /// </summary> /// <param name="item">The blog entry to get the attachments from</param> /// <param name="viewModel">The view model that contains the relevant templates</param> /// <returns>The Html Content of the attachment editor</returns> private static IHtmlContent EditAttachments(IBlogItem item, BlogViewModelBase viewModel) { // Create a content builder just to make the looped items content HtmlContentBuilder attachmentBuilder = new HtmlContentBuilder(); // Loop the results and create the row for each result in the itemsBuilder item.Files.ForEach( file => { attachmentBuilder.AppendHtml(EditAttachment(item, file, viewModel)); } ); // Call the standard content filler function return(ContentFill(BlogViewTemplatePart.Attachments, new List <BlogViewTemplateReplacement>() { new BlogViewTemplateReplacement(BlogViewTemplateField.Attachment_List, attachmentBuilder.GetString(), false) }, viewModel)); }
/// <summary> /// Load the item from disk /// </summary> /// <param name="request">The header of the item that is to be loaded</param> /// <returns>The blog item that was found</returns> public override IBlogItem Load(IBlogHeader request) { try { // Get the header record part from the base load IBlogItem headerOnly = base.Load(request); // Did it give us a valid header to now go and load the content from disk? if (headerOnly.Header.Id != "") { return(ReadBlogItem(headerOnly.Header)); } // Only should get to here if something has gone wrong throw new CouldNotLoadBlogException(); // Failed to load the content so error } catch (Exception ex) { // Something went wrong, explain why throw BlogException.Passthrough(ex, new CouldNotLoadBlogException(ex)); } }
/// <summary> /// Save a blog item /// </summary> /// <param name="item">The item to be saved</param> /// <returns>The item once it has been saved</returns> public virtual IBlogItem Save(IBlogItem item) { // Define the response IBlogItem response = null; // Check and see if the blog item exists in the local item list first IBlogItem foundItem = items.Headers.Where(x => x.Header.Id == item.Header.Id).FirstOrDefault(); if (foundItem == null) { item.Header.Id = NewId(); // Generate a new Id and assign it items.Headers.Add((BlogItem)item); // Add the item response = item; // Assign the data to the response } else { foundItem.Copy(item); // Copy the data in (don't repoint the reference) response = foundItem; // Assign the data to the response } // Return the item back to the caller return(response); }
public IActionResult FileBrowserUpload(String id, String CKEditorFuncNum, String Source, [FromForm] IFormFile Upload) { // The file to be attached CKEditorUploadResponse result = new CKEditorUploadResponse() { }; // Get the blog that is for this controller instance if (Current != null) { // Get the blog item IBlogItem blogItem = Current.Get(new BlogHeader() { Id = Current.Parameters.Provider.DecodeId(id) }); if (blogItem != null) { // Which editor was requested? switch (Source) { // Was CK Editor being used? If so set certain properties of the view model case "CKEditor": // If the file upload is goodthen BlogFile file = UploadFile(Current, blogItem, Upload.FileName, Upload); result.Uploaded = 1; result.Filename = Upload.FileName; result.Url = HtmlHelpers.AttachmentUrl(blogItem, file, ControllerName); break; } } } // Return the object as the result return(Json(result)); }
public IActionResult FileBrowser(FileBrowserRequest request) { FileBrowserViewModel browserModel = new FileBrowserViewModel() { }; // Get the blog that is for this controller instance if (Current != null) { // Set the browser templates browserModel.Templates = Current.Templates.ContainsKey(BlogControllerView.FileBrowser) ? Current.Templates[BlogControllerView.FileBrowser] : new BlogViewTemplates(); // Get the blog item IBlogItem blogItem = Current.Get(new BlogHeader() { Id = Current.Parameters.Provider.DecodeId(request.id) }); if (blogItem != null) { // Set the blog item for the returning view model browserModel.Item = blogItem; // Which editor was requested? switch (request.Source) { // Was CK Editor being used? If so set certain properties of the view model case "CKEditor": break; } } } return(View(this.ViewLocation("filebrowser"), browserModel)); }
/// <summary> /// Wrapper for the underlaying renderer for the blog item SEO items using the current "view" template /// </summary> /// <param name="helper">The HtmlHelper reference to extend the function in to</param> /// <param name="item">The item to be rendered</param> /// <param name="preview">Display in "prevew" mode for indexes etc.</param> /// <returns>The Html String output for the helper</returns> public static IHtmlContent BlogSEOHeader(this IHtmlHelper helper, IBlogItem item) => BlogSEOHeader(GetModel(helper), item);
/// <summary> /// Base implementation of the attachment url for putting together the relative path /// </summary> /// <param name="item">The blog item</param> /// <param name="file">The file in the blog item to link to</param> /// <param name="ControllerName">The name of the controller to be linked to</param> /// <returns></returns> public static String AttachmentUrl(IBlogItem item, BlogFile file, String ControllerName) => $"{FormatControllerName(ControllerName)}/item/{item.Header.Id}/attachment/{file.Id}";
/// <summary> /// The translated attachment url (Will not be direct but /// through a controller to relay the data) /// </summary> /// <param name="item">The blog item the file is attached to</param> /// <param name="file">The file to provide the url for</param> /// <param name="viewModel">The view model that containers the controller base url (incase there are multiple blogs)</param> /// <returns>The url for the file attachment</returns> public static String AttachmentUrl(IBlogItem item, BlogFile file, BlogViewModelBase viewModel) => AttachmentUrl(item, file, viewModel.RelativeControllerUrl);
//Save the Feed to Sitecore private void ProcessNewBlogItem(IBlogItem doc) { string message = string.Format("Creating New Item [docId:{0}] - \"{1}\"", doc.Id, doc.BlogTitle); Sitecore.Diagnostics.Log.Error(message, "RssFeedImport"); IBlogItem blog = null; var masterDb = Database.GetDatabase("master"); var item = masterDb.GetItem("/sitecore/system/Modules/RSSFeedSettings"); Sitecore.Data.Fields.LinkField linkField = item.Fields["BlogLocation"]; Guid folderTemplateId = IBlog_FolderConstants.TemplateId.Guid; DateTime rsspubdate = new DateTime(); if (doc.BlogDisplayDate != null) { rsspubdate = System.Convert.ToDateTime(doc.BlogDisplayDate.ToString()); } ; var year = rsspubdate.Year; var month = rsspubdate.Month; var rootItemId = new ID(new Guid(BlogFeedLocId)); var parentPubItem = masterDb.GetItem(rootItemId); var yearFolder = BlogImportHelper.EnsureChildFolder(parentPubItem, year.ToString(), folderTemplateId); var monthFolder = BlogImportHelper.EnsureChildFolder(yearFolder, month.ToString("00"), folderTemplateId); using (new Sitecore.SecurityModel.SecurityDisabler()) { var itemname = ItemUtil.ProposeValidItemName(doc.BlogTitle); var blogItem = monthFolder.Add(itemname, new TemplateID(IBlogItemConstants.TemplateId)); var db = Sitecore.Configuration.Factory.GetDatabase("master"); if (db != null) { if (blogItem != null) { blogItem.Fields.ReadAll(); blogItem.Editing.BeginEdit(); try { //Should be able to add name here blogItem.Fields["BlogID"].Value = doc.BlogID; blogItem.Fields["BlogTitle"].Value = doc.BlogTitle; blogItem.Fields["BlogAbstract"].Value = doc.BlogAbstract; blogItem.Fields["BlogDisplayDate"].Value = doc.BlogDisplayDate; blogItem.Fields["BlogSourceUrl"].Value = doc.BlogSourceUrl; } catch (Exception ex) { Sitecore.Diagnostics.Log.Error("Error while creating the New Item: " + BlogName + ": " + ex.Message, "RssFeedImport"); } blogItem.Editing.EndEdit(); } } } }
/// <summary> /// Save a blog item /// </summary> /// <param name="item">The item to be saved</param> /// <returns>The item once it has been saved</returns> public override IBlogItem Save(IBlogItem item) { try { // New Item? Boolean isNew = (item.Header.Id ?? "") == ""; // The base class will save the item to the in-memory header // so we don't want to pass the content in to this. We only want to save // the content to the file, so copy and update the item without the content // to the index IBlogItem headerRecord = item.Duplicate(); headerRecord.Content = ""; // Remove the content from being saved to the header record headerRecord.Files = new List <BlogFile>(); // The header record doesn't need the file listing for the header record only IBlogItem response = base.Save(headerRecord); // Make sure we have an Id // Successfully saved? if (response != null && response.Header != null && response.Header.Id != "") { // Make sure that the origional record that is about to be writen has an associated Id with it item.Header.Id = response.Header.Id; // If we have any file attachments to save we need to do this now // If the item.Files is blank then see if we already have files to attach if (item.Files != null) { item.Files.ForEach(file => { // Anything to write? if (file.Content != null && file.Content.Length > 0) { file = SaveFile(item.Header.Id, file); } }); } else { // Sort out the file array if (isNew && item.Files == null) { item.Files = response.Files = new List <BlogFile>(); } else if (!isNew && item.Files == null) { // Get the old blog back again to get the file listing etc. response = Load(response.Header); item.Files = new List <BlogFile>(); if (response != null && response.Header != null && response.Header.Id != "") { item.Files.AddRange(response.Files); } } } // Write the blog item to disk if (WriteBlogItem(item)) { // Try and save the header records to disk so any updates are cached there too if (WriteBlogIndex()) { return(response); } } } } catch (Exception ex) { throw BlogException.Passthrough(ex, new CouldNotSaveBlogException(ex)); } // Got to here so must have failed throw new CouldNotSaveBlogException(); }
/// <summary> /// Write a blog item to disk so it can be retrieved later /// </summary> /// <param name="blogItem">The Blog Item to be saved</param> private Boolean WriteBlogItem(IBlogItem blogItem) => Write <IBlogItem>(BlogItemFilename(blogItem.Header.Id), blogItem);
/// <summary> /// Wrapper for the underlaying renderer for the blog item editor /// </summary> /// <param name="helper">The HtmlHelper reference to extend the function in to</param> /// <param name="item">The item to be rendered</param> /// <param name="preview">Display in "prevew" mode for indexes etc.</param> /// <returns>The Html String output for the helper</returns> public static IHtmlContent BlogEditItem(this IHtmlHelper helper, IBlogItem item) => BlogEditItem(item, GetModel(helper));
/// <summary> /// Wrapper for the underlaying renderer for the file browser for a given blog item /// </summary> /// <param name="helper">The HtmlHelper reference to extend the function in to</param> /// <param name="item">The item to be rendered</param> /// <returns>The Html String output for the helper</returns> public static IHtmlContent FileBrowser(this IHtmlHelper helper, IBlogItem item) => BlogAttachments(item, GetModel(helper));