ToDebugString() – give me some debug info about my object, e.g. Request.Url

by Oliver Fri, September 16 2011 20:06

Lately, I was having trouble debugging certain parts of my code in Visual Studio, and all I wanted to know was the value of some variable at some point in time. Well, I’d use some logging if I could just get at that value easily. But for some objects I don’t really know what I’m looking for or where I should be looking for it. So just give me the values of all the members of that object, will ya? And could you recurse that? But no deeper than 3 levels, alright? Or let’s say… 5?

public static string ToDebugString(this object obj, int maxdepth, int depth=0)
{
    if (obj == null)
        return "null";
 
    if (obj is IConvertible)
        return obj.ToString();
 
    if (depth >= maxdepth)
        return "...";
 
    var sb = new StringBuilder();
 
    if (depth > 0)
        sb.AppendLine();
 
    foreach (var propertyInfo in obj.GetType().GetProperties(BindingFlags.Public|BindingFlags.Instance))
    {
        sb.Append(new string(' ', 2*depth)).Append(propertyInfo.Name).Append(": ");
        try
        {
            var value = propertyInfo.GetValue(obj, new object[0]);
            sb.AppendLine(ToDebugString(value, maxdepth, depth + 1));
        }
        catch (Exception ex)
        {
            sb.AppendLine(string.Format("[{0}]", ex.Message));
        }
    }
 
    // remove newline from end of string
    var newLine = Environment.NewLine;
    if (sb.Length >= newLine.Length)
        sb.Replace(newLine, "", sb.Length - newLine.Length, newLine.Length);
 
    return sb.ToString();
}
With this little helper I can now simply call anyobject.ToDebugString(4 /* maxdepth */) and I get a nicely formatted debug view of that object; e.g. Request.Url.ToDebugString(3) gives me:
AbsolutePath: /logg.aspx
AbsoluteUri: http://localhost:55235/logg.aspx
Authority: localhost:55235
Host: localhost
HostNameType: Dns
IsDefaultPort: False
IsFile: False
IsLoopback: True
IsUnc: False
LocalPath: /logg.aspx
PathAndQuery: /logg.aspx
Port: 55235
Query:
Fragment:
Scheme: http
OriginalString: http://localhost:55235/logg.aspx
DnsSafeHost: localhost
IsAbsoluteUri: True
Segments:
Length: 2
LongLength: 2
Rank: 1
SyncRoot:
Length: 2
LongLength: 2
Rank: 1
SyncRoot: ...
IsReadOnly: False
IsFixedSize: True
IsSynchronized: False
IsReadOnly: False
IsFixedSize: True
IsSynchronized: False
UserEscaped: False
UserInfo:

Nice Smile

Right now this method chokes on indexed properties but once I’ll need it I’ll go and look for a way to include them. It also chokes any exceptions on the way to just get the job done.

Happy coding!

Tags:

.NET | C# | Debugging | Software development | Tips & Tricks | Visual Studio | developer

MSBuild and Visual Studio 2010 generate different DLLs

by Oliver Tue, September 06 2011 22:18

Recently, we encountered a quite surprising behavior of MSBuild – the continuous integration build of our new collaborative Todo Management app (we hope to go into beta soon!) would produce a broken version whereas the local build with VS2010 was all smooth and well. Our admin and tester already posted about this problem over at his blog: MSBuild does not build like Visual Studio 2010.

The exception message finally led me down the right path:

Server Error in '/' Application.

No constructors on type 'Teamaton.TodoCore.Repositories.TodoRepositoryJson' can be found with 'Public binding flags'.

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: Autofac.Core.DependencyResolutionException: No constructors on type 'Teamaton.TodoCore.Repositories.TodoRepositoryJson' can be found with 'Public binding flags'.

The TodoRepositoryJson is a type we used at the very beginning of our development to quickly get started using a JSON document as data store. Later we switched to SQLite, so now we have another implementation: TodoRepositoryDb. Both implement the same interface ITodoRepository.

