This post breaks down a functionality which can send the content of a shopping cart, a basket as an e-mail. The functionality was build using Razor (C#), AJAX and JSON on top of a Dynamicweb content management system.
The customer has an eCommerce website where people add items to a basket. Sometimes the user may want to share the basket with others and there would require some way of doing that. The idea was to add a link which would then send the content of the basket to an e-mail.
Ideas about solving the task
Dynamicweb CMS is a .NET based system which offers several ways of extending the backend. It allows for custom backend .NET based code by adding assemblies that extend the system. That process requires that you code and compile a DLL which then is added to a bin folder on the web server. That is a process which requires that you know Dynamicweb Backend architecture well, and is a dedicated back-end developer.
The lighter path: C# Razor templates
For many functionalities it is the best and only way, however for light features like the send basket you may choose to write a simple C# Razor template. Razor is a format which somehow looks like “good old” ASP. It can contain a mixture of HTML and C# code in a “.cshtml” file. That is the path I choose to add the send basket functionality.
Breaking down the task
Which subtasks are required to build the solution? First lets start at the first description:
There should be a link which opens a dialogue box where the user can enter an receiver e-mail. There should then be a button which allows the user to submit the basket and inform the user when the e-mail has been sent.
The link to open the feature
The website exists in three languages, so everything needs to be translated in the template. This version shown here is in Norwegian. The layout of the link and button in this case has been created by an illustrator.
The popup dialogue
When the user sees this page there exists a basket to send as e-mail. The user can click on the envelope icon to open the dialogue where he can specify the receiver e-mail. It is a DIV with an input field and a send button:
The main page is greyed out and a centered dialogue box appears. The user can cancel the task by clicking the close icon. Using a HTML placeholder the input field has extra information guiding the user what to enter in the box. A big “send” icon to the right will send the basket using e-mail to the specified e-mail. The e-mail value is validated to ensure that a valid e-mail is entered.
A small tip: No FORM element, in order to avoid spam
One thing always to consider when adding user submission elements on a website is spam. This one has been protected using a simple trick: Add no FORM element, which may make the feature not so likely to be found by spam robots. The submit feature has been implemented using AJAX instead.
Receive the request to send a basket in back-end
The way I want to respond to the user is by creating a Dynamicweb page which will contain no more than an empty paragraph which will use a Razor template. The normal way for a Dynamicweb page is to respond with HTML, but I need a JSON respond. That is however a relative easy task, but a little tricky you will see.
Make the server respond with correct JSON headers
Dynamicweb CMS has a setting in back-end which will make the server respond with JSON headers:
Content-Type: application/json; charset=utf-8
Clean JSON friendly master and layout page
I have shared the MasterJSON.cshtml and JSON.shtml files on a gist on github. The layout file is nothing special, it simply pulls in the MasterJSON.cshtml and adds one single placeholder which is the minimum expected by Dynamicweb CMS for the layout template to work.
Both templates are razor, as we need to use razor in the paragraph template sending the e-mail (more below). In the MasterJSON.cshtml a trick is used to make the Dynamicweb template parsing engine happy and to trick it. Here goes:
The Dynamicweb template parsing engine will be happy about the template as it sees “ContentPlaceholder” tag, however as the test “1>2” will never be true, the normal output of the Dynamicweb CMS will never be rendered. Tricky, I know…
The Razor paragraph template
The actual sending of the basket by e-mail requires back-end code. As I wrote I went for a C# Razor template which will:
- Collect the receiver e-mail
- Find the basket on the current session using Dynamicweb API
- Render the basket as HTML to an e-mail
- Send the e-mail
- Build JSON respond to the AJAX request
The beauty of using Razor templates is that you can do anything. That is of cause a big responsibility to give any developer, and in particularly a front-end developer.
Always make an experienced back-end developer review your C# Razor templates
Here I am speaking from experience. I did make mistakes as I developed templates using C# in Razor, as the rules of the “back-end domain” are others than those of the front-end domain. I am a front-end developer with some experience in the back-end domain, but I need some guidance when coding in C#.
Collecting the receiver e-mail address is done like this:
var request = HttpContext.Current.Request;
string toMailAddress = "";
toMailAddress = Dynamicweb.Base.ChkString(request["sendTo"]);
The normal live cycle of a webpage is based around request and response. In .NET you have a object as you can see above which among other will hold any query string parameters. Here we can expect the receiver e-mail to be send as “sendTo”. To be sure that nothing is wrong with the parameter I use the Dynamicweb API method “ChkString”. It will among other check for SQL injection values and ensure that at least an empty string will exist.
To find the basket on the current session, I use a Dynamicweb API object:
Dynamicweb.eCommerce.Orders.Order order = Dynamicweb.eCommerce.Common.Context.Cart;
As this feature will be called from the step 1 of the basket, I know that a cart exists. A cart is what the basket is called internally in Dynamicweb eCommerce before it is turned into an order. It is an order, but an order which have not yet been ordered.
By now we have all the input we need. We can send the e-mail as the Order object actually has a build in method which can do exactly what we need: Send the order to a specified e-mail address (using other e-mail specific data). That is a great feature and it looks like this:
send = order.SendTo(ref pageView, subject, toMailAddress, fromMailAddress, fromMailName, ref template);
The method requires a “pageView” object to exist. It is a sort of context to the current session. I use this line of code to get that:
var pageView = Dynamicweb.Frontend.PageView.Current() ?? Dynamicweb.Frontend.PageView.GetPageview();
As you can see, I also have a subject, and information about where the e-mail is sent from.
You may also have noticed that I reference a template object. The template object is a Dynamicweb template which will render the current basket into HTML which can be e-mailed. I will not go into details here, rendering an order to HTML is another talk. To get such a template object you need to point to the template file as you instantiate the object. It could look like this:
Dynamicweb.Rendering.Template template = new Dynamicweb.Rendering.Template("eCom7/CartV2/Mail/sendBasket.cshtml");
The SendTo method will try to send an e-mail, and leave the status inside the “send” object you can see above. All we need to do now is to build JSON response to the AJAX code waiting for our response. I use the build in serializer of the System.Web assembly:
As I am in control here, I decide what should be responded to the AJAX request. I choose this data:
This will build a string containing serialized data and now all I need is to output that reply.
The pretty response
After all that work, I will get pretty responses like this one:
"PageTitle": "Send kurv NO",
"subject": "DIN HANDLEKURV HOS FIRMA",
Wrapping it up
Guess I left out the most important part:
The link to the live feature: http://www.altistore.no
All the work above will add a cool feature to a web-shop. It is not “just like that”, but mostly because it takes some thoughts and considerations to find the solution. What you should understand here is that you can do so many things with all the features offered by Dynamicweb CMS.
I am happy to share my knowledge of creating great website features like this. You can contact me on twitter: @netsi1964 if you need help to find and design solutions for web. Please share your thoughts and do not hesitate to post questions.