Microsoft Cloud Authors: Pat Romanski, Andreas Grabner, Nick Basinger, Kevin Benedict, Liz McMillan

Related Topics: Microsoft Cloud

Microsoft Cloud: Article

Corporate Wiki Part 3: Files Up and Down - Adding More Features

Corporate Wiki Part 3: Files Up and Down - Adding More Features

  • Corporate Wiki Part 1: Building Your First Wiki Parser
  • Corporate Wiki Part 2: Writing Your Own Wiki Search Engine

    Perhaps the greatest benefit of the Wiki is that everyone may equally participate in the creation of content, establishing a shared consciousness. While the common Wiki excels in telling, it is rather weak when it comes to showing. In a world of images and animation, the plain text presentation of the Wiki is not enough in the corporation.

    In today's office environment, content is produced with images and documents in a variety of file formats. A corporate Wiki needs to be able to display images and make documents available to users in their original format. Mixing images with text is indisputably more powerful than plain text alone in communicating ideas and information. In this article, part three of a series (see .NETDJ, Vol. 2, issues 1 and 3 for the earlier articles), I will add the image and file handling features required (see Figure 1).

    First question: What do I need? The corporate Wiki has to provide a way for users to easily upload and manage files, including images that may be displayed in a topic without knowing how to write the <img> HTML to make that happen. And, of course, there has to be some way to store and retrieve these files.

    I also need a strategy for making these files available in a Wiki topic, displaying images, and linking to files for downloading. A simple text reference to an image will display the image in the topic page and a reference to the same image followed by a URL will link that image to the URL. A slightly different reference to a given uploaded file will present a link that will allow the reader to download or open the file.

    First, I want to know where these files are going. In the first Wiki I built with a files feature, I used the file system but ran into the mess of granting the ASP.NET account write access to the hard drive. Since this practice is often discouraged by corporate IIS server administrators, I decided to store my uploaded files in this project directly in the database. Initially, for simplicity, there is only one "folder" in which to upload files, but having the files in the database rather than the physical file system allows me to add a folder system to the application and the data structures without having to rearrange and move physical files.

    To the database I have added the WikiFile table, which contains four columns: FileName, a varchar(255); FileSize, an int; FileDate, a smalldatetime; and FileData, an image column. Along with the table, there are five new stored procedures for accessing the WikiFile table: GetWikiFileNames, GetWikiFile, RenameWikiFile, AddWikiFile, and DeleteWikiFile (see the stored_procs.sql file in the source code; available online at www.sys-con.com/dndj/sourcec.cfm). Each of these has a corresponding method in the DataAccess class.

    With the database prepared to store and retrieve files, I created the files.aspx page and a link to that page from the view and viewversion pages. The files.aspx page contains a DataList control to display the files that have been uploaded while providing links to rename, delete, or download the file. The list also displays the date and time the file was added to the Wiki and the size of the file in kilobytes (see Figure 2).

    The DataList control has header, item, alternating item, and edit item templates defined. The control also specifies style templates for each of these. With the HTML and ASP.NET controls specified in the templates, it's time to hook up the code behind with code to bind the list to the DataSet returned by the GetWikiFileNames method in the DataAccess class and to handle the ItemDataBound and ItemCommand events.

    The FillFileList method is called when the page is not a postback (see Listing 1; for space reasons, the code is online at www.sys-con.com/dotnet/sourcec.cfm). The DataSet is created and filled using the DataAccess class, and the DataList object's data source is set and it's DataBind method is called. Now the rest of the work is left to the ItemDataBound event handler.

    The DataList1_ItemDataBound method handles this event by first identifying the type of item being handled. For an item or alternating item, the controls of the template are found and bound to the data in the item's DataItem property (see Listing 2). The rename and delete LinkButtons get their command argument and name set to allow easy handling of the ItemCommand event, which is fired when either of these link buttons are clicked on any given row.

    If the item type is an edit item and the EditItemIndex property is set to anything but a negative one, the edit item template's controls are bound. This sets up the rename form (see Listing 3). The form has two buttons defined and bound with the name of the file in their CommandArgument properties for use when the button is clicked in the ItemCommand event. The code also assigns the CommandName to each button, which identifies which button was clicked in the postback event handler.

    The DataList1_ItemCommand method, essentially the click event handler for all of the DataList's clickable controls, contains switch code for the four possible commands: rename, delete, saverename, and cancelrename (see Listing 4). Each of these are easily handled within the switch statement except saverename, which is handled in part within the switch statement and in part by the RenameFile method (see Listing 5).

    In the files.aspx HTML template, just above the DataList, I have placed the file upload form, which consists simply of an HTML input control with its type element set to "file" in order to produce the file open dialog browse button in the page. This control's runat element is set to "server" and the code-behind declares a protected instance of HtmlInputFile called postFile.

    The main form tag in the page has its enctype element set to "multipart/form-data," allowing the selected file to be sent to the server. And finally, there is a simple Button control called btnUpload to do the sending.

    The btnUpload_Click method handles this Button's click event, storing the uploaded file in the database and handling validation (see Listing 6). ASP.NET makes it very easy to work with uploaded files using the HtmlInputFile object called postFile, which contains a property called PostedFile of type HttpPostedFile. The PostedFile property contains everything you need to work with the uploaded file.

    The first thing to do is some basic validation. I check to see if a file has indeed been uploaded. If not, the lblMsg Label control's Text property is set and the method returns without saving anything to the database. Similarly, I check for a specific size limitation, though you would not have to implement this validation if you wish to rely entirely on ASP.NET's maxRequestLength configuration parameter (more about this later).

    Once the validations have completed, I add the file to the database. The filename is extracted from the FileName property, which contains the entire path of the file that was uploaded. A byte array is created using the posted file's ContentLength for its size. The posted file's InputStream is used to read the file into the byte array, which is then passed as a parameter to the DataAccess object to save the file in the database.

    The files are now in the database and ready to retrieve in a Wiki topic using the parser, extended with a few new formatting rules (see Table 1). The FormatImages method in the parser handles most of these (see Listing 7). In addition, there are two additions to the FormatHyperLinks method to handle a linked floating image and to deal with simple file links (see Listing 8). To hook it all up, a call to the FormatImages method is placed in the FormatStandardWikiLine method in the parser. Space limitations prevent a full discussion of the regular expressions used in the new parser code, so you will have to examine them on your own.

    The additions to the parser result in HTML links to either the getimage. aspx page or the getfile.aspx page. Neither of these pages contain HTML. Their functionality is contained strictly in the code behind. I have no extensive experience in sending binaries to the browser, nor was I able to find a clear solution example when I first tackled this problem just over a year ago. After some research and trial and error, I was able to create the GetImage and DownloadFile methods (see Listings 9 and 10). The main difference between the two are the response headers and the Download File method's code to deal with the Range request header and the 206 response status code.

    To avoid chatting up the database too much on a busy corporate Wiki server, I thought to explore the idea of storing images retrieved by the getimage.aspx page in a weak reference object maintained in a hashtable using the file name as the key. This would have the effect of caching the images indefinitely, but I decided against spending the time and space to experiment with that. On the other hand, a simpler approach would use ASP.NET's Cache object to store the image byte arrays, eliminating unnecessary trips to the database.

    The last change to the project is with the edit.aspx page, which has been updated with code that fills two select lists with the names of the files that have been uploaded. One contains all the files and the other contains only those files with a .GIF or .JPG extension. JavaScript allows the user to insert a reference to a file or image while editing simply by selecting the file they wish to use. The new formatting rules are noted in the help text on the edit page as well.

    Handling Large Files
    Uploading files using ASP.NET has its limits. The files, while being uploaded and handled, are kept entirely in the server's memory. If memory runs too low, the aspnet_wp.exe process will be restarted and you will lose any uploads in progress. Therefore, the file size should be limited. By default, ASP.NET limits this size to 4MB in the machine.config file's maxRequestLength element of the httpRuntime node in the system. web node.

    You will have to balance the maximum size requirements of your users with the capacity of your server to handle the volume of uploaded files you experience. If you cannot find that balance and you require the ability to upload much larger files, you should explore one of the many affordable commercial file upload utilities (see Resources).

    A Word About Security
    In any corporate intranet application, certain security precautions and protocols are required. These vary based on your target users and your own corporate policies. There are many ways to secure your application and many fine books and articles available to help you achieve the security you need. Just remember that the concept of the Wiki fosters free and open discourse, so keep that in mind when implementing any security scheme for your corporate Wiki.

    Final Thoughts
    Nearly two years ago, I put into place a simpler Wiki for my department. I was then transferred to another department and lost track of that Wiki. Just a few weeks ago, I received a phone call from someone there because the server had been taken down and they were desperate to get their Wiki back. Once your users adopt the Wiki, they won't want to let go.

    Simplicity is the key. If collaboration and knowledge management can be achieved easily and simply with virtually zero cost, you owe it to yourself to give Wiki a try.

    This concludes this three part series on building a corporate Wiki. Now go out and get busy on your Wiki today.


  • .NET File Uploader: www.mediachase.com
  • ABCUpload .NET: www.websupergoo.com
  • FileUp: www.softartisans.com
  • AspUpload: www.aspupload.com
  • More Stories By Tyler Jensen

    Engrossed in enterprise application architecture and development for over ten years, Tyler Jensen is a senior technical consultant in a large health intelligence company, designing and developing claims processing and analysis software. In his spare time he does a little writing and outside consulting.

    Comments (0)

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.

    IoT & Smart Cities Stories
    Moroccanoil®, the global leader in oil-infused beauty, is thrilled to announce the NEW Moroccanoil Color Depositing Masks, a collection of dual-benefit hair masks that deposit pure pigments while providing the treatment benefits of a deep conditioning mask. The collection consists of seven curated shades for commitment-free, beautifully-colored hair that looks and feels healthy.
    The textured-hair category is inarguably the hottest in the haircare space today. This has been driven by the proliferation of founder brands started by curly and coily consumers and savvy consumers who increasingly want products specifically for their texture type. This trend is underscored by the latest insights from NaturallyCurly's 2018 TextureTrends report, released today. According to the 2018 TextureTrends Report, more than 80 percent of women with curly and coily hair say they purcha...
    The textured-hair category is inarguably the hottest in the haircare space today. This has been driven by the proliferation of founder brands started by curly and coily consumers and savvy consumers who increasingly want products specifically for their texture type. This trend is underscored by the latest insights from NaturallyCurly's 2018 TextureTrends report, released today. According to the 2018 TextureTrends Report, more than 80 percent of women with curly and coily hair say they purcha...
    We all love the many benefits of natural plant oils, used as a deap treatment before shampooing, at home or at the beach, but is there an all-in-one solution for everyday intensive nutrition and modern styling?I am passionate about the benefits of natural extracts with tried-and-tested results, which I have used to develop my own brand (lemon for its acid ph, wheat germ for its fortifying action…). I wanted a product which combined caring and styling effects, and which could be used after shampo...
    The platform combines the strengths of Singtel's extensive, intelligent network capabilities with Microsoft's cloud expertise to create a unique solution that sets new standards for IoT applications," said Mr Diomedes Kastanis, Head of IoT at Singtel. "Our solution provides speed, transparency and flexibility, paving the way for a more pervasive use of IoT to accelerate enterprises' digitalisation efforts. AI-powered intelligent connectivity over Microsoft Azure will be the fastest connected pat...
    There are many examples of disruption in consumer space – Uber disrupting the cab industry, Airbnb disrupting the hospitality industry and so on; but have you wondered who is disrupting support and operations? AISERA helps make businesses and customers successful by offering consumer-like user experience for support and operations. We have built the world’s first AI-driven IT / HR / Cloud / Customer Support and Operations solution.
    Codete accelerates their clients growth through technological expertise and experience. Codite team works with organizations to meet the challenges that digitalization presents. Their clients include digital start-ups as well as established enterprises in the IT industry. To stay competitive in a highly innovative IT industry, strong R&D departments and bold spin-off initiatives is a must. Codete Data Science and Software Architects teams help corporate clients to stay up to date with the mod...
    At CloudEXPO Silicon Valley, June 24-26, 2019, Digital Transformation (DX) is a major focus with expanded DevOpsSUMMIT and FinTechEXPO programs within the DXWorldEXPO agenda. Successful transformation requires a laser focus on being data-driven and on using all the tools available that enable transformation if they plan to survive over the long term. A total of 88% of Fortune 500 companies from a generation ago are now out of business. Only 12% still survive. Similar percentages are found throug...
    Druva is the global leader in Cloud Data Protection and Management, delivering the industry's first data management-as-a-service solution that aggregates data from endpoints, servers and cloud applications and leverages the public cloud to offer a single pane of glass to enable data protection, governance and intelligence-dramatically increasing the availability and visibility of business critical information, while reducing the risk, cost and complexity of managing and protecting it. Druva's...
    BMC has unmatched experience in IT management, supporting 92 of the Forbes Global 100, and earning recognition as an ITSM Gartner Magic Quadrant Leader for five years running. Our solutions offer speed, agility, and efficiency to tackle business challenges in the areas of service management, automation, operations, and the mainframe.