Method chaining with deferring object creation

I have decided to write a couple of posts about how I used Method Chaining to help solve and better handle the creation of test data within my Unit Tests. This post and the example code via GitHub shows how I created test data using Method Chaining in a more generic form. There will be more posts to come regarding how this test data gets persisted into a in-memory database which will get used in XUnit Tests.

For my problem, I had to build up test data that will be used within a number of Unit Tests. Creating objects and assigning values to properties through Factory classes is considered a fairly normal approach, however being able to build up objects using method chaining gives me the flexibility to create objects with different characteristics.

For example, var foo = MyFooBuilder.Create().WithName(“My Foo”).WithAge(5).WithCar(“Audi”).Build(). This allows me to build up a foo object using a nice fluent chaining of methods compared to var foo = new Foo() { Name = “My Foo”, Age = 5, Car = “Audi” }. This allows me to keep all the Foo created code in a nice and tidy builder class which provides the flexibility to extend the builder to introduce new characteristics in the future.

What I ended up creating was a generic builder class that allows me to use a object of type T, build up a set of actions to get a newly created object. for example, var foo = MyBuilder.Create().WithProperty(new { Name = “MyPropertyName”, Value = “MyValue” }).Build();

You can view my builder class at https://github.com/codelabnz/BuilderExample

The call is ambiguous between the following methods or properties: ‘Umbraco.Web.UmbracoHelper.Media

I was coding up a new template in the latest version of Umbraco v7 using Razor and discovered this error when trying to get a Media object from one of my properties of the current page.


The call is ambiguous between the following methods or properties: ‘Umbraco.Web.UmbracoHelper.Media(params int[])’ and ‘Umbraco.Web.UmbracoHelper.Media(params string[])’

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: The call is ambiguous between the following methods or properties: ‘Umbraco.Web.UmbracoHelper.Media(params int[])’ and ‘Umbraco.Web.UmbracoHelper.Media(params string[])’

My property was a Media Picker type which I made the assumption it was given me a Integer Node Id to the specific media object.

I started out with the following code:

1
@Umbraco.Media(CurrentPage.ProfileImage).umbracoFile

This caused the error above, so by converting it to a string using the .ToString() method, this caused the compiler to ignore the error and use the correct UmbracoHelper method.

1
@Umbraco.Media(CurrentPage.portfolio5Image.ToString()).umbracoFile

Upgrading MVC Project 2 to 4 and open it in VS 2012

I have an old MVC 2 project that works fine in VS 2010. However, if you try and open the project in VS 2012 you will get a “incompatible” error and left with no way to upgrade the project to VS 2012.

Here are some pointers to get it working (this is how I got it working for myself).

In VS2010, upgrade your MVC project to version 4. You need to follow the upgrade steps for upgrading to MVC 2 – 3 first.

http://www.asp.net/whitepapers/mvc3-release-notes#upgrading

Secondly, upgrade from MVC 3 to 4 using the following link.

http://www.asp.net/whitepapers/mvc4-release-notes#_Toc303253806

Once you have done this, you need to edit the project file of the working web application (i.e csproj). Firstly, open the solution in VS2012, the web project will not work but you can edit the project file directly in the IDE.

Make sure that you add the MVC 4 ProjectTypes GUID ({E3E379DF-F4C6-4180-9B81-6769533ABE47}) and remove the old MVC ProjectTypes GUID ({F85E285D-A4E0-4152-9332-AB1D724D3325}).

