Umbraco Contour as an AdHoc database with CSV export

June 19, 2014

This is an old archived post, content maybe out of date, links may be broken and layout may be broken.

We love Umbraco Contour at Moriyama, the power that it gives editors to create and quickly roll out forms.

Sometimes though it isn’t quite the right fit. From time to time we want to roll out a form that isn’t editable by users, that has a complex integration that doesn’t merit the creation of contour custom field type or workflow.

Also, sometimes our client side guys can’t quite live with the GUID input field identifiers and inline JavaScript that contour can somehow generate.

It is easy enough to implement a nice clean, well marked up form in Umbraco, but the killer feature of Contour that you lose is CSV export. Our customers love that they can grab this data in a spreadsheet at any time of day or night and quickly see who has filled out a form in the last 20 minutes.

But do we really want to implement custom dashboards that allow CSV exports of custom database tables? Does anyone enjoy writing SQL? Well I can’t stand it.
We decided to keep the back office part of contour and create our own customer facing forms.

Using MVC we have a model that is effectively a POCO so we just wrote the glue that stuffs the POCO into a Contour record.

All you have to do is create a Contour form with field names that match your POCO and call the method with this signature (Full code later).

public void RegisterPocoInContour(Guid formGuid, int nodeId, string ip, object poco)

You’ll quickly realise that this technique doesn’t need to be limited to form submissions – you can stuff any old POCO into a Contour record allowing the end user to export it. A word of warning, this isn’t particularly performant and you wouldn’t want to do it several times within the context of a single request, not would you want to hammer it on a high traffic site.

So finally, the full code snippet.

public void RegisterPocoInContour(Guid formGuid, int nodeId, string ip, object poco)
	//The Form
    var recordStorage = new RecordStorage();
    var formStorage = new FormStorage();
    var form = formStorage.GetForm(formGuid);

    var recordService = new RecordService(form);

    var record = recordService.Record;
    record.IP = ip;
    record.UmbracoPageId = nodeId;
    recordStorage.InsertRecord(record, form);

    foreach (var field in recordService.Form.AllFields)
		var caption = field.Caption.Replace(" ", "");
		var rgx = new Regex("[^a-zA-Z0-9 -]");
		caption = rgx.Replace(caption, "");

		if (poco.GetType().GetProperty(caption) == null) continue;

		var propertyValue = poco.GetType().GetProperty(caption).GetValue(poco, null);

		if (propertyValue != null)
			var key = Guid.NewGuid();
			var recordField = new RecordField
				Field = field,
				Key = key,
				Record = record.Id,
				Values = new List<object> { propertyValue }

			var recordFieldStorage = new RecordFieldStorage();
			record.RecordFields.Add(key, recordField);


If this isn’t your cup of tea, I’ll be writing soon on how to automatically add tables to your Umbraco database on startup, by defining a POCO and having the schema automatically created. I’ll also demonstrate how to quickly populate the generated tables using PetaPoco, which is utilised by Umbraco core.

Leave a Comment

Comments are manually moderated and added once reviewed.

© 2021 Darren Ferguson, Built with Gatsby.