Category Archives: MVC 3

Securing Backend Pages in MVC for Umbraco 4.11.1

Beginning of the year I posted an article on how you can create backend pages in the open source ASP.NET CMS Umbraco (http://blog.bartdemeyer.be/2013/01/using-mvc-backend-pages-in-umbraco-4-11-1). At the end of the post I published a little TODO list:

  • Block access to the backend controller for non authenticated users
  • Adapt the actions that you get in the Umbraco back end by right clicking
  • Due to a very busy work schedule I didn’t had the time to look into this list. In the mean while version 6 was released by the Umbraco core team.

    Last week I received the question if I had already found a solution for the first item on the todo list: blocking access to the backend controller for non authenticated users.

    Between the search for Easter eggs together with my son, backing pancakes and nothing interesting on the TV this evening I found the time to implement the feature.

    Reminder: the problem

    A small reminder of the problem we are facing. We’ve created a MVC controller to access from the Umbraco backend to perform our own business logic like shown in the image below.

    image

    We used the implementation if the Umbraco’s Surface  Controller that will create a MVC area. If we know the structure of the URL to this area – controller – action we can access the page without logging in the Umbraco backend.

    image

    This is off course a security risk we have to solve. We don’t want non authenticated users to be able to access our business logic.

    Using the Authorization attribute

    In ASP.NET MVC access to certain controllers or individual actions is managed by using the Authorization annotation attribute. You can use the default attribute where you are able to filter request based on specific users or specific user roles.

    But you can off course inherit from the default attribute and implement your own authorization attribute.

    Create the UmbracoAuthorizeAttribute

    In this post I’ll extend the project we’ve created during the previous post and that you can find on Github.

    Add a folder ‘Helpers’ in the UmbracoMVCDemo.BackEnd project. In that folder create a new class ‘UmbracoAuthorizeAttribute’. Add the public keyword to the class implementation and we shall inherit from the System.Web.MVC.AuthorizeAttribute.

    Implementing authorization

    Implementing your own authorization login can be done by overriding two methods from the base class: AuthorizeCore(HttpContextBase httpContext) and OnAuthorization(AuthorizationContext filterContext).

    In AuthorizeCore(HttpContextBase httpContext) we will connect to the Umbraco backend to check if the user is authenticated or not.

    I’ll first check if the httpContext contains any value, if not we’ll throw an exception. After that I’ll use a method from the Umbraco BasePage: ValidateUserContextID. This method will return true if the user is authenticated and false if not. With that result we’ll set a class variable we can use in the implementation of the OnAuthorization method.

    In this implementation we’ll first execute the base class implementation before we check the failedAuthentication class variable. If the authentication in the failedAuthentication failed we’ll send the user to the login page using the FormsAuthentication class.

    Adding authorization to our controller

    It’s not enough to create the attribute, we still have to tell our controller to use the authentications we’ve implemented. Open up the DemoAdminSurfaceController class we created in the previous post and add the UmbracoAuthorize attribute (line 4).

    Testing

    I’ve opened up another browser and accessed the same action again. (keep in mind that we make use of the default FormsAuthentication that will use a session cookie. Therefor will a new tab in the same browser not give the desired effect). Because we’re not authenticated we get redirected to the login page.

    image

    You’ll see the url we entered in the ReturnUrl parameter. If we now enter our credentials we’ll get redirected to the Umbraco back end. Although the ReturnUrl is filled out we’ll not be redirected to the correct page. We still have to click on our demo Section and demo node.

    Remark

    I’ve had to alter the default web.config file to be correctly redirected to the login page. I’m not sure this needs to be done if you have a fresh installation, I’ll add it here to avoid bad redirections.

    Source

    You can find the full source code from this post and the earlier posts on Github. Feel free to download, fork, comment, …

    Using MVC backend pages in Umbraco 4.11.1

    Umbraco backend

    In a previous post we saw the use of your own MVC controllers in the Umbraco front end. The Umbraco community has made effort to document these possibilities on our.umbraco.org. The use of MVC in the back end of the Umbraco interface is not very well documented and it took me some analysis and debugging of the source code to find out how this could be implemented.

    Default you have 7 sections in the backend:

    • Content
    • Media
    • Settings
    • Developer
    • Users
    • Members
    • Translation (hidden by default for the admin user)

    These sections will do in a plain website where you don’t want to use custom code.

    One of my personal projects is to create a new website for the sport club where I’m already 15 years affiliated with. The current website is already 7 or 8 years old and was written in PHP. Needless to say that the look and feel is outdated, the PHP code I’ve written 8 years ago wasn’t the most beautiful piece of code I’ve created.
    I wanted to create a new website in ASP.NET MVC but I don’t want to put the effort in creating controllers and views for the administration part where a good CMS can fill up this gap.

    Because I’m already familiar with Umbraco it looked a good choice to combine the strength of Umbraco with custom development. But therefor I had to get custom MVC controllers working in the backend.

    New backend project

    This blog post goes further on the project created in the previous post. You can download the source at Github.

    In the existing solution we’ll add a new project by right clicking the solution and choose Add – New project.

    image

    Choose for a ASP.NET MVC 3 Web Application and give it a name (in this demo: UmbracoMVCDemo.BackEnd)

    image

    In the next window choose for Internet Application and the Razor view engine. We’ll need the core Umbraco libraries so open up the Package Manager Console and type ‘”Install-Package UmbracoCms.Core” and hit enter. Wait for the “Successfully added ‘UmbracoCms.Core 4.11.1’ to UmbracoMVCDemo.BackEnd.” message and we’re ready to go.

    Adding a new section

    First we’ll have to create a new section in the Umbraco backend. Open op your windows explorer and go to the root of the Umbraco installation. Open up the config folder and open up the applications.config file.

    <?xml version="1.0" encoding="utf-8"?>
    <applications>
      <add alias="content" name="Content" icon=".traycontent" sortOrder="0" />
      <add alias="media" name="Media" icon=".traymedia" sortOrder="1" />
      <add alias="settings" name="Settings" icon=".traysettings" sortOrder="2" />
      <add alias="developer" name="Developer" icon=".traydeveloper" sortOrder="3" />
      <add alias="users" name="Users" icon=".trayusers" sortOrder="4" />
      <add alias="member" name="Members" icon=".traymember" sortOrder="5" />
      <add alias="translation" name="Translation" icon=".traytranslation" sortOrder="6" />
    </applications>
    
    

    You’ll see the existing 7 sections configured in the config file. We’ll add a new one:

      <add alias="demo" name="Demo" icon="demo.gif" sortOrder="7" />
    

    We give the new application or section the alias ‘demo’ and the name ‘Demo’. For the icon we’ll add a new picture called ‘demo.gif‘ and set the sort order to 7. (The default images are showed using sprites where the icon name is actually the css class to define the background image. You can choose to alter the existing sprite and add a css class or select new picture). Create a new picture with your favorite image editor, name it ‘demo.gif’ and place it in the folder: [Umbraco root]/umbraco/images/tray/ folder.

    We’ll have to force the application pool to restart before Umbraco loads the new section. Open up the web.config file in the umbraco installation root and add a line break, save and refresh the page.

    Still the new section is not available in the backend because none of the users have access to this new section. Go to the users section, open up your user and add a check in the sections area next to the demo section. Refresh your page and you’ll see the new section appear.

    image

    When you click the Demo section at the bottom of the page we’ll see a new section opening up with an empty tree and the section name in square brackets.

    Adding a tree

    Next step will be to create the tree for our Demo section. This tree you can populate with data you choose. For this demo we’ll use some dummy data.

    In our backed project add a folder ‘Trees’ and add a new class named DemoTree. This class will have to inhered from the umbraco.cms.presentation.Trees.BaseTree class. This class has 3 abstract methods that we’ll need to implement.

    • RenderJS: the javascript that will run when a tree node is clicked
    • Render: the creation of tree nodes
    • CreateRootNode: to define the root node.

    We’ll also have to create a constructor that will receive a string that will forward to the base class.

    Last but not least we’ll have to decorate the class with the umbraco.businesslogic.TreeArrtibute where we define the application alias and title.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    using umbraco.cms.presentation.Trees;
    
    namespace UmbracoMVCDemo.BackEnd.Trees
    {
    	[Tree("demo","demo","Demo")]
        public class DemoTree : umbraco.cms.presentation.Trees.BaseTree
        {
            public DemoTree(string application) : base(application)
            {
            }
    
            public override void RenderJS(ref StringBuilder Javascript)
            {
                throw new NotImplementedException();
            }
    
            public override void Render(ref XmlTree tree)
            {
                throw new NotImplementedException();
            }
    
            protected override void CreateRootNode(ref XmlTreeNode rootNode)
            {
                throw new NotImplementedException();
            }
        }
    }
    

    Let’s start with defining the root node what is as simple as setting the NodeType and NodeId parameter.

    protected override void CreateRootNode(ref XmlTreeNode rootNode)
    {
    	rootNode.NodeType = "init" + TreeAlias;
    	rootNode.NodeID = "init";
    }
    

    Next we’ll implement the Render method and attach 2 nodes to the tree.

    public override void Render(ref XmlTree tree)
    {
    	XmlTreeNode xNode = XmlTreeNode.Create(this);
    	xNode.NodeID = "1";
    	xNode.Text = "Demo Node 1";
    	xNode.Action = "";
    	xNode.Icon = "folder.gif";
    	xNode.OpenIcon = "folder_o.gif";
    	OnBeforeNodeRender(ref tree, ref xNode, EventArgs.Empty);
    	if (xNode != null)
    	{
    		tree.Add(xNode);
    		OnAfterNodeRender(ref tree, ref xNode, EventArgs.Empty);
    	}
    
    	XmlTreeNode xNode2 = XmlTreeNode.Create(this);
    	xNode2.NodeID = "2";
    	xNode2.Text = "Demo node 2";
    	xNode2.Action = "";
    	xNode2.Icon = "folder.gif";
    	xNode2.OpenIcon = "folder_o.gif";
    	OnBeforeNodeRender(ref tree, ref xNode2, EventArgs.Empty);
    	if (xNode2 != null)
    	{
    		tree.Add(xNode2);
    		OnAfterNodeRender(ref tree, ref xNode2, EventArgs.Empty);
    	}
    }
    

    In the RenderJS method remove the ‘throw new NotImplementedException” line and build the project. We’ll have to copy the UmbracoMVCDemo.BackEnd.dll from the bin folder to the Umbraco installation bin folder.

    Refresh the page and you’ll see two new node appear. Notice that the Demo root node isn’t surrounded by square brackets any more.

    image

    If you open up the trees.config file in the umbraco root – config folder you’ll see Umbraco automatically added the tree.

    For now the nodes don’t do much if you click on it because we left the Action attribute empty. Before we can add an action we need the editor for the right hand side.

    Adding an editor – controller and views

    Like I said before we want to create the editor in a MVC pattern instead of the default Webforms like was possible before. Therefor will create a new controller by right clicking the controllers folder in the backend project.

    image

    Name the controller DemoAdminController and choose for the empty controller template. Because we’ll already have a DemoController in the frontend application I named this one DemoAdmin to avoid confusion.

    The Controller will have to inhered from the Umbraco.Web.Mvc.SurfaceController before we can use it in the backend.

    IMPORTANT: Although the documentation of version 5 stated the controller didn’t need to be suffixed by ‘Surface’ I noticed there are constraints set on the PluginControllerResolver in the Umbraco source code. We can remove this constraint in the source code but the easiest way is to rename our controller to DemoAdminSurfaceController. This will change our URL’s but they won’t be visible in the Umbraco backend anyway.

    We have to decorate the class with the Umbraco.Web.Mvc.PluginController attribute. (yes, the plugincontroller attribute although we’re inheriting a SurfaceController). In this attribute we’ll have to enter the area name. Every plugin will be placed in his own MVC area to avoid duplicate views and controllers. We’ll set the area name to ‘demo’.

    Last but not least we’ll have to create two constructors. One without parameters, one that will take a Umbraco.Web.UmbracoContext instance and forward this to the base class.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using Umbraco.Web;
    using Umbraco.Web.Mvc;
    
    namespace UmbracoMVCDemo.BackEnd.Controllers
    {
        [PluginController("Demo")]
        public class DemoAdminSurfaceController : SurfaceController
        {
    
            public DemoAdminSurfaceController()
            {
            }
    
            public DemoAdminSurfaceController(UmbracoContext umbracoContext)
                : base(umbracoContext)
            {
            }
    
            public ActionResult Index()
            {
                return View();
            }
        }
    }
    
    

    Last but not least we’ll have to create a view to back up the Index action on our controller that will for now will be one line:

    “<h1>Backend Demo Controller – view</h1>”

    Build the backend project and copy the dll to the Umbraco installation bin folder. Default will the view be searched in the following folder:

    [Umbraco ROOT]/App_Plugins/Demo/Views/DemoAdminSurface/. That is App_Plugins/[AreaName]/Views/[ControllerName]/. Create the folders and add the index view.

    I we go to the Umbraco backend we”’ll notice the 2 demo nodes still don’t do anything if we click them. We’ll first have to assign an action to these nodes.

    Assign an action to the nodes

    To assign an action to the nodes we’ll have to do two things. We’ll have to implement the RenderJS method in out Tree class and fill out the Action parameter from our nodes in the Render method.

    In the RenderJS method will render the necessary javascript that will open our editor in the right hand pane by using the ‘UmbClientMgr’ javascript object.

    public override void RenderJS(ref StringBuilder Javascript)
    {
    	Javascript.Append(
    	@"function openDemoController() {
    		UmbClientMgr.contentFrame('/Demo/DemoAdminSurface');
    	}");
    }
    

    In the Render method will add a call to the javascript action we just created (for now only on the first node).

    public override void Render(ref XmlTree tree)
    {
    	XmlTreeNode xNode = XmlTreeNode.Create(this);
    	xNode.NodeID = "1";
    	xNode.Text = "Demo Node 1";
    	xNode.Action = "javascript:openDemoController();";
    	xNode.Icon = "folder.gif";
    	xNode.OpenIcon = "folder_o.gif";
    	OnBeforeNodeRender(ref tree, ref xNode, EventArgs.Empty);
    	if (xNode != null)
    	{
    		tree.Add(xNode);
    		OnAfterNodeRender(ref tree, ref xNode, EventArgs.Empty);
    	}
    
    	XmlTreeNode xNode2 = XmlTreeNode.Create(this);
    	xNode2.NodeID = "2";
    	xNode2.Text = "Demo node 2";
    	xNode2.Action = "";
    	xNode2.Icon = "folder.gif";
    	xNode2.OpenIcon = "folder_o.gif";
    	OnBeforeNodeRender(ref tree, ref xNode2, EventArgs.Empty);
    	if (xNode2 != null)
    	{
    		tree.Add(xNode2);
    		OnAfterNodeRender(ref tree, ref xNode2, EventArgs.Empty);
    	}
    }
    

    Build the project and copy the dll to the Umbraco installation bin folder and refresh the backend in the browser. If we now click the first test node we’ll see the test view appear in the right hand side frame.

    Automating the copy process

    Just like in the previous blog post you can use the build events to automate the copy process of DLL’s and views. Place the 2 xcopy commands in the post build event.

    xcopy $(TargetPath) $(SolutionDir)UmbracoMVCDemo\bin\ /C /Y
    xcopy $(ProjectDir)Views $(SolutionDir)UmbracoMVCDemo\App_Plugins\Demo\Views\ /E /Y

    Source code

    You can find the solution above on Github.

    To do’s

    There are still some things I need to resolve:

    • Block access to the backend controller for non authenticated users
    • Adapt the actions that you get in the Umbraco back end by right clicking
    • ….

    Using MVC frontend pages in Umbraco 4.11.1

    Umbraco CMS

    Umbraco had a rough year, is the least we can say . After working on version 5 from the bottom up for almost 2 years they decided beginning 2012 to stop the version 5 with reason. Although I understand the reasons I’m very glad I didn’t had put any effort yet in the V5.

    Umbraco is an Open Source ASP.NET Content Management System that gives the developer a lot of freedom without interfering with the generated HTML, CSS and javascript. It has a steep learning curve but when you start to find your way into it, it gives you a lot of freedom.

    At my company we used the 4.7 version to create the company websites (abc-groep.be). In that version we could only use Webforms user controls to incorporate our own business logic. As I’m a big fan of MVC this stopped me to use the CMS for personal projects. The V5 version was the big promise to use MVC in Umbraco (it was actually build on MVC). Lucky for me the Umbraco developers have taken into account that MVC is a big deal for developers and while the V5 was dead the V4 version branch was enriched with MVC.

    In this post we’ll look into how you can use your own MVC controllers and views to create front end pages in an Umbraco installation.

    Installing Umbraco in new web project

    Let’s startup Visual Studio and create a new blank web project. Give it a name (here I used UmbracoMVCDemo) and click create. You’ll see that VS only creates an empty project with just 1 file, the web.config.

    image

    image

    After creating the project we’ll add Umbraco by Nuget. Open the Package Console Manager and type “PM> Install-Package UmbracoCms” and hit enter. You’ll see the installation of a couple of dependencies passing by and you should see “Successfully added ‘UmbracoCms 4.11.1’ to UmbracoMVCDemo.”. If you hit F5 you’re browser should fire up  and show the installation page of your local Umbraco CMS.

    image

    Folow the instructions to create your database (MS SQL Server, MS SQL Express Edition, MYSQL and) Microsoft SQL CE 4 database. Choose an administrator user and choose to have no template installed. (if you want you can install these later on).

    After installation go to http://localhost:53998/umbraco/login.aspx (choose the correct port as configured in IIS Express or IIS). Log in with your just created administrator and you should see an empty website.

    image

    We then only have to specify we want to use MVC for our views. Open up the Umbraco.Settings.config file in the config folder under the root. Find and alter the next setting:

    <defaultRenderingEngine>MVC</defaultRenderingEngine>

    Adding new project

    We start by adding a new project in our solution with a right click on the solution and choose Add – New Project

    image

    Choose a new ASP.NET MVC 3 Web Application and give it a name (in this demo UmbracoMVCDemo.FrontEnd).

    image

    In the next dialog choose for an internet application with Razor as View engine. We will need to have the Umbraco core libraries that we can add with Nuget. Open up the Package manager Console and type “Install-Package UmbracoCms.Core”, hit enter and wait for the “Successfully added ‘UmbracoCms.Core 4.11.1’ to UmbracoMVCDemo.FrontEnd.” message.

    Create new controller

    Add a new controller by right clicking the controllers folder and choose for Add – New Controller. Name it DemoController and choose for the Empty controller template.

    The controller needs to inhered from the Umbraco.Web.Mvc.RenderMvcController controller instead of the default ASP.NET Controller class. Next to that we’ll have to override the default Index Action method. We need to add a view for the Index action and add some test text in the view.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using Umbraco.Web.Models;
    
    namespace UmbracoMVCDemo.FrontEnd.Controllers
    {
        public class DemoController : Umbraco.Web.Mvc.RenderMvcController
        {
            //
            // GET: /Demo/
    
            public override ActionResult Index(RenderModel model)
            {
                //Do some stuff here, then return the base method
                return base.Index(model);
            }
    
        }
    }
    
    
    @{
        ViewBag.Title = "Index";
    }</pre>
    <h2>Index</h2>
    <pre>
    This is our own Demo controller and View.
    

    And that’s it, we’re ready to build. After building our Frontend project we’ll have to copy the generated UmbracoMVCDemo.FrontEnd.dll from the bin folder to the bin folder of our Umbraco installation. Next to the DLL we have to copy the Index.cshtml view from the views/Demo directory to the Umbraco installation views subfolder.

    Configuring Umbraco for our DemoController

    Umbraco uses a technique called ‘Hijacking routes’ to allow custom controllers. Basically will Umbraco for every Document Type check if he can find a controller that inhered the MVCRenderController and has the same name as the document type. If they can find a controller they will execute the overridden Index Action.

    Open up your Umbraco interface in a browser window and click on settings. Right click on Document Types and choose Create. Type Demo and uncheck “Create matching template”. That’s all configuration that has to be done.

    Go to the content section and right click on Content and choose Create. Select the Demo document type and name it Demo. After the entry is created click on the ‘save and publish’ button on top of the entry. Open up a  new browser tab and go to http://localhost:53998/Demo (change the port to the port in your IIS or IIS Express settings) and you’ll see our test text appearing.

    image

    Using own models, …

    At our.umbraco.org you’ll can find a lot of information on how to use your own custom models, bypass the Umbraco pipeline with your own routes, use templates to access different actions, ….

    Automate the copy process

    The copy action of the dll and your views can get a bit tedious after some time (in my case after the first time) but you can use after build events to automate this process. Open up the properties of the FrontEnd project and select the Buils events tab.

    In the Post-build event command line add:

    xcopy $(TargetPath) $(SolutionDir)UmbracoMVCDemo\bin\ /C /Y
    xcopy $(ProjectDir)Views  $(SolutionDir)UmbracoMVCDemo\Views\ /E /Y
    

    The views location

    We saw before that we had to copy the Index.cshtml view from our Frontend project to our Umbraco installation root – Views subfolder. Especially if you want to use multiple actions in a controller the Umbraco Views folder gets messy. I’m more a fan of a folder per controller with in there the views for that controller.

    That’s possible but there is a catch. The Umbraco engine checks if the view is present in the Views folder before allowing the request to use your controller. If the view is missing an empty page is returned. But if we add a Demo folder and add our index.cshtml view in there we’ll see that that view will be used before the view in the root views folder. (This seems to be intended and default ASP.NET MVC behavior)

    Therefor we only need a placeholder view in the basic views folder. This can be an empty view or just add a text that refers to the correct folder. And we can then create a Demo subfolder and add the correct views in that Demo folder.

    The post build action will also copy the views to the correct subfolder instead of the root views folder.

    Second part to be careful with is when creating multiple controllers there will be multiple Index.cshtml views what will give problems in the root views folder. I can strongly recommend creating a second action with an unique name so you can use templates with a unique name for every controller.

    Source

    You can find the demo project at Github.

    Next…

    In a next blog post we’ll look into using our own MVC controllers to create backend functionality.

    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.

    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.