Here is a list of available GUIDS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Windows (C#) {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
Windows (VB.NET) {F184B08F-C81C-45F6-A57F-5ABD9991F28F}
Windows (Visual C++) {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}
Web Application {349C5851-65DF-11DA-9384-00065B846F21}
Web Site {E24C65DC-7377-472B-9ABA-BC803B73C61A}
WCF {3D9AD99F-2412-4246-B90B-4EAA41C64699}
WPF {60DC8134-EBA5-43B8-BCC9-BB4BC16C2548}
XNA (Windows) {6D335F3A-9D43-41b4-9D22-F6F17C4BE596}
XNA (XBox) {2DF5C3F4-5A5F-47a9-8E94-23B4456F55E2}
XNA (Zune) {D399B71A-8929-442a-A9AC-8BEC78BB2433}
Silverlight {A1591282-1198-4647-A2B1-27E5FF5F6F3B}
ASP.NET MVC {F85E285D-A4E0-4152-9332-AB1D724D3325}
ASP.NET MVC 4 {E3E379DF-F4C6-4180-9B81-6769533ABE47}
Test {3AC096D0-A1C2-E12C-1390-A8335801FDAB}
Solution Folder {2150E333-8FDC-42A3-9474-1A3956D46DE8}

http://stackoverflow.com/questions/2911565/what-is-the-significance-of-projecttypeguids-tag-in-the-visual-studio-project-fi

From here you reload the project (after you save the project file) and a way you go.

Get All Nodes By DocumentType

The following code describes how to get all the nodes by a particular document type across the whole Umbraco site. It uses a recursive method so if you add this as a macro I would suggest caching to reduce the number of times this method runs.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using umbraco.presentation.nodeFactory;


public class UmbracoHelper
{
    private const int CONST_NODEAMOUNT = 10;
    /// <summary>
    /// Get all nodes by type, put -1 to start at the root of the website
    /// </summary>
    /// <param name="NodeId"></param>
    /// <param name="typeName"></param>
    /// <returns></returns>
    public static List<Node> GetAllNodesByType(int NodeId, string typeName)
    {
        List<Node> foundNodes = new List<Node>();
        var node = new Node(NodeId);
        foreach (Node childNode in node.Children)
        {
            var child = childNode;
            if (child.NodeTypeAlias == typeName)
            {
                foundNodes.Add(child);
            }

            if (child.Children.Count > 0)
                GetAllNodesByType(ref foundNodes, child, typeName);
        }

        //Take the first 10, this can be changed
        return foundNodes.Take(CONST_NODEAMOUNT).ToList();
    }

    /// <summary>
    /// Recursive method to get the nodes from the child passed in as a parameter
    /// </summary>
    /// <param name="foundNodes"></param>
    /// <param name="node"></param>
    /// <param name="typeName"></param>
    private static void GetAllNodesByType(ref List<Node> foundNodes, Node node, string typeName)
    {
     
        foreach (Node childNode in node.Children)
        {
            var child = childNode;
            if (child.NodeTypeAlias == typeName)
            {
                foundNodes.Add(child);
            }

            if (child.Children.Count > 0)
                GetAllNodesByType(ref foundNodes, child, typeName);
        }
    }

   
    public UmbracoHelper()
    {
       
    }
}

Script error when using RichTextEditor type in Razor macro – Umbraco

I came across this issue when trying to check if the RichTextEditor property had any content before rendering it to the display.

Examine the following code:

1
2
3
4
5
6
7
8
9
@{
var thisNode = Model;

}

@if (!string.IsNullOrEmpty(thisNode.MyRichContent))
{
<div class="text-widget">@thisNode.MyRichContent</div>
}

This causes a script error because Umbraco thinks MyRichContent is a object type.
To get around this, either call .ToString() on the property or do a length condition i.e thisNode.MyRichContent.ToString().Length > 0 to resolve the issue.

Passing arrays into a ASP.NET Web Api method as parameters

Here is an easy way to pass in a array of values as parameters in a ASP.NET Web Api method.

1
2
3
4
5
6
        [HttpGet()]
        public HttpResponseMessage FindByMembers([FromUri]Int32[] ids = null)
        {
           //Do stuff
            return Request.CreateResponseMessage(HttpStatusCode.OK);
        }

The Url will be http://mywebsite/api/mycontroller/findbymembers/?ids=1&ids=2&ids=3.

Happy API coding!

Unit Testing ObjectResult

I came across an interesting scenario where I wanted to unit test an imported function in the Entity Framework. The initial problem is that an imported function generates code like this:

1
2
3
4
5
public virtual ObjectResult<MyObject> GetData()
        {
   
            return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<MyObject>("GetData");
        }

The key method here is the results are returned as the ObjectResult object which 1) cannot be mocked (using RhinoMocks) because it’s sealed. There are no constructors available to create concrete instances of the object. So the best solution I can come up with is to create a new interface and create two classes that implement the interface, one for the real application and one for unit testing. From here, the unit testing class which has the interface can return anything it likes i.e. fake objects while the other class can call the function import method and return the results.

