Wednesday, 30 March 2016

Slack Slash Commands and ASP.Net Web Hooks

Cross-posting a link to a piece written for my company's blog on Slack Slash Commands and ASP.Net Web Hooks.

Monday, 15 February 2016

Getting Started with MS Dynamics API

This is mostly a "note to self" post following some research and prototyping into working with the Microsoft Dynamics API from ASP.Net but might also be useful for anyone else that stumbles across it trying to get things working on this front.

Accessing a Dynamics Instance

First step for me was to get access to an instance of MS Dynamics to work with by signing up for a free trial. This gives access to a fully featured set up of Dynamics that you can work with for 30 days.

You'll need to sign up with a user name and password and get assigned a sub-domain that will be of the form *.onmicrosoft.com. All of these will be needed for accessing via the API.

Working with the API

Starting with an empty ASP.Net MVC application, the first step is to install a NuGet package:

PM> Install-Package Microsoft.CrmSdk.Extensions

And then add references to the following assemblies:

  • System.IdentityModel.dll
  • System.Data.Services.dll
  • System.Data.Services.Client.dll
  • System.Runtime.Caching.dll
  • System.Runtime.Serialization.dll

Make sure you have .Net 4.5.2 installed and the project set up to target this version of the framework.

With that in place, the following code that creates a new Account record in Dynamics should run successfully:

 public ActionResult Index()
 {
  var crmConnection = CrmConnection.Parse("Url=https://mydomain.crm4.dynamics.com; Username=username; Password=password;");
  var service = new OrganizationService(crmConnection);

  var account = new Entity("account");
  account["name"] = "Test Account";

  var accountId = service.Create(account);

  var result = "Account created with Id: " + accountId;
  return Content(result);
 }

Using Strong Typing

Whilst the above is fine for simple integrations to work with Dynamics data in a more maintainable way it's likely we'd want to make use of strong typing.

To get this working I downloaded the CRM SDK (file: MicrosoftDynamicsCRM2016SDK.exe)

And then from a command prompt opened at C:\Program Files\MS Dynamics SDK\SDK\Bin:

CrmSvcUtil.exe /out:c:\temp\Xrm.cs /url:https://mydomain.crm4.dynamics.com/XRMServices/2011/Organization.svc /username:username /password:password /namespace:Xrm /serviceContextName:XrmServiceContext

This generated a file called Xrm.cs which can be copied into the project. And then code such as the following can be run:

 public ActionResult Index()
 {
  var crmConnection = CrmConnection.Parse("Url=https://mydomain.crm4.dynamics.com; Username=username; Password=password;");
  var service = new OrganizationService(crmConnection);

  var account = new Account
  {
   Name = "Test Account 2",
  };
  account.Id = service.Create(account);

  var result = "Account created with Id: " + account.Id;
  return Content(result);
 }

References

Thursday, 31 December 2015

Working with View Models in Umbraco and EPiServer

Cross-posting an article I've written for my company Zone's Medium blog. I've written about techniques for using strongly typed view models with Umbraco here before - in this article I recap some of that and extend the discussion to EPiServer CMS too.

You can read and comment on the article here.

Friday, 9 October 2015

ASP.Net 5 and C# 6: Slides and Resources

ASP.Net 5 and C# 6: Slides and Resources

Had the pleasure of speaking yesterday at the London Umbraco meet-up hosted at Zone on the topic of ASP.Net 5 and C# 6. For anyone who was there and wants a reference, or who wasn't and is interested in an introduction to this area, I'll post a few resources.

Firstly the slides from the talk are available here.

And then here's a number of links to blogs and other online resources that I've used in researching the topic and preparing the talk:

You can even watch it if you like.

Thanks to Ali, Ravi for organisation last night and all the attendees.

Saturday, 26 September 2015

DDD, CQRS and testing with ASP.Net MVC: Slides and References

Just had the pleasure of attending and speaking at the Web European Conference in Milan.

For anyone that attended my talk, or any that didn't but were tempted more by another session, here's some links to slides and references.