Turns out, the Autofac type registering code was the culprit:

   1: var builder = new ContainerBuilder();
   2: builder.RegisterAssemblyTypes(typeof (Todo).Assembly)
   3:     .Where(t => t.Name.Contains("Repository"))
   4:     .AsImplementedInterfaces()
   5:     .InstancePerLifetimeScope();

What worked with Visual Studio, didn’t work with MSBuild: obviously – well, now it is – both ITodoRepository implementations were registered with Autofac, and while Autofac’s assembly scanning delivered them in the order we assumed from the DLL built with VS  – first, TodoRepositoryJson, and second, TodoRepositoryDb, thus overriding the first registration – MSBuild seems to build a DLL which returns the inverse order! Very strange.

Honestly, I’m not familiar with the anatomy of DLLs and surprised by this result. But it’s the only explanation I’ve found so far.

Well, the solution to the problem is, of course, to care more about what we register with Autofac and in which order.

Happy coding,

Oliver

Tags: , , ,

Build | C# | Software development | Visual Studio

JSON Import In .NET

by Anton Fri, July 22 2011 13:37

Bantam Is Quitting Services

We as teamaton were using bantam for all of our todos. At the beginning of this year bantam was bought by ConstantContact, and they announced that bantam will cease services as of July 1. Since we are developing our own todo management tool (see our blog), we decided to push the development and use it instead of bantam.

Of course we wanted to take all of our todos with us. We used bantams export feature which gave us a JSON-file with all our tasks (closed and open ones). So I took on the task to write an JSON import feature into our tool.

Json.NET

After a bit of researching, I found that the library Json.NET would suit our import needs perfectly. Applying the deserialization was pretty straightforward – the documentation helped a lot. Here is the code from the Import controller:

[HttpPost]
public ActionResult Import(HttpPostedFileBase file)
{
    var todos = new List<Todo>();
    if (file != null && file.ContentLength > 0)
    {
        var streamReader = new StreamReader(file.InputStream);
        string text = streamReader.ReadToEnd();
        streamReader.Close();
 
        var bantamTodos = JsonConvert.DeserializeObject<IList<BantamTodo>>(text) as List<BantamTodo>;
        todos = bantamTodos.Select(bantamTodo => bantamTodo.ConvertToTodo()).ToList();
        _todoRepository.SaveImport(todos);
    }
 
    return RedirectToAction("List");
}

It just opens the file, extracts the content as a string, deserializes the string into a list of bantam todos, and then converts these bantam todos into our “normal” todos.

Indirection Via BantamTodo-Class

As you can see, I did not convert the JSON directly into our Todo-class. You can use attributes and the converter class to deserialize JSON into a class of your liking. There are two reasons, why I did not choose to do so: I did not want to load the Todo-class with attributes and converters, and I thought it would be easier to introduce a middle class (BantamTodo), which poses as a container and converter.

I used a nice tool, to take a good look into the original JSON-file: JSON Viewer.

JSON Viewer

With the information about the structure of the JSON file I started implementing via the TDD pattern. Here is my test class, which tests the deserialization of the the bantam todos and the conversion from the class BantamTodo to Todo:

[Test]
public void Should_Import_BantamToDo_FromJson()
{
    var jsonToDo = ArrangeTaskAsJson();
    var bantamToDo = JsonConvert.DeserializeObject<BantamTodo>(jsonToDo);
 
    bantamToDo.Categoy.Should().Be.EqualTo("Organisation");
    bantamToDo.Complete.Should().Be.EqualTo(true);
    bantamToDo.Created_At.Should().Be.EqualTo(new DateTime(2011, 6, 30, 0, 41, 57));
    bantamToDo.Due.Should().Be.EqualTo(new DateTime(2011, 7, 1));
    bantamToDo.Author.Name.Should().Be.EqualTo("Anton");
    bantamToDo.Assigned_To.Name.Should().Be.EqualTo("Oliver");
    bantamToDo.Related_To[0].Name.Should().Be.EqualTo("ToDo-Management Tool");
    bantamToDo.Name.Should().Be.EqualTo("Entwicklung nach Gebieten Personen zuordnen - Verantwortliche, Blogs, etc.");
    bantamToDo.Description.Should().Be.EqualTo("some good description");
    bantamToDo.Flagged.Should().Be.EqualTo(true);
}
 
