Synchronizing recipients with MailChimp lists part II

In the last post (Synchronizing recipients with MailChimp lists) we’ve seen how we can fetch the mists that are configured in MailChimp. In this part we’ll add subscribers to the mist and get the chance to unsubscribe users from the same list.

Adding a contact class

If we want to add contacts to our list we’ll need to create new views and alter the home controller in our demo project. In our model folder we’ll add a new class, Contact.

using System;
using System.ComponentModel.DataAnnotations;
using DataAnnotationsExtensions;

namespace MailChimpAPIDemo.Models
{
    public class Contact
    {
        [Required]
        public string FirstName { get; set; }
        [Required]
        public string LastName { get; set; }
        [Required]
        [Email]
        public string EmailAddress { get; set; }
        public DateTime? BirthDate { get; set; }
    }
}

You can see I’ve added 4 parameters, first name, last name, email address and birthdate. I’ve added the ‘Required’ annotation to the 3 required parameters. For the email address I’ve added the ‘Email’ annotation. This attribute is not in the default Annotations class but can be quickly added by adding the ‘DataAnnotationsExtensions’ package from Nuget. Open the Nuget Manager Console and type the following command.

PM> install-package DataAnnotationsExtensions

New lists in MailChimp have default only one required attribute and that’s the email address. You can alter the attributes you want to make required r you can add your own attributes by the web interface. Open up the list you want to alter and choose for ‘Settings – List Field and *|MERGE|* tags’

Then you can alter the field as you like. I’ve added the Birthday field and made the first and last name required for our demo list.

Adding the action and creating the view

Now that we have our Contact class we can add an Action in our controller. We add the ‘AddContact’ action twice. Once to deliver the view and one to retrieve the POST information.

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using PerceptiveMCAPI;

namespace MailChimpAPIDemo.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

            var returnValue = new List();

            var lists = new PerceptiveMCAPI.Methods.lists();
            var input = new PerceptiveMCAPI.Types.listsInput();

            PerceptiveMCAPI.Types.listsOutput output = lists.Execute(input);
            if (output != null && output.result.Any())
            {
                foreach (var listsResult in output.result)
                {
                    returnValue.Add(new McList()
                        {
                            ListId = listsResult.id,
                            ListName = listsResult.name,
                            MemberCount = listsResult.member_count,
                            UnsubscribeCount = listsResult.unsubscribe_count
                        });
                }
            }

            return View(returnValue);
        }

        public ActionResult AddContact(string listId)
        {
            return View();
        }

        [HttpPost]
        public ActionResult AddContact(string listId, Models.Contact contact)
        {
            return RedirectToAction("Index");
        }
    }

    public class McList
    {
        public string ListId { get; set; }
        public string ListName { get; set; }
        public int MemberCount { get; set; }
        public int UnsubscribeCount { get; set; }
    }
}

In the second action we will add the code to add the contact to the MailChimp list. First we’ll have to add the view to enter the contact’s details. Right click on the first ‘AddContact’ method and choose for ‘Add View’. (Don’t forget to build the application first so the new Contact class can be found)

Click ‘Add’ and you’ll see a new view get generated in the ‘Views\Home’ directory. We’ll still have to create a link in the ‘Index’ view to go to the new created ‘AddContact’ view. Because we need the list id we’ll add the link in the table where all lists are listed.

@model IEnumerable
@{
    ViewBag.Title = "Home Page";
}</pre>
<h3 style="text-align: justify;">MailChimpLists</h3>
<p style="text-align: justify;">
@foreach (var result in Model) { }</p>

<table>
<thead>
<tr>
<th>List Id</th>
<th>List name</th>
<th>Subscribers</th>
<th>Unsubscribers</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>@result.ListId</td>
<td>@result.ListName</td>
<td>@result.MemberCount</td>
<td>@result.UnsubscribeCount</td>
<td>@Html.ActionLink("Add contact","AddContact", new{listId = @result.ListId})</td>
</tr>
</tbody>
</table>
<pre>

You’ll see the new table cell with the Html helper creating a link to the ‘AddContact’ action.

Implementing the POST action

Now we have a working view to add contacts we can implement the wrapper class in the POST action in the ‘HomeController’. In the previous blog post I’ve wrote down the workflow that is used for every API call.

