Anders G. Nordby

Lead Software Engineer at Sopra Steria

Monthly Archives: February 2014

EPiServer 7.5: Customer data parsed from Excel files

For a long time, I’ve been “locked” in a long-running EPiServer 6 R2 project, with lots of overtime – which means I’ve been forced to keep using old technology for about a year. Now, I’m in an EPiServer 7.5 project, and everything is new… I’ve never before used Visual Studio 2013, MVC, EPiServer 7.5 or Git in a project, so there’s much to learn! (I’ve been trying to fiddle a bit with new stuff on my own, but we all know there’s a huge difference between trying out and actually needing to do something.)

Enough of the rant; I found an interresting need that I thought I would share. The website I’m building will have various calculators (helping visitors to select the right product for them based on certain criteria), and the calculators themselves will be built as single-page apps in the front-end. The background data for the calculators will, in agreement with the front-end developer, be delivered as JSON data. However, the customer will support us with background data by delivering Excel files.

In EPiServer 7.5, all files (or pages for that matter) are IContent, meaning that we can add new fields to these files if we want to. And that is precisely what we want in this case! We create extra properties for a new filetype, which we simply call Excel:

using System.ComponentModel.DataAnnotations;
using EPiServer.Core;
using EPiServer.DataAnnotations;
using EPiServer.Framework.DataAnnotations;
using EPiServer.Web;
using MyNamespace.Web.Business.EditorDescriptors;

namespace MyNamespace.Web.Models.Media
    [ContentType(GUID = "63A4C976-973E-4065-A134-2BC443DFFBB8")]
    [MediaDescriptor(ExtensionString = "xls")]
    public class Excel : MediaData
        public virtual string JsonData { get; set; }

        public virtual string ParseLog { get; set; }

        public virtual bool ParsedOk { get; set; }

Then, in Global.asax we hook up to the uploading of the file, and parse the file here (the parsing will in real life of course be more complicated than shown here):

using System.Collections.Generic;
using System.IO;
using System.Web.Mvc;
using EPiServer;
using EPiServer.ServiceLocation;
using EPiServer.Web;
using MyNamespace.Web.Models.Media;

namespace MyNamespace.Web
    public class Global : EPiServer.Global
        protected void Application_Start()
            // Register Display Options
            var options = ServiceLocator.Current.GetInstance();
                .Add("full", "/displayoptions/full", ContentAreaTags.FullWidth, "", "epi-icon__layout--full")
                .Add("wide", "/displayoptions/wide", ContentAreaTags.TwoThirdsWidth, "", "epi-icon__layout--two-thirds")
                .Add("narrow", "/displayoptions/narrow", ContentAreaTags.OneThirdWidth, "", "epi-icon__layout--one-third");


            DataFactory.Instance.CreatingContent += UploadingFile;

        private void UploadingFile(object sender, ContentEventArgs e)
            if (e.Content is Excel)
                var excel = e.Content as Excel;
                excel.JsonData = "{json:true}";
                excel.ParseLog = "Parsing the file...\n";
                excel.ParseLog += "...done!";
                excel.ParsedOk = true;

                e.Content = excel;

The beauty of this approach is that the editors can just upload their files, and we’ll try to parse the files as they are uploaded. If the file parses correctly, the file can then be pointed to from the relevant page – and the already parsed JSON can be rendered to the front-end when we need it. If parsing fails, the ParsedOk flag will be false, which we can check during page validation. If the editors get a validation error on the Excel file they are trying to use, they can then check the ParseLog of the file, correct the errors, and upload the new version of the file. We as developers won’t need to keep track of any special directory for JSON files, or which JSON file corresponds to which Excel file, as everything is contained in one “package”.


UPDATE: I previously thought I needed to create an editor descriptor to make the fields readonly, but have now discovered that all I need is to use the [ReadOnly(true)] attribute.