Archive for the ‘Visual Studio’ Category
When trying to serialise your model into Json you would notice the ugly way that the Microsoft JavaScriptserializer outputs dates. ie. {“d”:”\/Date(1240718400000)\/”}
This might not be a problem when you are using JQuery or Javascript, but what if your consumer is, say, an IPhone or another device? Wouldn’t you rather stick to a platform independent and recognised format?
The steps below might be a bit too drastic for your implementations, but follow them and you might also learn how to create your own ValueType and CustomJsonSerialiser all in one go!
This is what we want to accomplish. We only needed to give one converter to our CustomConverterJsonResult, but you could make this a list or even a configuration/ioc injection.
public ActionResult Index(int? id)
{
return new CustomConverterJsonResult (new UnixDateTimeConverter(), _repository.GetPerson(id));
}
Below is our custom ValueType. This allows you to do the following:
UnixDateTime uDateTime = DateTime.Now; //OR DateTime dateTime = uDateTime; //OR > < => and even casting between them
public struct UnixDateTime : IComparable
{
private static DateTime _baseDateTime = new DateTime(1970, 1, 1, 0, 0, 0);
private readonly long _epochSeconds;
public UnixDateTime(DateTime dateTime)
{
_epochSeconds = ConvertToUnixEpochSeconds(dateTime) ?? 0;
}
public UnixDateTime(long epochSeconds)
{
_epochSeconds = epochSeconds;
}
public override bool Equals(object obj)
{
if (!obj.GetType().IsAssignableFrom(typeof(UnixDateTime)))
return false;
return ((UnixDateTime)obj)._epochSeconds.Equals(_epochSeconds);
}
public bool Equals(UnixDateTime other)
{
return other._epochSeconds.Equals(_epochSeconds);
}
public override int GetHashCode()
{
return _epochSeconds.GetHashCode();
}
public int CompareTo(object obj)
{
return _epochSeconds.CompareTo(((UnixDateTime) obj)._epochSeconds);
}
public override string ToString()
{
return _epochSeconds.ToString();
}
public static bool operator >(UnixDateTime source, UnixDateTime target)
{
return source._epochSeconds > target._epochSeconds;
}
public static bool operator <(UnixDateTime source, UnixDateTime target)
{
return source._epochSeconds < target._epochSeconds;
}
public static bool operator ==(UnixDateTime source, UnixDateTime target)
{
return source._epochSeconds == target._epochSeconds;
}
public static bool operator !=(UnixDateTime source, UnixDateTime target)
{
return source._epochSeconds != target._epochSeconds;
}
public static implicit operator UnixDateTime(DateTime dateTime)
{
return new UnixDateTime(dateTime);
}
public static implicit operator UnixDateTime(long value)
{
return new UnixDateTime(value);
}
public DateTime? ToDateTime()
{
return ConvertFromUnixEpochSeconds(_epochSeconds);
}
private static long? ConvertToUnixEpochSeconds(DateTime? date)
{
if (!date.HasValue)
return null;
return (long)((DateTime)date - _baseDateTime).TotalSeconds;
}
private static DateTime? ConvertFromUnixEpochSeconds(long? seconds)
{
if (!seconds.HasValue)
return null;
return _baseDateTime.AddSeconds(seconds.Value);
}
}
We then need a CustomConverterJsonResult. The reason for this is to inject the converters needed (no support for this in the normal JsonResult).
public class CustomConverterJsonResult : JsonResult
{
private readonly JavaScriptConverter _customConverter;
public CustomConverterJsonResult(JavaScriptConverter customConverter, object data)
{
_customConverter = customConverter;
Data = data;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = !string.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
if (ContentEncoding != null)
response.ContentEncoding = ContentEncoding;
if (Data != null)
{
JavaScriptSerializer serializer = CreateJsonSerializer();
response.Write(serializer.Serialize(Data));
}
}
private JavaScriptSerializer CreateJsonSerializer()
{
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new []{_customConverter});
return serializer;
}
}
And finally… the JavascriptConverter.
public class UnixDateTimeConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
if(dictionary != null)
{
var stringValue = string.Empty + dictionary["UnixEpochSeconds"];
if(string.IsNullOrEmpty(stringValue))
return null;
return new UnixDateTime(long.Parse(stringValue));
}
return null;
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
var result = new Dictionary<string, object> { { "UnixEpochSeconds", obj.ToString() } };
return result;
}
public override IEnumerable<Type> SupportedTypes
{
get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(UnixDateTime), typeof(UnixDateTime?) })); }
}
}
This creates the following output:
{"Person":[{"Name":"John Doe","LastUpdated":[{"UnixEpochSeconds":"187653000"}]]}
If you use Agile as project management methodology then you must have heard of the ‘SOLID’ principles. Agile and SOLID goes hand in hand.
Uncle Bob has a great article on SOLID and explains each principle in detail with examples.
A summary of the principles below:
- S – Single Responsibility Pattern
A class should have one, and only one, reason to change - O – Open/Close Principle
Classes should be closed for modification, but open for extension - L – Liskov Substitution Principle
Derived classes must be substitutable for their base classes. - I – Interface Segregation Principle
Clients should not be forced to depend upon interfaces that they do not use. - D – Dependency Inversion Principle
Depend on abstractions, not concretions
You can read the full article here
A few months ago I started with BDD (Behaviour Driven Development). The first thing I noticed with most frameworks (MSpec, NBehave) is that you either need a new test runner tool (Galio) or need quite a bit of tweaking to implement the respective framework with Test-Driven.NET or Resharper’s test runner (Galio has a Resharper plugin).
This isn’t a problem in most cases, but what if you need to run these tests on Team-City or Cruise-Control? Now the complexity of the tweaking starts to become quite a different ball game!
Luckily there is an open-source tool called StoryQ which runs on NUnit and doesnt require any tweaking. The developer can run this with his usual test-runner tool and best of all, nothing has to change on the Buildserver.
Besides requiring no tweaking, StoryQ is a pretty competitive BDD tool altogether and provides loads of nifty features.
The idea is that “Tests” should be viewed as “Specs”, because this removes much of the confusion of TDD especially for beginners.
Your typical Unit test (or Spec) would look like this:
using NUnit.Framework;
using StoryQ.Framework;
namespace StoryQ.Tests.Documentation
{
[TestFixture]
public class SimpleDocumentationSpec
{
[Test]
public void WritingSpecificationsToBegin()
{
Story story = new Story("writing executable specifications");
story.AsA("business person")
.IWant("to write executable specifications")
.SoThat("a developer can implement them")
.WithScenario("Writing specifications")
.Given("That i have written everything in text")
.When("the test is run")
.Then("the test result should be pending")
.WithScenario("Writing specifications again")
.Given("That i have written everything in text")
.And("still have no asserts")
.And("and have another condition")
.When("the test is run")
.And("I am happy")
.Then("the test result should be pending")
.And("here's just some more and's");
story.Assert();
}
}
}
This would present an NUnit output result of:
SimpleDocumentationSpec.WritingSpecificationsToBegin : IgnoredPending
Story: writing executable specifications
As a business person
I want to write executable specifications
So that a developer can implement them
Scenario 1: Writing specifications
Given That i have written everything in text *Pending
When the test is run *Pending
Then the test result should be pending *Pending
Scenario 2: Writing specifications again
Given That i have written everything in text *Pending
And still have no asserts *Pending
And and have another condition *Pending
When the test is run *Pending
And I am happy *Pending
Then the test result should be pending *Pending
And here's just some more and's *Pending
You can then start adding functionality with the given scenarios like so:
using NUnit.Framework;
using StoryQ.Framework;
namespace StoryQ.Tests.Documentation
{
[TestFixture]
public class UsingNarrativesSpec
{
[Test]
public void WritingExecutablePassingSpecificationsWithNarratives()
{
Story story = new Story("writing executable specifications");
story.AsA("business person")
.IWant("to write executable specifications")
.SoThat("a developer can implement them")
.WithScenario("Writing specifications again")
.Given(Narrative.Text("I have a narrative"))
.When(() => TheTestIs_("run"))
.Then(Narrative.Exec("this will now pass", passMe));
story.Assert();
}
static void passMe()
{
Assert.IsTrue(true);
}
static void TheTestIs_(string s)
{
Assert.AreEqual(s, "run");
}
}
}
Which will give you the output of:
UsingActionsSpec.WritingExecutableSpecificationsAsActions : PassedStory: writing executable specifications
As a business person
I want to write executable specifications
So that a developer can implement them
Scenario 1: Writing specifications
Given That i have written everything in text *Pending
When the test is run *Pending
Then the test result should be pending *Pending
Scenario 2: Writing specifications again
Given That everything isnt Passed
When The test is run Passed
Then the test result should be pending *Pending
There are many more options and different ways to implement the scenarios on the StoryQ home page.
Another great feature about StoryQ is to convert your english written stories into C# tests. Yes, you read that right! It will even write the code for you! By using convention that can be tought to your “Product Owners”, you can literally copy and paste their requirements to a tool which will present the generated c# test.