The same workflow is used for every API call:

  • Create the correct main object from the Methods namespace
  • Create the correct input type object from the Types namespace
  • Call Execute on the main object
  • Catch the result in the correct output type object from the Types namespace

We start with creating a PerceptiveMCAPI.Methods.listSubscribe object and we’ll create a PerceptiveMCAPI.Types.listSubscribeInput object that this time will contain a few parameters. Every input class has a sub class ‘parms’ where the necessary parameters can be entered. Here we will add the email address of the contact that MailChimp will use as a primary key and the id of the list where we want to add the contact to.

[HttpPost]
public ActionResult AddContact(string listId, Models.Contact contact)
{
	var subscribe = new PerceptiveMCAPI.Methods.listSubscribe();
	var input = new PerceptiveMCAPI.Types.listSubscribeInput()
	{
		parms = new PerceptiveMCAPI.Types.listSubscribeParms()
		{
			email_address = contact.EmailAddress,
			double_optin = false,
			replace_interests = false,
			send_welcome = false,
			update_existing = true,
			merge_vars = new Dictionary<string, object>(),
			id = listId
		}
	};
	return RedirectToAction("Index");
}
}

Of course we want to add the other values of the contact like first and last name. In the PerceptiveMCAPI.Types.listSubscribeParms class we already implemented the ‘merge_vars Dictionary’. In this dictionary we can add the other values.

	[HttpPost]
	public ActionResult AddContact(string listId, Models.Contact contact)
	{
		var subscribe = new PerceptiveMCAPI.Methods.listSubscribe();
		var input = new PerceptiveMCAPI.Types.listSubscribeInput()
		{
			parms = new PerceptiveMCAPI.Types.listSubscribeParms()
			{
				email_address = contact.EmailAddress,
				double_optin = false,
				replace_interests = false,
				send_welcome = false,
				update_existing = true,
				merge_vars = new Dictionary<string, object>(),
				id = listId
			}
		};
		input.parms.merge_vars.Add("FNAME", contact.FirstName);
		input.parms.merge_vars.Add("LNAME", contact.LastName);
		input.parms.merge_vars.Add("BIRTHDAY", contact.BirthDate);

		return RedirectToAction("Index");
	}
}

After we added all parameters we can invoke the ‘Execute’ method and catch the result in the output class. This class will only contain a bool value (result) if the API call succeeded or not. If it didn’t succeeded we can check the ‘api_ErrorMessages’ parameter of the output object. After the contact is added we’ll send the user back to the lists overview page.

Testing time

Time to test if our code is working. First of all we’ll run the application and go to the AddContact view by browsing first to the Index view.

After we click create will be redirected to our Index page where we’ll see the list now contains 1 member.

If we check in the MailChimp interface we’ll see the contact we’ve added by the API call.

One problem that we see here is that the Birthday is not filled out in this overview. First mistake I’ve made is to add the merge parameter without testing if the nullable DateTime has a value. If we check the API documentation we’ll see that we have to send a date value as ‘YYYY-MM-DD’ and not the European format we’ve used.

input.parms.merge_vars.Add("BIRTHDATE", contact.BirthDate.HasValue ? contact.BirthDate.Value.ToString("yyyy-MM-dd") : string.Empty);

Let’s try again:

And let’s check the MailChimp interface again.

And now we’ll see the correct birthdate.

Source code

You can find all demo’s from this blog post on Github. You’re free to fork or download.

Synchronizing recipients with MailChimp lists

MailChimp is an online service for sending professional looking email newsletters. They have a built in template designer but you can simply import your own designs from file or URL. For small organizations like sport clubs, hobby groups and so one they have a free plan with a maximum of 2000 subscribers and 12000 emails per month. More than enough for what I needed.

Manual synchronizing

MailChimp can have multiple lists to split up your contacts (per company or age group or …). Per list you can use segments to divide that one list. The only down side is that you only can add an email address once. This will give problems if you want multiple members of one family into one list under the same email address (parents email address for example).

People can be added through a registration form that you can alter to follow your website design and MailChimp offers signup by embedded code or by links or by a QR code, … When you’re already working with a contact database you can import these contacts in your list. MailChimp is very strict about importing people in their lists. You can’t use 3rd party lists, no lists you scraped from websites, … Users should be able to opt-in for the newsletter service and should always have a way to unsubscribe. If you don’t follow their guidelines your account will be blocked very quickly. Not without reason of course, they want to avoid that spammers misuse their service.