[Test]
public void Should_Convert_BantamToDo_ToTodo()
{
    var jsonToDo = ArrangeTaskAsJson();
    var bantamToDo = JsonConvert.DeserializeObject<BantamTodo>(jsonToDo);
    var todo = bantamToDo.ConvertToTodo();
 
    todo.Status.Should().Be.EqualTo(bantamToDo.Complete ? Status.Closed : Status.Open);
    todo.Description.Should().Contain(bantamToDo.Name);
    todo.Description.Should().Contain(bantamToDo.Description);
    todo.Tags.Select(t => t.Name).Should().Contain(bantamToDo.Categoy);
    foreach (var bantamProject in bantamToDo.Related_To)
        todo.Tags.Select(t => t.Name).Should().Contain(bantamProject.Name);
    todo.DateCreated.Should().Be.EqualTo(bantamToDo.Created_At);
    todo.DateCompleted.Value.Date.Should().Be.EqualTo(bantamToDo.Due);
    todo.DateDue.Should().Be.EqualTo(bantamToDo.Due);
    todo.Creator.Name.Should().Be.EqualTo(bantamToDo.Author.Name);
    todo.Assignee.Name.Should().Be.EqualTo(bantamToDo.Assigned_To.Name);
    todo.Priority.Value.Should().Be.EqualTo(bantamToDo.Flagged ? 2 : 0);
}

The implementation was pretty straightforward. Since it was my first time working with MVC, and also my first time working with JSON, it took me some time. All in all – research, export and meetings included – it took me about 12 hours.

If you have any suggestions as to improvement I would appreciate them. If you are trying to import JSON into .NET yourself, I hope that this article helps.

Tags:

.NET | C# | Software development | Test Driven Development (TDD) | JSON

Code evolution + LINQ

by Oliver Tue, June 28 2011 01:27

Three year old code:

   1: protected string CpeBehaviorIds() 
   2: { 
   3:     var cpeIds = ""; 
   4:  
   5:     var helpItems = GetHelpItems(divGlobal); 
   6:  
   7:     foreach (var helpItem in helpItems) 
   8:         cpeIds += helpItem.CollapsiblePanelBehaviorID + ','; 
   9:  
  10:     // remove comma at end 
  11:     if (cpeIds.Length > 0) 
  12:         cpeIds = cpeIds.Remove(cpeIds.Length - 1); 
  13:  
  14:     return cpeIds; 
  15: } 
  16:  
  17: protected string CpeExpandIds() 
  18: { 
  19:     var cpeIds = ""; 
  20:  
  21:     var helpItems = GetHelpItems(divGlobal); 
  22:  
  23:     foreach (var helpItem in helpItems) 
  24:         cpeIds += helpItem.CollapsiblePanelExpandID + ','; 
  25:  
  26:     // remove comma at end 
  27:     if (cpeIds.Length > 0) 
  28:         cpeIds = cpeIds.Remove(cpeIds.Length - 1); 
  29:  
  30:     return cpeIds; 
  31: } 
  32:  
  33: protected static List<HelpItem> GetHelpItems(Control control) 
  34: { 
  35:     var idList = new List<HelpItem>(); 
  36:  
  37:     if (control is HelpItem) 
  38:         idList.Add(control as HelpItem); 
  39:     else 
  40:         foreach (Control child in control.Controls) 
  41:             idList.AddRange(GetHelpItems(child)); 
  42:  
  43:     return idList; 
  44: }
New code:
   1: protected string CpeBehaviorIds() 
   2: { 
   3:     return divGlobal.Controls<HelpItem>().Select(h => h.CollapsiblePanelBehaviorID).JoinNonEmpty(","); 
   4: } 
   5:  
   6: protected string CpeExpandIds() 
   7: { 
   8:     return divGlobal.Controls<HelpItem>().Select(h => h.CollapsiblePanelExpandID).JoinNonEmpty(","); 
   9: }
  10:  
  11: public static string JoinNonEmpty(this IEnumerable<string> values, string separator)
  12: {
  13:     return String.Join(separator, values.Where(s => !string.IsNullOrEmpty(s)).ToArray());
  14: }