Slides can be found here at slideshare.net

And here's a few links to blog posts I've written before on the subject:

A few references to sources I used in researching and constructing the presentation:

Finally just to say a big thanks to all attendees, the organisers and sponsors. Hope to be back next year.

Sunday, 23 August 2015

Code As Data With Reflection

Other than occasional use, working with reflection using C# isn't something I've had that much need to do. Recently though I was working on an additional feature for the Umbraco package The Dashboard. It provides a nice first screen for editors, showing their recent edits and other work carried out on the site content.

The idea for the new feature was to create a developer version of this, that displayed various details about the code that had been implemented on the project. The use case being in the case of inheriting or coming back to a site, being able to have a quick overview of the techniques that have been used for route hijacking, surface controllers, application events and the like.

In order to implement this it was going to be necessary to make quite heavy use of reflection and this post highlights a few of the methods used.

Getting instances of types

In the case of Umbraco route hijacking using custom controllers it's necessary to implement an MVC controller that implements an interface (IRenderMvcController). Similarly for surface controllers, you need to inherit from a base class (SurfaceController). So to find all the instances of these I needed to search all the assemblies of the project and find all non-abstract, classes that implemented a given interface or inherited a given base type. I also wanted to exclude anything that came with the Umbraco core itself as that wasn't useful to display.

Here's the code I used:

public class ControllerDetailDto
{
    public string Name { get; set; }

    public string Namespace { get; set; }
}

public IEnumerable<ControllerDetailDto> GetControllersAssignableFrom(Type baseType)
{
    return GetNonCoreTypesAssignableFrom(baseType)
        .Select(x => new ControllerDetailDto
        {
            Name = x.Name,
            Namespace = x.Namespace,
        });
}

private IEnumerable<Type> GetNonCoreTypesAssignableFrom(Type baseType)
{
    return AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(s => s.GetTypes())
        .Where(p => baseType.IsAssignableFrom(p) && p.IsClass && !p.IsAbstract && !p.Namespace.ToLower().StartsWith("umbraco."));
}

Getting method details

In the case of custom controllers used for route hijacking, I also wanted to get the list of action methods. This was done by finding all public, non-static methods direct declared on the controller and filtering by those that returned ActionResult or something inheriting from it. I was only interested in the GET ones so obtained all those by excluding any that had an [HttpPost] attribute.

The crucial part of the code for doing this was as follows:

public IEnumerable<string> GetActionMethodsOnController(Type controllerType)
{
    return controllerType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
        .Where(x => typeof (ActionResult).IsAssignableFrom(x.ReturnType) &&
            !x.Name.StartsWith("get_") &&
            (!x.GetCustomAttributes(typeof (HttpPostAttribute), false).Any()))
        .Select(x => x.Name)
        .OrderBy(x => x);
}

Getting event details

The last task I had was to get details of the application event handlers that had been registered. For a given Umbraco service, e.g. ContentService, there are a number of methods that may have handlers registered on it - to carry out actions on Saving of content for example.

This wasn't particularly straightforward but I got some help from this blog post by David Kowalski and a chapter he referenced from C# in Depth. The code I used to get this information was as follows:

public class ReflectedClassDto
{
    public string Name { get; set; }

    public string Namespace { get; set; }
}

public class CustomEventDto
{
    public string EventName { get; set; }

    public IEnumerable<ReflectedClassDto> Handlers { get; set; }
}

public IEnumerable<CustomEventDto> GetCustomEvents(IService serviceInstance)
{
    return serviceInstance.GetType().GetEvents()
        .Select(x => new CustomEventDto
        {
            EventName = x.Name,
            Handlers = GetCustomEventHandlers(serviceInstance, x)
        })
        .Where(x => x.Handlers != null && x.Handlers.Any());
}