Importing

MailChimp offers imports from a range of services like Salesforce, Google Contacts, Google docs, Eventbrite, … Next to these services you can upload from file of copy paste from an excel file. And the latter was my manual synchronization every time before I would send out a new newsletter. I’ve created a stored procedure in my SQL database that would return all my contacts with their email addresses, first and last name. After exporting to excel, I could manually copy the 3 columns to the MailChimp web interface. If you’re only sending a newsletter every 3 months, this is doable. But we’re now speeding up on our newsletters and sending at least one per month and during the holidays multiple newsletters per month.

Time to look into the MailChimp API. I didn’t wanted to write a wrapper from scratch and looked into the list of existing wrappers. The first I found was the PerceptiveMCAPI created by Perceptive Logic. I haven’t looked into the other wrappers. I’m not saying the PerceptiveMCAPI is the best, the following is just an explanation how to incorporate the PerceptiveMCAPI into a .NET application.

PerceptiveMCAPI

You can download the compiled code from the codeplex page. Don’t expect a lot of documentation, I could hardly find any blogs or other information how to use their wrapper. I ended up downloading their source code to find all options available. The examples below just alters subscriptions to a list. The rest of the wrapper is similarly build so you can implement the other actions following the examples below.

Add the compiled source code to a folder in your application and add a reference in your project to the DLL. You don’t have to reference the CookComputing.XmlRpcV2.dll that is in the same download.

Updating the Web.config

Before we can use the wrapper we have to add a reference in the config file (web.config for web application, app.config for desktop applications). First of all, add a ‘<section>’ under the ‘<configSections>’ tag. If you don’t have a ‘<configSections>’ tag already add it directly under the ‘configuration’ opening tag. Don’t forget to add a closing ‘</configSections>’ tag.

&lt;/pre&gt;
&lt;section&gt;&lt;/section&gt;
&lt;pre&gt;

After we added the ‘<section>’ tag we can add the ‘<MailChimpAPIconfig>’ tag. There we can enter default values like the API key from MailChimp, the datacenter we want to use and other settings. See chapter MailChimp API key for more information how to get your API key.



Retrieving all our lists from MailChimp

Now we added our default values in the config file we can start to make our first call to the MailChimp API. In this first call we’ll retrieve all the lists we have created in MailChimp. We will need the list ID to add or remove subscribers from that list. For demo purposes I will add the necessary code in the home controller class. In real world application this would be ideally be placed in a separate manager class.

First add the using statement on top of our controller class.

using System.Web.Mvc;
using PerceptiveMCAPI;

The same workflow is used for every API call:

  • Create the correct main object from the Methods namespace
  • Create the correct input type object from the Types namespace
  • Call Execute on the main object
  • Catch the result in the correct output type object from the Types namespace

We need to access the MailChimp lists so we create a ‘PerceptiveMCAPI.Methods.lists’ object as our main object. The corresponding input type object will then be the ‘PerceptiveMCAPI.Types.listsInput’ class.

using System.Web.Mvc;
using PerceptiveMCAPI;

namespace MailChimpAPIDemo.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = &quot;Modify this template to jump-start your ASP.NET MVC application.&quot;;

            var lists = new PerceptiveMCAPI.Methods.lists();
            var input = new PerceptiveMCAPI.Types.listsInput();

            return View();
        }
    }
}

To retrieve all the lists we don’t need extra input parameters so we can give the input object as it is to the Execute call. The return type do we catch in a ‘PerceptiveMCAPI.Types.listsOutput’ class.

using System.Web.Mvc;
using PerceptiveMCAPI;

namespace MailChimpAPIDemo.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = &quot;Modify this template to jump-start your ASP.NET MVC application.&quot;;

            var lists = new PerceptiveMCAPI.Methods.lists();
            var input = new PerceptiveMCAPI.Types.listsInput();

            PerceptiveMCAPI.Types.listsOutput output = lists.Execute(input);

            return View();
        }
    }
}

After a check if the result is not null we can loop over the result List parameter in the output type. I’ve added a custom MCList class to hold all the results that we can send to the view. There are more parameters in the result object that you can use like statistics etc. These parameters are not documented but generally you can look at the MailChimp API documentation and figure out what is available.

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using PerceptiveMCAPI;