Firstly, I create the interface

1
2
3
4
5
6
public partial interface IExtendedEntities
    {
       
        IEnumerable<MyObject> GetDataWrapper();

    }

Secondly, I create the class that will use this interface for the real application.

1
2
3
4
5
6
7
public partial class MyClassReal : DbContext, IExtendedEntities
    {
        public IEnumerable<MyObject> GetDataWrapper()
        {
            return this.GetData().AsEnumerable();
        }
    }

Thirdly, create the class that uses the interface for unit testing

1
2
3
4
5
6
7
public partial class MyClassFake : DbContext, IExtendedEntities
    {
        public IEnumerable<MyObject> GetDataWrapper()
        {
            return Builder<MyObject>.CreateListOfSize(10).Build();
        }
    }

When I’m implementing the logic, I can inject (using nInject) an object of the interface IExtendedEntities and call GetDataWrapper();

When unit testing, I can create a new MyClassFake object and return a list of test data. This gives me the control to create a test case of specific test data to be put through the method that gets called to return a set of results from the Imported Function.

Tracking and Not Tracking Objects returned from SqlQuery in Entity Framework

If you don’t want objects to be tracked by the context, you can do this:

1
2
3
4
public ObjectResult<MyObject> GetData()
{
         return this.Database.SqlQuery<MyObject>("call GetData(@p0,@p1,@p2,@p3)", 1, 2, 3, 4);
}

If you want to track objects by the context, you can do this:

1
2
3
4
public ObjectResult<MyObject> GetData()
{
     return ((DbSet<MyObject>)this.MyObjects).SqlQuery("call GetData (@p0,@p1,@p2,@p3)", 1, 2, 3, 4);
}

The different is when you call SqlQuery from the objects DbSet, this will automatically track objects with the current database context.

Referenced Projects in a solution disappear on compile time Visual Studio 2010

Take the following example of a solution:

  • MyProject
  • MyProject.Core
  • MyProject.Infrasturcture

I decide to add a new console application called MyProject.Console. I reference the MyProject.Core into this console application. Everything is working fine until I try to build and run the console application. I get a error saying “Could not find the referenced Assembly.”.

I figured out that when I created the new console application in Visual Studio 2010 it defaulted to .NET 4 Client Profile as the framework and not .NET 4. This is because all my other projects were using the .NET 4 framework.

References

http://stackoverflow.com/questions/4286599/referenced-project-gets-lost-at-compile-time

Giving Enum’s descriptions

Enums are very good for giving descriptions to values especially numeric values. By default though a enum value name cannot have spaces. Look at the following which shows an example of no spaces between the first enum value name.

1
2
3
4
enum myEnum
{
   Icannothaveaspace = 1
}

A good way to solve this problem is to use the Description attribute from the System.ComponentModel namespace. We can use this attribute to give each enum value a descriptive meaning.

1
2
3
4
5
6
7
8
9
using System.ComponentModel;

 public enum MyEnum
    {
        [Description("Authorised Contact")]
        AuthorisedContact = 1,
        [Description("Assigned Contact")]
        CoauthorisedContact = 2
    }

From here we can create a extension method that uses reflection to get the description attribute for the selected enum value.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static class Extensions
    {
        /// <summary>
        /// Get the description of a enum value using the description attribute
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetEnumDescription(this Enum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());

            DescriptionAttribute[] attributes =
                (DescriptionAttribute[])fi.GetCustomAttributes(
                typeof(DescriptionAttribute),
                false);

            if (attributes != null && attributes.Length > 0)
                return attributes[0].Description;
           
            return value.ToString();
        }
    }

To use this, just call GetEnumDescription to get the description of a enum value.

1
2
3
4
5
6
7
8
9
  using Extensions; //Make sure that you use this to get the extension method
 
  public myClass
  {
      public void foo()
      {
          var myDescription = MyEnumValue.GetEnumDescription();
      }
  }