måndagen den 7:e april 2014

Dynamic forms - with a keep it simple approach

Wouldn't it be cool if editors just could drag-and-drop input fields and rearrange the design of forms in EPiServer? I can almost hear you say: XForms. Yes, I've heard about it. I have written a fair amount of code using the good ol' built in EPiServer feature. I have even succeeded in taming the XForm Beast to obey the simple rules of MVC (with help from you great bloggers out there). But that is a different story.

What about the forms that need other features than the ones provided by EPiServer XForms?

An example scenario:
We want to collect user input by using a web based form. The input data should be passed on to a back end system for processing, and should not be stored in the EPiServer database at all. Additionally, the editors want to create different campaign pages with different forms. The editors want to A/B test the campaign pages - to learn how to reshape and adjust the form to maximize conversion rates. Can this be done with EPiServer?

Here's a simple solution: blocks.
(check out the full example at GitHub)

The Input Block
Let's write a block type that can be used in forms all over the site. Instances of the block type will behave in different ways, when used in different contexts. To succeed with that, each instance of the block type need to have really good answers to some existential questions:

What am I?

Where do I belong?

How should I act in public?

The answers come in the form of categories. It doesn't have to be like that, It's just me. I think categories are cool. They remind me of twitter hash tags (I think twitter hash tags are cool too).


What am I? (Field) Where do I belong? (Group) How should I act? (Behaviour)


This instance is a "first name" input field, existing in a "user" context,
with user input set to required.


The View
Now we have the answers to the deep questions asked earlier and can write the user interface. 


The example code has some convenience methods, 
such as generating the input field name based on the categories.


Html output generated with data from the model (the block type).
A server side regular expression pattern is also passed on to the client.


The Validation
What about validation? Dynamic forms are by nature quite unpredictable. But we know about the behaviour of the individual block, and can use that knowledge to write both custom client and server validation. In this example I am using the Zurb Foundation Abide framework to perform client script validation. 


Custom validator added to the Abide framework, 
specialized in validating first name input fields. 
The name of the validator is the value of the selected subcategory for "Field".

"David" is valid. Nice to know.


This example code has two types of server validation. First up is the data annotations defined in the model. Secondly (if necessary) there is also the ability to perform custom validation. What validator to use is determined by the block behaviour (the categories), just like selecting the client validator. Here is where specialized validation takes place, such as dependencies between individual fields in the posted form.



Form data posted to the controller action method.


Going through each item in the page content area,
find the appropriate validator and execute the validation method. 
The model is passed to the validator.


That's it.

Check out the example code at GitHub. To get up and running you need to create an EPiServer 7.5 database and (of course) configure the connectionstrings file.

I really want your feedback on this. 

Please post your comments here or contact me on Twitter.

måndagen den 17:e mars 2014

Quick Start: EPiServer 7.5 & mvc - the minified version

What is EPiServer and what does EPiServer 7.5 do? 

I (think) that I have aswered those questions during lunch hour today here at Knowit in Stockholm. 

This video - in swedish - is a minified version of my talk & live coding about the CMS, using asp.net mvc to demo how page types, properties, editor features and pages are wired together (without complicating things too much).

Do you have feedback about this presentation? Please contact me by writing a comment at this blog post or at twitter.


söndagen den 9:e mars 2014

You might not need JavaScript

Are you about to code some awesome web stuff and have JavaScript enabled in your browser?

Turn that sh*t off!!!

Okay. Easy now.

I really like JavaScript. I like it even more than I like C#. There, I said it. And I mean it.

JavaScript is cool. JavaScript is freedom. Freedom from static typing, classes and compilation. Just code, save & browse. JavaScript is the language that help us deliver great things for the web. But what would happen if you would turn scripting off in the browser?

Oops. Dude, I can't do a thing on this web site.

Before we try to write the great things, I think we should begin to write stuff that just works. Focus on functionality. The features. Write code with quality built in from the start and without scripting dependencies. How about calling it NoScript First?

NoScript First is a development style, just like Test Driven Development and Mobile First.

Based on code I've read and written over the years I think far too many of us (myself included) misses things that really need to be there on the server: stuff like validation, security, unit tests and limiting allowed http methods. How come?

I think it is because we are humans (yes, coders are humans too). We like shortcuts. When a shortcut appear, we take it. Some shortcuts are great, some are not. Doing client script form validation, and not really testing if the server does the correct job is one of the really bad ones.

Enough.

Here's an example: a web page with user input to be sent, by posting a form to the server.

Turn JavaScript off and write the html (the view).


@using (Html.BeginForm("Add", "Home", FormMethod.Post))
{
    @Html.AntiForgeryToken()
    @Html.TextBoxFor(model => model.Name)
    <input id="my-button" type="submit" value="Send"/>
}


Write the server code (the controller and the model). Make sure the user input is sanitized. Require an anti forgery token and limit the request to allow POST only.