namespace MailChimpAPIDemo.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = &quot;Modify this template to jump-start your ASP.NET MVC application.&quot;;

            var returnValue = new List();

            var lists = new PerceptiveMCAPI.Methods.lists();
            var input = new PerceptiveMCAPI.Types.listsInput();

            PerceptiveMCAPI.Types.listsOutput output = lists.Execute(input);
            if (output != null &amp;&amp; output.result.Any())
            {
                foreach (var listsResult in output.result)
                {
                    returnValue.Add(new McList()
                        {
                            ListId = listsResult.id,
                            ListName = listsResult.name,
                            MemberCount = listsResult.member_count,
                            UnsubscribeCount = listsResult.unsubscribe_count
                        });
                }
            }
            return View(returnValue);
        }
    }

    public class McList
    {
        public string ListId { get; set; }
        public string ListName { get; set; }
        public int MemberCount { get; set; }
        public int UnsubscribeCount { get; set; }
    }
}

When we start up the test application will get the correct results. We see the one list we declared in MailChimp and of course no subscribers yet. (I’ve altered the default view, you can find this changes in the source code)

MailChimp Web interface vs our own web interface


Adding subscribers to our list

Now we can fetch all our lists (just one in this demo) we can start adding subscribers to our list. This will be explained in the following blog post.

MailChimp API key

The API key you can find in the MailChimp web interface under Account – API keys & Authorized Apps.

Click the ‘Add A Key’ button to add a new API key

Source code

You can find all demo’s from this blog post on Github. You’re free to fork or download.

Extending NetBash

NetBash is a small utility u can use in MVC projects created by Luke Lowrey. It’s an alternative for endless administrative pages for every function you need. It’s nested in your view and styled as a real bash command window.


In one of my side projects I created my own commands to send text messages to cell phones, to activate a mass mailing and so on. As I manage the application I get regularly questions for custom database queries where no administration screen is created for. Luke Lowrey already provided the NetBash.Database Nuget package to query the database. After installing the package I wasn’t able to get the database queries to work.

Open source

Luke Lowrey was so nice to create a GitHub repository with the source code for NetBash and the NetBash.Database plugin. As a new Github user I forked the NetBash.Database repository and cloned the code locally. I added the projects to my projects solution and removed the existing references to the Nuget packages. After adding new references to the added projects I was ready to start debugging.

First thing I noticed was the option to add the connectionstring name to the NetBash sql command but no way to fetch all connectionstrings names from the config file.As the project has multiple connectionstrings for different database it would be a help to have a way to visualize them before starting to query. First job, add an option to show the connectionstring names.

New NetBash option

Luke used NDesk to define the options that can be used in the Database plugin. Adding an option is quite simple. In the SqlCommand class we alter the Process method.

var p = new OptionSet() {
{ "e|execute", "Executes an sql query",
	v => _command = Command.Execute },
//{ "i|info", "Shows database information",
//    v => _command = Command.Info },

{ "t|tables", "Lists tables and space used optional filter on provided table name",
	v => _command = Command.Tables },

{ "s|schema", "Display table schema for the provided table name",
	v => _command = Command.Schema },

{ "clear", "Removes all rows from database",
	v => _command = Command.Clear },

{ "cn|connectionstring","Returns the connectionstring name that will be used",
	v=>_command=Command.ConnectionStringName},

{ "lcn|listcn","Shows all connectionstring names found",
	v=>_command = Command.ListConnectionStrings},

{ "c=|conn=", "Name of connection string to use (defaults to first found)",
  v => _connectionName = v },

{ "h|help", "show this list of options",
	v => _command = Command.Help }
};

Here we added the ‘lcn’ command in the OptionSet (line 19). Before we can set the _command parameter we have to add our command to the Command enum.

private enum Command
{
	Execute,
	Info,
	Tables,
	Schema,
	Clear,
	Help,
	ConnectionStringName,
	ListConnectionStrings
}

All we need now is a private method where we loop over all the connectionstrings and add them to a StringBuilder (see getConnectionStringNames()).

private string getConnectionStringNames()
{
	var sb = new StringBuilder();
	for (int i = 0; i < ConfigurationManager.ConnectionStrings.Count; i++)
	{
		sb.AppendLine(ConfigurationManager.ConnectionStrings[i].Name);
	}
	return sb.ToString();
}