private static IEnumerable GetCustomEventHandlers(IService serviceInstance, EventInfo eventInfo)
{
    var fi = GetEventField(serviceInstance, eventInfo);
    if (fi != null)
    {
        var del = fi.GetValue(serviceInstance) as Delegate;
        if (del != null)
        {
            return del.GetInvocationList()
                .Where(x => !x.Method.DeclaringType.FullName.ToLower().StartsWith("umbraco."))
                .Select(x => new ReflectedClassDto
                {
                    Name = x.Method.Name,
                    Namespace = x.Method.DeclaringType.FullName,
                });
        }
    }

    return null;
}

private static FieldInfo GetEventField(IService serviceInstance, EventInfo eventInfo)
{
    return serviceInstance.GetType()
        .GetField(eventInfo.Name,
            BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public |
            BindingFlags.FlattenHierarchy);
}

The first step is to get the list of events defined on the service instance - these are things like OnSaving etc - that have at least one handler defined. To get the event handlers we then extract the private field that backs the event and obtain the value of that field as a delegate (of type MulticastDelegate). With that there's a method called GetInvocationList() that allows you to retrieve all the defined handlers for the event. Again I remove all the ones that come with the Umbraco Core.

To see this in context see the open-source repository for the package and specifically this file.

Friday, 7 August 2015

(Yet) Another Look at Unit Testing Umbraco Surface Controllers

A quick recap

A little while back now I spent a bit of time investigating how one might go about unit testing Umbraco surface controllers. With the help of information posted by some others that had similarly looked into it I found there was a method that worked, but it wasn't ideal for a number of reasons.

Firstly there was a need to utilise an Umbraco test helpers dll, that contained implementations of various base classes that could be used to support testing. No great hardship to use that but it did mean you had to compile the source to get it and it led to some other restrictions on your tests.

One of those being you had to use NUnit. Again, a perfectly decent test runner but if you generally used MSTest or something else you had to make a switch.

And lastly in order to create various surface controller dependencies, you had to use some rather impenetrable looking reflection code to get around the fact that certain classes and methods were marked as internal rather than public. This worked, and only needed to be written once in a a base class to utilise it in all your tests, but was rather brittle. Code marked as internal is done so for a reason, one of those being that even if it's potentially useful to provide public access to developers, the core team haven't yet committed to the implementation so reserve the right to change it, even in a minor upgrade.

Putting all that together probably explains that although I did have a method that worked it wasn't something I made part of my general work with Umbraco.

The situation today

One thing I've been following and looking forward to the release of version 7.3 of Umbraco is the discussion on improved testing support. And given the recent release of this in beta, wanted to check it out.

Am pleased to report things are a lot easier now. There's still a bit of set-up and mocking code required, but that's unavoidable to ensure the surface controller has access to things like the Umbraco context in it's operations. But there are no base classes that you are required to depend on, no tie to a particular unit testing framework and no longer a requirement for reflection code.

As well as what follows, you can see some more examples of this in the Umbraco source code itself - which I used for reference. You can also take a look through the code of the Umbraco REST API which as noted in the comments below also contains several examples.

An example

I'll go back to the simple example I was looking to test in the previous blog post:

[HttpPost]
public ActionResult CreateComment(CommentViewModel model)
{
    if (!ModelState.IsValid)
    {
        return CurrentUmbracoPage();
    }

    TempData.Add("CustomMessage", "Thanks for your comment.");

    return RedirectToCurrentUmbracoPage();
}

And I have these two tests:

[TestMethod]
public void CreateComment_WithValidComment_RedirectsWithMessage()
{
    // Arrange
    var controller = GetController();
    var model = new CommentViewModel
    {
        Name = "Fred",
        Email = "fred@freddie.com",
        Comment = "Can I test this?",
    };

    // Act
    var result = controller.CreateComment(model);

    // Assert
    var redirectToUmbracoPageResult = result as RedirectToUmbracoPageResult;
    Assert.IsNotNull(redirectToUmbracoPageResult);
    Assert.AreEqual(1000, redirectToUmbracoPageResult.PublishedContent.Id);
    Assert.IsNotNull(controller.TempData["CustomMessage"]);
}