LINQ – we love you!

Oliver

P.S. Controls<Type>() is another extension method defined like this:

   1: /// <summary>
   2: /// Returns all controls of the given Type that are found inside this control.
   3: /// Searches recursively.
   4: /// </summary>
   5: public static IEnumerable<T> Controls<T>(this Control control) where T : Control
   6: {
   7:     var controls = control.Controls;
   8:  
   9:     if (controls.Count == 0) return new List<T>(0);
  10:  
  11:     var newColl = new HashedSet<T>();
  12:     foreach (Control child in controls)
  13:     {
  14:         if (child is T)
  15:             newColl.Add((T) child);
  16:  
  17:         var childColl = child.Controls<T>();
  18:         foreach (T ctrl in childColl)
  19:             newColl.Add(ctrl);
  20:     }
  21:  
  22:     return newColl;
  23: }

Tags:

C# | Software development | developer

Sorting some result list by the ids of another list

by Oliver Fri, June 24 2011 21:47

Imagine we have the following list of ids of some kind of objects and a mapping of some of the ids to some values (also int’s here):

   1: var ids = new List<int> { 6, 2, 5, 3, 7 };
   2: var valueMap = new List<int[]> { new[] { 5, 15 }, new[] { 2, 12 }, new[] { 3, 13 } };

Now, if we want to return the results a.k.a. the valueMap in the same order we have the ids, we can use the LINQ extension method .Join()like this:

   1: var joined = ids.Join(valueMap, id => id, arr => arr[0], (id, arr) => string.Format("id: {0} - value: {1}",  id, arr[1])); 

Really convenient! Let’s look at the output:

   1: Console.WriteLine(string.Join("\r\n", joined)); 
   2:  
   3: // Prints:
   4: // id: 2 - value: 12
   5: // id: 5 - value: 15
   6: // id: 3 - value: 13

By the way, I use FastSharp to write and test this kind of small code snippets Winking smile

Happy Coding,

Oliver

Tags:

.NET | C# | Software development | Tips & Tricks

Mocking revisited – mocking a method and passing a parameter using FakeItEasy and Moq

by Oliver Tue, June 21 2011 23:35

Finally, I’ve started mocking things in our kind of legacy project while building new functionality. Now, I wanted to replace some DAL service with a mock that would would just serve me some results instead of ramping up NHibernate, going to the DB and assembling all the entities for this test. At first I tried to use FakeItEasy as I liked the syntax more than that of Moq:

  1: var _geoObjectServiceMock = A.Fake<IGeoObjectService>();
  2: var results = new List<int>{ 1, 2, 3, ... };
  3: A.CallTo(() => _geoObjectServiceMock.GetSearchResultIds(A<GeoObjectSearchDesc>.Ignored))
  4:     .Returns(results);

This was easy. Just fix up the result you want the method to return and set it up. Well – I needed more. I needed to return my results list dependent on the GeoObjectSearchDesc parameter passed to the method. In short: I did not find a way to do this. I searched Google and Stackoverflow but to no avail. What I did find was an example using Moq showing exactly what I wanted to do. From Moq’s QuickStart wiki page:

  1: // access invocation arguments when returning a value
  2: mock.Setup(x => x.DoSomething(It.IsAny<string>()))
  3:     .Returns((string s) => s.ToLower());
  4: // Multiple parameters overloads available

So I quickly installed Moq using NuGet, e.g. from the Package Manager Console:

  1: Install-Package Moq -project Tests

Now I have something like this which is exactly what I was looking to do:

  1: var _geoObjectServiceMock = new Mock<IGeoObjectService>();
  2: var results = new List<int>{ 1, 2, 3, ... };
  3: _geoObjectServiceMock.Setup(svc => svc.GetSearchResultIds(It.IsAny<GeoObjectSearchDesc>()))
  4:                      .Returns<GeoObjectSearchDesc>(gosd => results.Take(gosd.PageSize).ToList());

That’s what I expected – to get control over the method parameter(s) inside the mock. Great! Thank you Moq.

Happy Coding,

Oliver

Tags:

.NET | C# | Test Driven Development (TDD)

Mocking for the first time – a short overview of a few .NET mocking frameworks

by Oliver Fri, March 25 2011 15:50

In my recent post Testing: trying to get it right I mentioned that a lot of our tests are of the dirty hybrid kind, somewhere between real Unit tests and real Integration tests. Focusing on the Unit test part, we’re looking into using a mocking framework right now to change the way we write tests – most of all to decouple the different components that we use in the application under test.

Wanting to use the fresh and hype NuGet package manager to install the mocking frameworks, I chose among the ones that were both available there and also looked promising:

Really, it could not have been easier to get all these libraries into the project than using NuGet!

Sample code

So I went ahead and wrote a short and simple test just to get a feel of the syntax they offer. At first I wanted to mock a simple Repository using its interface. Here is what I ended up with:

  • Telerik JustMock: using syntax from their quick start manual
        1: public void MockRepositoryInterfaceTest()
      
        2: {
      
        3: 	// Arrange
      
        4: 	var repo = Mock.Create<ITodoRepository>();
      
        5: 	Mock.Arrange(() => repo.Todos)
      
        6: 		.Returns(new List<Todo> {new Todo {Description = "my todo"}}.AsQueryable);
      
        7: 
      
        8: 	// Act + Assert
      
        9: 	repo.Todos.ToList().Count.Should().Be.EqualTo(1);
      
       10: }
  • Moq: just visit the project homepage
        1: public void MockRepositoryInterfaceTest()
      
        2: {
      
        3: 	// Arrange
      
        4: 	var repo = new Mock<ITodoRepository>();
      
        5: 	repo.SetupGet(rep => rep.Todos)
      
        6: 		.Returns(() => new List<Todo> {new Todo {Description = "my todo"}}.AsQueryable());
      
        7: 
      
        8: 	// Act + Assert
      
        9: 	repo.Object.Todos.ToList().Count.Should().Be.EqualTo(1);
      
       10: }
  • FakeItEasy: just visit the project homepage
        1: public void MockRepositoryInterfaceTest()
      
        2: {
      
        3: 	// Arrange
      
        4: 	var repo = A.Fake<ITodoRepository>();
      
        5: 	A.CallTo(() => repo.Todos)
      
        6: 		.Returns(new List<Todo> {new Todo {Description = "my todo"}}.AsQueryable());
      
        7: 
      
        8: 	// Act + Assert
      
        9: 	repo.Todos.ToList().Count.Should().Be.EqualTo(1);
      
       10: }

    In the first test-ride FakeItEasy and JustMock look pretty much identical, whereas the syntax Moq offers is a bit awkward with the SetupGet() method name and the need to call repo.Object to get the instance. I hope to examinate further differences in use as the project moves on.

    Mocking concrete classes

    Since we’re working with a large application that still has a lot of services and classes not implementing any interface I also wanted to make sure we’ll be able to mock concrete types. Well, this didn’t go so well:

    different-mocking-frameworks-all-fail-on-concrete-classes

    JustMock and FakeItEasy simply returned an instance of the concrete class I gave them, Moq complains that it can’t override the Todos member. So I added the virtual modifier to it and the test is now green. Still, I got the impression that I was trying to do something that I shouldn’t. The following blog post motivates further not to mock concrete classes: Test Smell: Mocking concrete classes. So I guess introducing interfaces as a kind of contract between classes is the way to go, but in the meantime and where we can’t avoid mocking concrete types we’ll be left using Moq.

  • That’s it for now, happy coding!

    Oliver

    C# access modifiers: protected internal vs. protected vs. internal

    by Oliver Thu, January 27 2011 22:50

    As I just read here on msdn, the modifiers protected and internal are orthogonal as in that they can be specified in all combinations and are combined with a logical OR. This means:

    • protected members are accessible from inheriting classes
    • internal members are accessible from classes within the same assembly
    • protected internal classes are accessible from inheriting classes and all classes from the same assembly

    The last option is maybe the most unclear – but just imagine a subclass defined in a different assembly and you’ll see what this might be good for :-)

    Happy Coding, Oliver

    Tags:

    .NET | C#