We then return the result to the Process method (line 21,22).

switch (_command)
{
case Command.Execute:
return execute(query);

case Command.Info:
return executeEmbedded("DbInfo.sql");

case Command.Tables:
return getTables(query);

case Command.Schema:
return showSchema(query);

case Command.Clear:
return clearRecords();

case Command.ConnectionStringName:
return getConnectionStringName();

case Command.ListConnectionStrings:
return getConnectionStringNames();

case Command.Help:
default:
return showHelp(p);
}

Now we can use the “SQL -lcn” command in the NetBash interface to list us all the connectionstrings that are in the config file.

Entity Framework formatted connectionstring support

Now we can show all connectionstring names I encountered the next problem. To query the database Luke makes use of a SqlCommand. This command needs a SqlConnection object that has the correct connection string.

In the project we use Entity Framework (EF) that needs his own type of formatting for the connectionstrings. The SqlConnection object can’t work with this types of strings. But the type of connectionstring that we have to use is embedded in the EF string. All we need to do is check if the connectionstring is the EF type and then parse it. In the System.Data.EntityClient namespace Microsoft added a EntityConnectionStringBuilder that we can use to parse the string.

private string CheckForEntityFrameworkConnectionString(string connString)
{
	if (connString.Contains("provider connection string="))
	{
		//Parse connectionstring from Entity connectionstring
		var entityBuilder = new EntityConnectionStringBuilder(connString);
		return entityBuilder.ProviderConnectionString;
	}
	return connString;
}

The EntityConnectionStringBuilder has a constructor that takes an EF connectionstring. After that we can access the ProviderConnectionString parameter that will contain the string we need. We add the CheckForEntityFrameworkConnectionString in the getConnectionString method and we’re ready to query our database.

private string getConnectionString()
{
	var connString = ConfigurationManager.ConnectionStrings[_connectionName] ??
					 ConfigurationManager.ConnectionStrings[0];

	string connectionString = CheckForEntityFrameworkConnectionString(connString.ConnectionString);
	return connectionString;
}

Github commit and Pull Request

Now we added the functionality we wanted we can commit it all to our Github repository that is a fork of the original repository. After committing we want to inform Luke that we have some changes that he maybe would like to incorporate in his code. Github has this functionality on board. You can issue a “Pull request”. With this request you can ask the manager of the original repository to include the changes you have made. The manager then has to choose the changes he wants to merge into his code. I’ve added my ‘Pull Request’ and hopefully Luke likes the changes I added and will merge them into his fantastic utility.

Deploy your site to Azure from Github private repositories

Last June I attended Microsoft Tech Ed in Amsterdam. During the event the main focus in ASP.NET development was on Azure, the Microsoft cloud solution. I didn’t had the time yet to play around with Azure until I wanted to test if one of my personal projects would have mess speed/loading problems when deployed on Azure.

Github

After working with Subversion (SVN) for the last years, the distributed source control of Github looked appealing. I didn’t wanted to give up the safety of my local SVN server at home with daily backups to my NAS. But on the other side, a recommended and proven source control like Github could only scale down backup and safety worries. To test out Github I’m now combining the two source control systems. Every change first gets committed to my SVN server and then committed and synchronized with my Github account.

Deploying to Azure

Azure websites have a few options to deploy to. Until some time ago the easiest way to deploy a website was to download the “publish profile” from the Azure management portal as shown in the image below

.

In Visual Studio you can select the downloaded “profile” and then publish to Azure.

Publish directly from Github

Scott Hanselman made a good post about deploying your application directly from your Github repository to your Azure website. Still working on Azure to test out the possibilities there was no problem that every commit would be deployed. It would give me the advantage to direct test the changes I made on my development machine in a ‘live’ production environment (although it isn’t the real production environment).

Following the steps as described by Scott I ran into a problem. When trying to associate my Azure website with the correct Github repository I could only choose from the existing public repositories. As my personal projects aren’t all open source projects I had placed this specific project in a private repository.

Searching for a solution

