Category Archives: Development

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, …

    Roadmap for ASP.NET MVC, ASP.NET Web API, and ASP.NET Web Pages

    I saw a tweet from John Galloway (@jongalloway) coming by this evening that can interest any developer in the ASP.NET stack. It’s a draft of the features that Microsoft want to include in the next release of the stack.

    There are no release dates and they do emphasize it’s a planning document but I like the way Microsoft is going with the open sourced ASP.NET stack.

    http://aspnetwebstack.codeplex.com/wikipage?title=Roadmap

    Creating a JIRA interface in 1-2-3

    For one of our projects where close to the first test release. While preparing the necessary documents (test overview, legal documents, bug report, …) I felt a bit ashamed to give the client a Word document to report bugs to us. For a software development company it’s a bit shameful to let the client fill out a paper, scan it, mail it and then have someone copy the document in our issue tracker.

    While driving home I thought it couldn’t be that difficult to set up a small site where the client can report the bugs. But I didn’t want to create a new bug tracker nor give the client direct access to our issue tracker (JIRA from Confluence).

    JIRA has a API that you can address to create and fetch issues from their tracker. But I didn’t want to  spend a couple of hours implementing the REST service. (jeah, I know, lazy as hell)

    Nuget to the rescue

    When I got home, the first thing I checked was the nuget site to see if anyone had already created a package to communicate with the JIRA API. First thing that showed up in the search was Atlassian.SDK a complete package, even including a Linq Query implementation to search for issues created by Federico Silva Armas.

    image

    Great, let’s get started.

    New MVC 4 web application

    I fired up Visual Studio 2012 and choose a new MVC 4 Default application with Razor support. Opened up the Package Manager Console and ran the following command:

    Add controller

    I added a new controller in the controllers folder and named it HomeController. In the Index method I’ve added the call to JIRA to fetch all items from a certain filter.

    The implementation is really simple, create a new Jira object with as parameters the URL to your JIRA instance, a username and a password. (in the constructor)
    In the Index method you then can call GetIssuesFromFilter and add the filtername as parameter. The advantage of using a filter is that you can always change this filter settings if you want to remove certain issues from the result without to change anything in your application.

    You’ll need off course the user rights correctly set in JIRA to access the issues that are returned from the filter.

    Add View

    Next I created a new view under the Views – Home folder using the add view action after a right click on the folder. Create a strongly-typed view by selecting the Atlassian.Jira class as Model class.

    image

    Click Add and the view is created.

    If you hit F5 now, your browser should open up and you get already the overview screen for all issues returned from the filter you have selected.

    In 10 minutes I’ve created a working (but ugly) web application that can fetch all the tickets I wanted to show to the customer. Of course your view will need some tweaking to show the values of the issues you want to be shown.

    Adding a new issue

    Adding a new issue to JIRA is as simply. (You can check the complete code on Github). I give you a (very) short overview.

    Create 2 new methods Create in the HomeController. The first one just returned the view, the second one add the HttpPost attribute and this will receive an Atlassion.Issue object with all the values. Pushing this to JIRA is as simple to create a new issue object from the jira object and fill up the values. Hit SaveChanges on the jira object and your issue is created.

    On thing I had a problem with is the projetc name – key difference in the jira.CreateIssue() method. I first tried with the project name but I got some HTML 500 error returning. Although for fetching issues this worked fine but for creating issues you apparently have to gibe the project key instead of the project name.

    Look and feel

    Ok, we have a working application but the look and feel isn’t that, certainly not enough to send to an end user. I didn’t wanted to spend to much time on the look and feel and decided to use the Twitter Bootstrap.

    Don’t start downloading the package from the Twitter Bootstrap website. Instead use the nuget package manager again. There is a Bootstrap for MVC 4 package that will add all necessary items to your solution.

    Open up the Package Manager Console again and run the following command:

    Add bootstrap to the bundles

    To add the bootstrap files to your application we’ve to alter the style and script bundles that are in use. Open up the BundleConfig.cs class in the App_Start folder. There we can add the necessary files to the bundles.

    Online 28 I changed the the Content/css bundle to include the bootstrap css instead of the default Site.Css. On line 21 I added a script bundle to include the bootstrap.js file.

    Because I added a script bundle we’ll have to add this bundle in the _ Layout.cshtml view.

    Just underneath the rendering of the jQuery bundle add the rendering of the bootstrap bundle. (at the bottom of the view.

    Result

    I was able to create an new interface for our client to report bugs in just an hour of two. (the above only took 30 min but I’ve added some extra logic to send emails and stuff). Off course it’s not correct to add all business logic in your controllers and to hard code some strings and stuff. For this small application it’s more then enough. Underneath the screenshots of the 2 pages (in Dutch).

    image

    image

    Source code

    You can find this project on Github, feel free to fork, comment, …

    One note, to avoid adding my personal credentials to the project I’ve created an xml file that holds the credentials in the App_Data folder. When creating the Jira object I fetch the values from this file. For obvious reasons I added this file to the .gitignore so it wouldn’t be pushed to Github. The structure of the file:

    Creating graphs in WPF using OxyPlot

    For one of our projects we had to retrieve data from an external source and store them in a database. One of the requests from the client was to see the retrieved data in a graph. Furthermore, he wanted to see a live update every second of the retrieved data in that graph.

    After some searching I found the OxyPlot library. This library can be used in WPF, Silverlight, Windows Forms and even in Windows Store apps. The are now working on a alpha release for  Mono.

    Although the package is already downloaded more then 10 000 times there are not so many blog posts to find about implementing the library.

    Using Nuget

    The easiest way to include OxyPlot in you application is by using the Nuget package manager in Visual Studio.

    Open op Visual Studio and start with creating a new WPF project. Choose a name and a location and hit ‘OK’.

    image

    After the project is created open up the Package Manager Console and type following commands at the prompt and hit enter (after every command):

    • Install-Package Oxyplot.Core
    • Install-Package Oxyplot.Wpf

    image

    You can of course use the Package Manager UI by right clicking References and choose Manage Nuget Packages and them that way.

    Create the ViewModel

    We’ll use the MVVM model (partial) to render the Graph on the screen. First step is to create the ViewModel for our MainWindow.xaml. Right click on the project and add a folder ViewModels. Right click the folder and add a class MainWindowModel.cs.

    image

    To use the MVVM model we need to make the class public and inherit the INotifyPropertyChanged interface.

    NOTE: The OxyPlot WPF package doesn’t completely support the MVVM model. You can’t use only the OnPropertyChanged method to update the graph. You’ll still need the manually refresh the graph from the code behind class of the XAML page. I saw a post in the discussions on codeplex that they are looking to add complete MVVM model but are short of time at the moment. Maybe the next version will support it. To be complete I add the necessary steps to implement the MVVM model in this post.

    After inheriting the interface we have to implement the PropertyChangedEventHandler event as shown below.

    Now we can add some public properties that we’ll bind to in the XAML page. First create a PlotModel that’s part of the OxyPlot library. In the constructor we’ll initiate the PlotModel parameter. The setter will call the OnPropertyChanged method that will notify the view there is a change on the object that may have to be rendered.

    Adding the graph to the page

    We can now add the graph to the MainWindow.xaml page. Before we can add the graph we’ll need to add the namespace for the OxyPlot library (line 4). We’ll bind the PlotModel parameter to the PlotModel we’ve created in the view model.

    Binding the model to the view

    Last part for our setup is to bind the view model to the view. Because we don’t use any MVVM frameworks we’ll have to manually bind the model in the code behind of the MainWindow.xaml page.

    Add a private property of our view model and initiate this property in the constructor. Point the DataContext to this property and we’re done.

    If we hit F5 to run the application we’ll see an empty window opening. We have of course add some data to the PlotModel before the graph will be rendered.

    Set up the Graph – PlotModel

    Back to our view model to set up our view model. First start will be adding the axes for the graph so OxyPlot knows where to plot the points.

    Create a new method SetUpModel in our view model class. In here we’ll define the legend of the graph (position, border, sire, …) and add 2 axis. A DateTimeAxis for our X-axis (we want to plot points in a line of time) and a ValuaAxis for our Y-axis.

    The set up for the legend of the graph is self explanatory. At line 10 you’ll see the creation of the DateTimeAxis. We’ll choose the position of the axis, give it a name (Date) and a string format pattern how the date has to be displayed. Next to that we’ll add some parameters to show major and minor gridlines and the interval size. After creation we’ll add the axis to the PlotModel.
    The ValueAxis is similar initiated, only did we position the axis on the left side and tell the Axis to start at the value 0.

    If we add a call to this method in the constructor of our view model and hit F5 again we’ll now see window opening that contains an empty graph.

    image

    The data

    Now we have our graph and are ready to add some graph lines to the PlotModel. In this post we’ll add four different lines that will be plot.

    To avoid complexity I added a class Data.cs where the data is hardcoded.  In a real life application you’ll be implementing a database call or a service invocation or a web API request, …

    The data I’ll receive will be a List<T> of a new simple class I’ve created: Measurement. This class has 3 public parameters: a DetectorId (long), a Value (int) and a DateTime (DateTime). I’ve added 4 different detectors that each have 10 measurements of a random value between 1 and 30.

    Add the data to the PlotModel

    In the view model we’ll create a new method LoadData where we’ll get the data and add some code to plot all point on the graph.

    After fetching the data I’ll use the LINQ GroupBy expression to create a IEnumerable with as key the DetectorId and a collection of Value and Datetime as values. (line 5)

    This will allow us to loop over the result and then add a LineSerie per Detector. In the setup of the LineSerie we’ll set some properties like colors and line thickness and the title. (line 9 till 18).

    After we’ve created the LineSerie we can add the points to the LineSerie. We make use of the DateTimeAxis builtin funtion to convert a date to a double and add the value (line 20).

    After we added the points to the LineSerie we’ll still have to add the LineSerie to the PlotModel. (line 21).

    And that’s it. Hit F5 and you’ll see that are graph will be rendered and that per detector a line will appear plotting the random values between 1 and 30.

    image

    Updating the graph real-time

    For the second question of our client we had to add real-time updates. For this demo I’ll add an new measurement to the graph every second. The OxyPlot library will make sure our graph will move along every time we’ll add a new measurement.

    I’ve added a static method in the Data.cs class that will return a random value a second after the DateTime parameter that will be send along. In the view model I’ve created a private parameter DateTime parameter (lasUpdate) that will hold the moment we last updated the graph.

    Update the view model

    We’ll add a new method to the view model UpdateModel. This time we’ll make it public so it can be called from the view as shown in the next chapter.

    In the UpdateModel method we’ll fetch the data from out Data.cs class and perform the same grouping action as in the LoadData method.

    This will allow us to fetch the data per detector. After retrieving the correct LineSerie we can add the points like we did in the LoadData method.

    Update from the view

    We don’t want the update of the model to initiate before the previous is completely rendered to avoid an exception that we are modifying a list while rendering the graph. Therefor we make use of a  CompositionTarget.Rendering event. This event will be fired every time the view is done rendering.

    In the constructor of the MainWindow.xaml.cs class we’ll attach an eventhandler on the Rendering event.

    In the event handler we’ll call the update method from the view model. After that call we’ll have to tell the PlotModel that there was an update and that he has to refresh the graph (line 14). (This is where OxyPlot drifts away from the MVVM model).

    Avoid to many updates

    The rendering event is ideal to avoid exceptions but you’ll see to many updates per second to keep the graph readable. We can solve this to add a StopWatch in the code behind and only trigger the update when the last update is at least a second ago.

    After adding the StopWatch we’ll see that every (for this demo 5 seconds) a new point is added to the graph.

    image

    Source code

    As you can see, with OxyPlot you don’t need to write to many code to create real time updating charts.

    OxyPlot has many more options and graph styles, they have provided a demo page where a variety of graphs are rendered in Silverlight. You can copy the source code with the keyboard combination Ctrl+Alt+C. If you want to copy the properties use Ctrl+Alt+R.

    The source code of this post can you find on Github. Feel free to fork, download, …

    The hard search for missing Extension methods in Umbraco 4.7.0

    Implementing SignalR

    For one of our company websites we got the question from HR to implement a chatbox on the website so interested candidates could contact them in an easy way. After comparing a few open source alternatives we decided to build our own using the just released SignalR framework.

    Everything worked fine on our development server where we’re running a backup of the production Umbraco website. Our dev team could easily create the chatbox and sooner as expected we had a working chatbox to present to HR.

    Moving changes to staging

    Like all our development projects we work in different steps. Development on the local machine or development server, client tests on the staging machine. This way we remove the risk that some developers test come in the way of our clients testing.

    For this implementation the client is our own HR department, still we follow the same development guidelines to avoid test data on the acceptance (staging) environment.

    Extension methods missing

    After copying all DLL’s and usercontrols to the staging environment we noticed that all of our Macros in Razor where failing. Suddenly the ‘umbraco.MacroEngines.DynamicNodeList‘ was missing the extension methods like ‘First’ and ‘FirstOrDefault’.

    image

    Start debugging

    First reaction was of course to delete all the DLL’s we’ve altered for this last release and to reinstate the old DLL’s. Still we faced the same problem.

    Back to start, we took a new backup from the production server and started the deploy again. There we noticed we overwritten a third party DLL ‘Newtonsoft.Json.dll’, a well known library for Json conversions created by James Newton-King. More information on his website.

    We skipped the replacement of the DLL and all of our Razor scripts we’re working like before. Problem solved (we thought).

    SignalR failed to work

    After the re-deploy of our chatbox DLL’s and usercontrols we couldn’t get the chatbox to work. It seemed the SignalR hub was missing to contact the server to register a chat user. A check with Firebug reveled the hub couldn’t be loaded because a DLL reference couldn’t find the correct version of the DLL. Of course the ‘Newtonsoft.Json.dll’ was playing up again.

    image

    Some more debugging

    No problem, we find out where Umbraco references the DLL and update it to the latest version and rebuild the Umbraco DLL and we’re good to go. Wrong, we checked the source of the 4.7.0 version that was available on codeplex but no sign of ‘Newtonsoft.Json.dll’.

    Then it had to be one of our own projects referencing the DLL? No, none of our own project had a reference to the ‘Newtonsoft.Json.dll’.

    I loaded the project on disk, configured it in IIS and attached the Visual Studio debugger. In the Debug menu –> windows –> Modules component I could find the ‘Newtonsoft.Json.dll’ reference but no way to find out witch component was responsible for loading the DLL.

    Some more (manual) debugging

    As I couldn’t find a way to find out who was responsible for loading the DLL I had only one option left.

    I took a look at the download at codeplex and removed all DLL’s that were not in the original download. Of course some other problems showed up as all custom created usercontrols failed to load but the Razor Extension methods worked and I could start a tedious process of adding DLL’s to the bin folder with my Visual Studio debugger attached and to reload the site every time.

    Found the problem

    When I copied the ‘Twitterizer2.dll’ back into the bin folder the Razor scripts failed again. I finally found the source of the problem. After a quick look at the Github repository of the Twitterizer project I found the Newtonsoft references and the different versions in the packages folder.

    Resolving the problem

    I did found the problem but we wanted to keep the Twitter possibilities that we had implemented before so we needed the Twitterizer2 DLL.I forked the project on Github and cloned the project locally.

    After updating the package to the latest version (the same our SignalR implementation was using) I’ve rebuilded the DLL and copied it to the Umbraco bin folder. Finally we had our Razor scripts working and our chatbox was responding!

     

    It took me half a day of debugging before I did found the problem. If anyone has a good way to find out witch component loads a certain DLL, let me know in the comments or by a tweet, …

    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.