[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Add(Person person)
{.....}

public class Person
{
    [MyRequiredAttributeThatSanitizesStrings]
    public string Name { get; set; }
}


Try it, test it. Maybe even unit test it?
Turn JavaScript back on, hijack the submit event and do the great things.


$('#my-button').on('click', function (clickEvent) {
    clickEvent.preventDefault();
    // do the magic here
});


When you are done, try switching between JavaScript turned on and off. Do both ways work? Remember, keep it simple. NoScript First goes very well together with Test Driven Development, by the way.

Here is a full example asp.net mvc NoScript First project:
https://github.com/DavidVujic/blog/tree/master/NoScriptFirst


ps.
Check out some of my posts and videos on test driven development:
From the streets of test driven development: JavaScript
aspConf 2012 - Quick start: test driven development
ds.

måndagen den 30:e december 2013

FakeMaker - helping you with test driven EPiServer development

Test driven development and EPiServer?
Relax. Test driving the CMS actually got a whole lot easier with version 7. Most of the built in features are implementing interfaces and you can use asp.net mvc. Those ones are two really good friends of test driven development. However, creating that fake content and set up mocked repositories isn't really as smooth as it should (could) be, right?
When mocking code is all you see on your screen, this little library called FakeMaker may help you. Okay, a bigger screen also would, but is probably more expensive. With FakeMaker, you have two classes: FakeMaker and FakePage. The FakeMaker class takes care of the mocking and FakePage helps you create content.
Here's some examples.

Create an instance of FakeMaker:
var fake = new FakeMaker();

Create the pages you need:
var page = FakePage.Create("MyPageName");

or a page of a specific page type:
FakePage.Create<CustomPageData>("MyOtherPageName");

Add it to the mocked repository:
fake.AddToRepository(page);

You can now pass the fake repository to your code (also known as Dependency Injection) from the ContentRepository property or use the built in EPiServer ServiceLocator feature.

Please let me know what you think about it.

Check out the documentation, the examples and the source code:

You will also find FakeMaker at NuGet:

onsdagen den 18:e december 2013

Upgrading to EPiServer 7.5 - without the headache

Earlier today I managed to transform the day from huge #FAIL (with headache) to the good feeling of #SUCCESS (headache gone). Oh, this is not twitter. Sorry, I forgot. 

The project I'm involved in currently, we develop an application with EPiServer 7 (it's actually 7.1 to be precise) and I personally enjoy the product being a lot more testable than ever before. Stay tuned for an upcoming post on test driven development with EPiServer. (and there goes the holidays ... why did I promise that?).

The latest version - 7.5 - was recently released and since we are at the beginning of the project there cannot be a better opportunity for an upgrade. So, we made the decision to at least give it a try.


There is an upgrade guide at the EPiServer World site, but I guess there are a couple of scenarios that the team over there did not try out. I have sent them feedback on this and some issues raised here will probably be solved shortly.


Have a look at the upgrade guide.

I suggest that you follow the upgrade guide along with the stuff I describe here. 


Before you start, I recommend that you take a copy of the database and use the copy when upgrading (don't forget to update the connectionstrings configuration file). 


The first impediment I ran into was that the installer failed because the site was using a VPP folder in an external share. Before you run the installer, copy the VPP folder to your local disk and update the episerverframework configuration file.


If you would wake up in the middle of the night and realize upgrading was a bad move, all you need to do is a rollback of the source code. You only messed up the copy of the database and the local VPP folder. Don't worry.

Follow the steps 1-9 in the guide.


The following step in the guide is about updating the assembly references. Here is a bug. In our project we have added the assemblies from the EPiServer NuGet feed and to update without the headache this what one need to do: right click the references folder, select "Manage NuGet packages" and navigate to the Installed packages folder. Uninstall the references to "EPiServer.CMS.Core" and "EPiServer.Search".


Next up is where I found the bug: when I browsed the new assemblies in the EPiServer feed and installed them, the reference to StructureMap had the wrong version and the code would not compile. What I did was to install StructureMap from the official NuGet feed first. Then I went back to the EPiServer NuGet feed and installed "EPiServer.CMS.Core" and "EPiServer.Search". The previously installed version of StructureMap was already there and was not overwritten.



Here is the version existing in the EPiServer NuGet feed.

Here is the newer version from the official NuGet feed.

The solution is ready to be built. Most likely the compilation will fail, because of the breaking changes of the 7.5 version. Step 12 in the guide is about making the source code changes.


One thing that I find confusing is the code existing in the EPiServer.UI assembly. We have written a custom report in this project and that needed to be updated. The new stuff to use is within the namespace EPiServer.Shell, but the actual assembly is EPiServer.UI. And that assembly isn't referenced when getting the stuff from the EPiServer NuGet feed. So, what did I do? Well, I picked up the local dll from the EPiServer installation folder (the 7.5 folder).

Confusing, isn't it?

Finally, the code actually compiles without any errors. Tadaa!

But wait. Don't browse the site! I did that. And it lead me to the wrong problem solving path. Headache. The site should actually not be browsable at this point, and that is fine. So, move on to the next step in the guide and run the update add-ons stuff from the Deployment Center.

By now, the upgrade is almost done. So close, and yet so far away. The next move is to migrate the VPP files into the new media system. The guide mentions the VPP Migration Tool. But where is it? Guys, a link to the download page from the guide would save us lots of time (and headache). Finally I found the tool at the download page for the CMS 7.5 page (the column to the right with the header "You might also want to download"). 

Almost done. Don't give up! Have a banana and drink some water.

It's time to follow another guide: Migrating VPP-based files to the new media system.

I added the classes GenericMedia, ImageFile and VideoFile. I still am not sure if that really was needed. The guide describes the code as just examples. To be safe I also regenerated the GUIDs with some help from Visual Studio.




The final impediment is the kind of problem that is so simple, but sometimes so difficult to see. I think it's about that tree and the forest, you know? The Migration Tool threw an exception when I tried to connect to the site. The exception was about not being allowed to use external assemblies. "What? Where? Who?"

Man, did I google to find a solution. Whew!

The executable file itself was blocked by Windows since it was a downloaded file. By right clicking it and selecting properties, the "Unblock" button will appear. Click it. Just do it. Run the Migration Tool again and you will finally be able to tweet #SUCCESS.

The things described here has been verified in two different virtual machines, one with Windows Server 2012 R2 and the other one with Windows 8.1 Pro.

Good night.