Up to Google to search if anyone else had solved this problem, maybe a setting on Github, maybe a setting in Azure, … I didn’t found any solutions on the GIT Deployment to Windows Azure forum nor on the wiki pages of the Kudu project (Kudu is the engine behind git deployments in Azure Web Sites. It can also run outside of Azure. It can be found on Github). I decided to post a comment on Scotts blog post. Scott was so kind to forward my question to David Ebbo who is working on Kudu with David Fowler. Just one hour after I posted my comment David responded on my question of it is already possible to deploy from private repo’s:

Not yet, but we are going to support this in the next update. Exact date is TBD, but hopefully in the next month or so.

No solution yet but …

One step closer, but no solution yet. I have some workarounds:

  • Make my repository public on Github.
  • Use the publish profile to deploy directly from Visual Studio
  • Look into pushing to Azure from a build server (not discussed in this post)

What I wanted to emphasize is the quick and clear response from Microsoft when dealing with this kind of problems. I can remember the long and tedious protocol to file bugs and then hopefully someone would answer a month or so later. The Microsoft of today is changed. Quicker response, listening to their users (the developers) and an improved open source protocol! A big change that hopefully will extend to all divisions at Microsoft.

MSDN

For the people who have a MSDN subscription. There’s a basic start credit included in your MSDN subscription. If you want to start playing around in Windows Azure without waving a credit card from step 1.

Goodbye editing host files for simple test websites

During development I often create test websites or pages to test new implementations or new frameworks. After creation the simple way to test the website is to add the site to the local IIS server and to assign a hostname to avoid remembering a specific port. This works great but you still have to add the hostname to your host file (c:\windows\system32\drivers\etc\hosts) and point it to the loopback address (127.0.0.1).

When I started to read the article Configuring your ASP.NET application for Microsoft OAuth account on the MSDN blog site one of the first items was to use a test domain. Without reading further I was already configuring IIS with a new custom host name for that specific site. After creating the site I read the item completely and discovered the localtest.me service.

This neat little service pointed all localtest.me domain names to 127.0.0.1. And they used the wildcart ‘*.localtest.me’ so you can choose any name you want. With this service setting up a test site is as simple as configuring your site in IIS.

Configure IIS for localtest.me

Open up IIS and create your site like you always do. Open up the bindings screen and add any hostname ending on .localtest.me.

 

 

 

 

 

 

After clicking ok, you can simply browse to mytestsite.localtest.me and your local website will appear.

Credits

Credits off course for Scott Forsyth and Imar Spaanjaars who came up with this idea.

More info on: localtest.me

SSL

Be sure to read their remarks on SSL before trying to test a local SSL configured site.

The birth of ABC G.OD – Group of Open Development

While working at the ABC-Groep, just north of Antwerp I’m involved in the coaching program the company have set up a couple of years ago.

As most of my colleagues are consultants working in the branch office of our customers we started with a program to provide a better follow up of the consultant, improve communication between the consultant and the company and to create a company feeling. Most of the consultants only meet each other on the obligated company meetings where for them a bunch of unknown people are present. With regular visits to the consultant, dedicated technical sessions for each branch and a fun event we try to involve the consultants in the social binding that exists in our company.

During one of my coach visits a consultant came up with the idea to create open source projects after the working hours. These projects could help us to play around in the latest version of the .NET framework and to discover the huge amount of open source libraries that can be plugged in into your .NET project. With Nuget it’s never been easier to use third party components or frameworks. As some of my colleagues work at legacy projects and others still work in .NET 3.5, doing a project in the latest version would be very interesting.

After some preparation we had our first kick-off meeting last week. With an 11 colleagues we started the ‘Open Development Group’. We talked about what should be the target, how we are to involve each other in the development process and what we we’re going to create. After some (healthy) discussion we came up with our first project: ‘The ABC Athletes Follow up’. An administrative application for coaches/trainers to efficiently follow up on their athletes.

Github

With 1 developers it’s necessary to have a common code repository to share and commit the code to. Next to the code repository we needed an issue tracker to file the open tasks and report the bugs. Since the projects would be open source we found Github is the perfect place to manage our projects. Github has a built-in issue tracker, repository browser, Wiki, …

Making the projects open source will not only improve the feedback on the created projects but will also give the contributors a very visual overview of their work in the latest version of .NET and other frameworks, components, … This overview can be very handy for the future job interviews of the contributors.

You can find our project page on http://abc-god.github.com/

GOD