[TestMethod]
public void CreateComment_WithInValidComment_RedisplaysForm()
{
    // Arrange
    var controller = GetController();
    var model = new CommentViewModel
    {
        Name = "Fred",
        Email = string.Empty,
        Comment = "Can I test this?",
    };
    controller.ModelState.AddModelError("Email", "Email is required.");

    // Act
    var result = controller.CreateComment(model);

    // Assert
    var umbracoPageResult = result as UmbracoPageResult;
    Assert.IsNotNull(umbracoPageResult);
    Assert.IsNull(controller.TempData["CustomMessage"]);
}

To support testing there's a need to make a minor amend to the controller itself, to create a constructor that allows the passing of an instance (mocked for testing) of the Umbraco context and helper:

public class BlogPostSurfaceController : Umbraco.Web.Mvc.SurfaceController
{
    private readonly UmbracoHelper _umbracoHelper;

    public BlogPostSurfaceController(UmbracoContext umbracoContext)
        : base(umbracoContext)
    {
    }

    public BlogPostSurfaceController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper)
        : base(umbracoContext)
    {
        _umbracoHelper = umbracoHelper;
    }

    public override UmbracoHelper Umbraco
    {
        get { return _umbracoHelper ?? base.Umbraco; }
    }
}

And then in the test project I need to implement the helper method I've created above called GetController(). I've placed all this code in my test class but in practice it would make sense to move much of this into your own test base class, so it can be reused across tests.

private BlogPostSurfaceController GetController()
{
    var appCtx = MockApplicationContext();
    var umbCtx = MockUmbracoContext(appCtx);

    var controller = new BlogPostSurfaceController(umbCtx, new UmbracoHelper(umbCtx));
    SetupControllerContext(umbCtx, controller);

    return controller;
}

private static ApplicationContext MockApplicationContext()
{
    return new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(),
        new ProfilingLogger(new Mock<ILogger>().Object, new Mock<IProfiler>().Object));
}

private static UmbracoContext MockUmbracoContext(ApplicationContext appCtx)
{
    return UmbracoContext.EnsureContext(
        new Mock<HttpContextBase>().Object,
        appCtx,
        new Mock<WebSecurity>(null, null).Object,
        Mock.Of<IUmbracoSettingsSection>(section => section.WebRouting == Mock.Of<IWebRoutingSection>(routingSection => routingSection.UrlProviderMode == "AutoLegacy")),
        Enumerable.Empty<IUrlProvider>(),
        true);
}

private static void SetupControllerContext(UmbracoContext umbCtx, Controller controller)
{
    var webRoutingSettings = Mock.Of<IWebRoutingSection>(section => section.UrlProviderMode == "AutoLegacy");
    var contextBase = umbCtx.HttpContext;
    var pcr = new PublishedContentRequest(new Uri("http://localhost/test"),
        umbCtx.RoutingContext,
        webRoutingSettings,
        s => Enumerable.Empty<string>())
    {
        PublishedContent = MockContent(),
    };

    var routeData = new RouteData();
    var routeDefinition = new RouteDefinition
    {
        PublishedContentRequest = pcr
    };
    routeData.DataTokens.Add("umbraco-route-def", routeDefinition);
    controller.ControllerContext = new ControllerContext(contextBase, routeData, controller);
}

private static IPublishedContent MockContent()
{
    return Mock.Of<IPublishedContent>(publishedContent => publishedContent.Id == 1000);            
}

Just for completeness, to run the code you will need to pull in the following from NuGet:

    PM> Install-Package UmbracoCms.Core -Pre
    PM> Install-Package Moq

And make sure you add framework references to System.Web, System.Configuration and System.Web.ApplicationServices.

The full list of using statements are as follows:

using System;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SurfaceControllerUnitTests.Controllers;
using SurfaceControllerUnitTests.Models;
using Umbraco.Core;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Profiling;
using Umbraco.Web;
using Umbraco.Web.Mvc;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;

Great to see this improved testing support with the latest Umbraco. Not seen too much being made of it yet but for me an important part of this upcoming Umbraco release is it now being so much more accessible to testing.