- Posted by mateid on August 22, 2010
I think dynamic languages have some serious advantages when working with JSON over static languages. Things are just easier and there is a lot less friction. Static languages like C# make things a little cumbersome because you always need to specify a type. That is almost always. :) There is an alternative in C#, provided via anonymous types. You can deserialize to an anonymous type by giving the JSON deserializer and example object. (I’m using the fabulous JSON.net library for these samples) Let’s see what I mean:
public class JSON_to_anonymous_type
{
private string json = @"{ Name: ""James"" }";
[Test]
public void can_deserialize_to_simple_anonymous_type()
{
var example = new { Name = string.Empty };
var person = JsonConvert.DeserializeAnonymousType(json, example);
Assert.AreEqual("James", person.Name);
}
}
The JSON serializer will take your example anonymous object and attempt to use it as template to deserialize the JSON literal. This provides a nice alternative to defining a full blown C# class to deserialize to in some cases.
The example above is rather simplistic, usually the JSON literals we have to deal with in real life are a little more complex than this. Let’s look at something a little closer to a real life scenario. Say the person is married, and we’d like to include the spouse information with our JSON literal. We now need a nested anonymous type. The syntax can get a little crazy but here goes:
[TestFixture]
public class JSON_to_anonymous_type
{
private string json_moderate = @"{ Name: ""James"", Spouse : { Name: ""Sally""} }";
[Test]
public void can_deserialize_to_moderately_complex_anonymous_type()
{
var example = new { Name = string.Empty, Spouse = new { Name = string.Empty } };
var person = JsonConvert.DeserializeAnonymousType(json_moderate, example);
Assert.AreEqual("James", person.Name);
Assert.AreEqual("Sally", person.Spouse.Name);
}
}
Let’s try one more scenario – we would like to parse a list of children from the JSON literal. This is starting to become a little hard to read, but still better than having to define two static classes if all we need to do is say count the couple’s children.
[TestFixture]
public class JSON_to_anonymous_type
{
private string json_complex = @"{ Name: ""James"", Spouse : { Name: ""Sally""}, Children : [ { Name : ""Tom"" }, { Name : ""Sandra"" } ] }";
[Test]
public void can_deserialize_to_complex_anonymous_type()
{
var example = new { Name = string.Empty, Spouse = new { Name = string.Empty }, Children = new[] { new { Name = string.Empty }}};
var person = JsonConvert.DeserializeAnonymousType(json_complex, example);
Assert.AreEqual("James", person.Name);
Assert.AreEqual("Sally", person.Spouse.Name);
Assert.AreEqual(2, person.Children.Length);
}
}
I think that covers a couple of complex scenarios that you might encounter in real life. Deserializing to anonymous types can reduce the friction of declaring one or more static classes for simple scenarios where we may need to simply peak at a JSON literal to extract one or two properties, or perform some simple operation. If things get a little more serious than by all means declare a couple of static types to deserialize to, if only for readability's sake.
- Posted by mateid on July 20, 2010
I've broken this up into three parts:
The last feature that I want to add to my BeforeFilter is an exclusion list that specifies controller actions for which not to execute the filter methods. Assume that you have Edit/Create/Display views; the Edit and Create views could – for example - require additional data to render drop down lists. If we populate this data with a before filter we should have the ability to exclude the Display view from the filter where this additional data is not necessary.
Attribute parameters can only be constant expressions so we have that restriction to contend with. The usage should be friendly and easy to use – a little syntactic sugar doesn’t hurt. I was contemplating something similar to the snippet below:
[BeforeFilter("Initialize", Except = new [] {"Index", "Details"} )]
public class ItemController : Controller
{
...
}
This looks pretty straight forward and the implementation should not be too difficult.
How are we going to know the action that is about to be executed? The OnActionExecuting method is passed an ActionExecutingContext. It contains an ActionDescriptor object that has various interesting properties including the ActionName.
Naturally we begin with a test. Our test setup will changes slightly so that we can mock the ActionDescriptor and create the context with the mocked out version. The test will include a setup for the ActionName property and verify that the filter methods are not invoked for the actions specified in our list. The setup and the test code is below:
[SetUp]
public void Before()
{
controller = new Mock<TestController>();
descriptor = new Mock<ActionDescriptor>();
context = new ActionExecutingContext
{
Controller = controller.Object,
ActionDescriptor = descriptor.Object
};
}
[Test]
public void should_not_call_specified_controller_method_given_an_action_is_an_exception()
{
descriptor.SetupGet(x => x.ActionName).Returns("Display");
var attribute = new BeforeFilterAttribute("initialize", "logaction")
{
Except = new [] {"Display"}
};
attribute.OnActionExecuting(context);
controller.Verify(x => x.initialize(), Times.Never());
controller.Verify(x => x.logaction(), Times.Never());
}
The implementation for OnActionExecuting changes very little, we simply check if the ActionName is on the exception list before invoking the filter methods:
if(!Except.Contains(filterContext.ActionDescriptor.ActionName))
controllerMethod.Invoke((object)controller, new object[] { });
And that’s that, we now have a fairly complete BeforeFilterAttribute we can use to keep controllers clean.
- Posted by mateid on July 16, 2010
I've broken this up into three parts:
I’ve decided to add more features to the before filter I’ve build in the previous post. I need a way to specify a few methods I’d like to execute before the controller actions. I can do that now by specifying a number of BeforeFilter attributes but that looks a little silly. What I want is the ability to do something like this:
[BeforeFilter("InitializeCategories","InitializeProvinces")]
This should be fairly easy to accomplish. We should probably start with a test. I’ve added a logaction method to the test controller so we can assert it was called. Here is the test:
[Test]
public void should_call_all_specified_controller_methods_given_they_exist()
{
controller.Setup(x => x.initialize());
controller.Setup(x => x.logaction());
var attribute = new BeforeFilterAttribute("initialize", "logaction");
attribute.OnActionExecuting(context);
controller.VerifyAll();
}
To make this pass we change our implementation slightly. The method names now become a collection we need to iterate over and invoke the method on the controller if found; if not, we throw and exception as before. I've changed the exception type to an InvalidOperationException.
public BeforeFilterAttribute(string methodName) : this(new[] { methodName })
{
}
public BeforeFilterAttribute(params string[] methods)
{
this.methods = new List<string>(methods);
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var controller = filterContext.Controller;
foreach (var method in methods)
{
...
}
base.OnActionExecuting(filterContext);
}
This makes the test pass and now we have a BeforeFilter that’s a little more useful and friendly.
I would like to add one more feature to my BeforeFilter and that is an exception list. In other words, I would like a way to specify controller actions for which to NOT execute the methods. That way I have the ability to apply the BeforeFilter to the controller itself instead if the individual action and still retained fine grained control over the before methods that execute for a given action. I will leave that for a separate post.
- Posted by mateid on July 13, 2010
I've broken this up into three parts:
MVC2 has a nice feature called filters. They let you keep your controllers clean and factor out common code. This looks like it works particularly well for cross cutting concerns like security, logging, caching, etc. I’ve used in in one instance when I needed to populate the view bag with some common reference data used on the view to render a drop down list. With some lines omitted for brevity code for the controller looked something like this:
[HandleError]
public class ItemController : Controller
{
public ActionResult Edit()
{
ViewData["categories"] = repository.FindAll();
return View();
}
public ActionResult Create()
{
ViewData["categories"] = repository.FindAll();
return View();
}
}
We can quickly extract a method for the common code and call it InitializeCategories:
private void InitializeCategories()
{
ViewData["categories"] = repository.FindAll();
}
So you do this for a couple of controllers and you start to wonder if there is a more generic solution to this. We could try to extract a base class but that may not be suitable to all controllers or it could lead to some unpleasant inheritance hierarchy. This is when action filters come to mind. What if we could declaratively specify some method to execute before each controller action? We would like to end up with code similar to this:
[HandleError]
public class ItemController : Controller
{
[BeforeFilter("InitializeCategories")]
public ActionResult Edit()
{
return View();
}
[BeforeFilter("InitializeCategories")]
public ActionResult Create()
{
return View();
}
public void InitializeCategories()
{
ViewData["categories"] = repository.FindAll();
}
}
Writing an ActionFilter to handle this is relatively easy. There are a few types of filters available already, but for our purpose we can simply subclass ActionFilterAttribute and override the OnActionExecuting method. This method is called before out controller action executes. The method will be passed an ActionExecutingContext parameter which contains a variety of interesting information about the execution context including the controller instance. We can start by writing a test for our attribute. Lets say that we want to assert that a method on the controller is called if it exists. We make that pass and we write a second tests that asserts we throw a meaningful exception if the specified method does not exists. The tests looks like this:
[TestFixture]
public class A_BeforeFilterAttribute
{
private Mock<TestController> controller;
private ActionExecutingContext filterContext;
[SetUp]
public void Before()
{
controller = new Mock<TestController>();
filterContext = new ActionExecutingContext { Controller = controller.Object };
}
[Test]
public void should_call_the_specified_controller_method_given_it_exists()
{
controller.Setup(x => x.initialize());
var attribute = new BeforeFilterAttribute("initialize");
attribute.OnActionExecuting(filterContext);
controller.VerifyAll();
}
[Test]
public void should_throw_invalid_method_exception_given_it_doesnt_exist()
{
var attribute = new BeforeFilterAttribute("nosuchmethod");
Assert.Throws<Exception>(() => attribute.OnActionExecuting(filterContext));
controller.VerifyAll();
}
public class TestController : Controller
{
public virtual void initialize()
{
}
}
}
I created a test controller so that I can set up an expectation that its method will be called. The mocking framework I used here is Moq. The implementation that makes the tests pass is below:
public class BeforeFilterAttribute : ActionFilterAttribute
{
private readonly string methodName;
public BeforeFilterAttribute(string methodName)
{
this.methodName = methodName;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var controller = filterContext.Controller;
var method = controller.GetType().GetMethods().Where(x => x.Name.Equals(methodName)).FirstOrDefault();
if (method == null)
{
throw new Exception(string.Format("The method {0} could not be found on {1}.", methodName, controller.GetType().FullName));
}
method.Invoke((object) controller, new object[] {});
base.OnActionExecuting(filterContext);
}
}
Kind of a lengthy posts for such short code. This can be expanded a little so that we can specify a list of methods to be called, but I haven’t needed that yet and it’s all about providing value to the customer. That could maybe look something like this:
[BeforeFilter("InitializeCategories","InitializeProvinces")]
public ActionResult Edit()
{
return View();
}
We can accomplish this by creating an overloaded constructor for the BeforeFilterAttribute:
public BeforeFilterAttribute(params string[] methodName)
{
}
That’s it for now folks, if you decide to implement the overload please share!
- Posted by mateid on December 9, 2008
I ran into an interesting tidbit the other day: a couple of structs implementing and interface. That just seems like asking for trouble to me, structs are value types and interfaces are reference types. Something tells me there could be some subtle issues associated with this. It’s pretty clear that boxing will occur when you pass a value type as a reference type, but I’m sure that’s not the only issue we’ll see here. Time for a quick study.
Here’s the interface we’ll be implementing:
1: public interface IPlayer
2: {
3: string Name { get; set; }
4: string Club { get; set; }
5: int Age { get; set; }
6:
7: void Transfer(string newClub);
8: }
And here’s a real simple implementation for it:
1: public struct Player : IPlayer
2: {
3: public string Name { get; set; }
4:
5: private string club;
6: public string Club
7: {
8: get { return club; }
9: set { club = value; }
10: }
11:
12: public int Age { get; set; }
13:
14: public void Transfer(string newClub)
15: {
16: club = newClub;
17: }
18: }
So we’re just going to go ahead and create an instance of a player. Once we have that we’ll print the club he’s currently playing for and we’ll transfer him to a different club (and make a lot of money in the process).
1: Player player = new Player {Age = 20, Club = "AC Milan", Name = "Marco van Basten"};
2: player.Transfer("Ajax Amsterdam");
3:
4: Console.WriteLine(player.Club);
It’s not too hard to guess this will output “Ajax Amsterdam”. Now what happens if we transfer Marco back to AC Milan, but using the IPlayer interface now? Let’s see.
1: IPlayer copy = player;
2: copy.Transfer("AC Milan");
3:
4: Console.WriteLine(player.Club);
Looks like Marco still plays for Amsterdam even though we just transferred him to Milan. Tough! Well, what happened? The implicit cast created a temporary object we updated and threw away. Not good. Now if we changed the Player struct to a class it would all work as expected.
I would stay away from structs implementing interfaces, just make it a class instead.