The term ‘Open Development Group’ was just a work title for me to check out if there were any colleagues interested in the project. During our kick-off meeting the question arises if ‘Open Development group’ would be a good name to communicate to colleagues and the outside world. It didn’t take long to have one shouting out that if we changed it to ‘Group of Open Development’ the acronym ‘ABC G.OD’ does sound a bit better. A new name was born.

You can follow the ABC G.OD on the Github page, directly the Github repository or on twitter (@GodAbcGroep)
You’ll find more information about the ABC-Groep on the website, on twitter (@abcgroep). All .NET developers are part of the ACE branch of the ABC-groep, a company focusing on .Net development, consultancy for Microsoft Dynamics and services for the Microsoft Sharepoint platform.

Getting ready for TechEd Europe 2012

Only 2 weeks from now and a new edition of Tech Ed Europe starts, this time in Amsterdam. The last Tech Ed Europe was in Berlin in the cold month of November 2010. Feedback from most visitors was to organize a new edition in the summer instead of the winter. Microsoft listened to this and skipped a 2011 edition to be back with a summer 2012 edition.

Where software developers and IT pro’s had a separate conference in the past, from 2012 on they share the venue. It has his advantages but also his disadvantages. Flipping through the different session on this year’s conference, it’s hard to find the good developer sessions that we had in the past.

Ok, I don’t have to exaggerate. There more than enough developer sessions for Azure developers, Sharepoint developers, … For the .Net core developer with a focus on web development in ASP.NET it’s harder to find the best sessions. On the first session slot I could only find Visual Studio Tips & Tricks for example. Of course I will pick up something new in these sessions with the Visual Studio 12 release coming up but I prefer the more technical sessions.

Luckily the conference is 5 days long with a lot of interesting sessions and other professionals to meet. And that in the lovely city of Amsterdam, it could be worse !!

Good service at Coolblue

Some webshops have a bad reputation when it comes to after sales service and repairs.

2 weeks ago I bought the Samsung Galaxy S II (SGS2) at the GSMStore.be, one of the shops of CoolBlue. After filling out the order form I was able to pick up the telephone at their shop in Antwerp where I work close by. One of the packs they introduced was the SGS2 together with a case, car adapter and a screenprotector.

After configuring the phone I noticed some people I talked to were complaining about feedback of their own voice what made the conversation very hard. After removing the case from the phone it seems to be better but there still was some feedback on the background. After searching around on the net I found a lot of people complaining about the feedback with their brand new SGS2. Most of the time the complaint was when using a case. The first solution off course is not to use the case. But I just bought a 500 euro phone with a case so I wouldn’t damage the screen to soon.

After some searching I found a post on the XDA Developers forum where is explained how the isolation of the speaker is not completely tight so the sound vibrations are caught by the case and transported to the microphone. The noise reduction will turn up the volume for the other party returning their own voice in an echo. The solution is to place a damper between the speaker and the body of the phone. But this implied I had to open up my brand new phone and crossing the rules stated in the warranty.

I contacted CoolBlue by the customer service page on their website hoping for a quick solution. I received a few minutes later a confirmation email and later that day an email with a ticket attached. With that ticket I could, free of charge, return the phone by the postal service. Because I work close to the shop, I stepped into the shop instead of mailing them the phone. The guy at the customer service desk was friendly and was happy to replace my phone with a brand new one. We attached the case in the store and did some test calls. No echo anymore and a happy customer back on his way.

It’s that professional behavior that makes a customer trust an organization. Thumbs up for CoolBlue.

Using jQuery in ASP.NET applications – part 3 MVC – creating an API

This post will extend the previous post Using jQuery in ASP.NET applications – part 3 MVC.

In the previous post we saw how to create a AJAX call to a specific controller in a MVC application. This will work just fine if you have a small amount of AJAX calls in your application. As your application Is growing you’ll notice that the AJAX calls will get stuck between the other controller actions whom return normal views.

If you want to share functionality between views you’re have repeat the same code in multiple controllers or point non-related views to your controller. This will technically work but conflicts with the MVC pattern.

MVC has a functionality to split up your code in different areas what most of the time is used to split up the administration pages from the rest of your website. Or to reorganize your code to split different use cases. We’ll use this Area functionality to create or own API.

Creating the Area

Note: I’ve switched to Visual studio 11 Beta for the demos. You’ll see the new slick black/white/grey look and feel of VS 1 in the screenshots. Neither less you can do everything underneath in Visual Studio 2010.

Open up the project we created In the previous post. Right click the project and choose ‘Add’. Select the Area option.

Give the new area the name ‘API’. After clicking Add you’ll see that visual studio create an Areas folder within their you’re ‘API’ area. In this area you’ll see the same setup as in a MVC application. You’ll have folders for controllers, models and views.

The APIAreaRegistration class visual studio created will register the routes we need to address our area.

using System.Web.Mvc;

namespace Demo.Areas.API
{
    public class APIAreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get
            {
                return "API";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                "API_default",
                "API/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

In the Application_Start method in the Global.asax file we’ll see the AreaRegistration.RegisterAllAreas method that will take care of the registration of the routes of the different areas when available.

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }

Create a new controller

All our AJAX calls are related to handle books, more specific: add book titles. Therefor it is logical to create a book controller in our API. Ricght click on the controllers folder in our API area and choose for Add controller. Name it BookController and choose for an Empty controller.

Visual studio will now create the new controller. When created it should contain only an index action.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Demo.Areas.API.Controllers
{
    public class BookController : Controller
    {
        //
        // GET: /API/Book/

        public ActionResult Index()
        {
            return View();
        }
    }
}

We add the same code we used in our HomeController.

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Demo.Models;

namespace Areas.API.Controllers
{
    public class BookController : Controller
    {
        private static string sessionName = "BooksSessionName";

        public ActionResult AddBook(string bookTitle)
        {
            List<Book> books;
            if (Session[sessionName] != null)
            {
                books = Session[sessionName] as List<Book>;
                if (books == null)
                    books = new List<Book>();
            }
            else
            {
                books = new List<Book>();
            }
            Book book = new Book() { BookId = GetNextBookTitleId(), BookTitle = bookTitle };
            books.Add(book);
            Session[sessionName] = books;
            return Json(book, JsonRequestBehavior.AllowGet);
        }

        private long GetNextBookTitleId()
        {
            if (Session[sessionName] != null)
            {
                List<Book> books = Session[sessionName] as List<Book>;
                if (books != null)
                {
                    long ticket = books.Max(t => t.BookId);
                    ticket++;
                    return ticket;
                }
            }
            return 1;
        }
    }
}

AJAX call to the API

After rebuilding our application we can now alter our javascript call so we address the API instead of our home controller. Open up the Home.js file in our scripts folder under the root of the application. Change the URL in the AJAX call to “/API/Book/AddBook”

$(document).ready(function () {
    $("#btnAddBookTitle").click(function () {
        var $bookTitle = $("#txtBookTitle").val();
        $.ajax({
            type: "GET",
            url: "/API/Book/AddBook/",
            data: {bookTitle:$bookTitle},
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (msg) {
                var $book = msg;
                var $option = new Option($book.BookTitle, $book.BookId);
                $("#lstBookTitles").append($option);
            },
            error: function () {
                alert('Error calling AddBook');
            }
        });
        return false;
    });
});

API is ready for use

With these small changes and build in functionality in visual studio we can easily create an API for all our AJAX calls. If we, for example, need to query for users by an AJAX call we can create a new user controller in our API area and implement the necessary actions.

None of the methods that solely serve AJAX calls are in the other controllers that serve views. We created a nice separation between those.

Next on the blog todo list is the implementation of an AJAX call to a WCF REST service.

You can download the demo project here

Tech session jQuery and ASP.NET

This month we organized a bunch of jQuery Tech sessions for our colleagues at the ABC-Groep where we are working for the company Ace, the Microsoft .NET company of the group. After some introduction to jQuery sessions we had yesterday the jQuery and ASP.NET, how to AJAX session. A few of the subjects that we handled are already on this blog.

The rest of the subjects will follow soon.

Until then here are the presentation and the demos of the jQuery and ASP.NET, how to AJAX session.

[UPDATE] All the source code used in the demo are placed on GitHub:

  • Presentation
  • Demo AJAX vs JQuery
  • Demo ASMX – Web Forms
  • Demo MVC
  • Demo WCF
  • Demo WEB API (including using jQuery Templates plugin and the jQueryUI autocomplete dropdown)

Keep in mind that the demos where focused on the technical implementation of AJAX calls to the different ASP.NET stacks. Therefor there has been no time spend on layout and presentation in the demos.