OdeToCode IC Logo

Prototypes and Inheritance in JavaScript

Thursday, July 22, 2010 by K. Scott Allen

Forget everything you know about object-oriented programming. Instead, I want you to think about race cars. Yes – race cars.

That's the intro for my latest article @ Script Junkie - Prototypes and Inheritance in JavaScript. I hope you enjoy reading it.

 

Delegated Model Binding

Sunday, July 18, 2010 by K. Scott Allen

In the last post we saw the recursive nature of the default model binder in MVC. Now, let's look at the following class:

public class User
{
    public string Name { get; set; }
    public string Email { get; set; }
    
    /* 
     * bunch more simple stuff 
     */

    public AuthorizationClaims AdditionalClaims { get; set; }
}

Imagine AdditionalClaims are something that the default model binder will not understand. For whatever reason, you'll need to use a custom model binder to pull data from the request environment and into the claims property. If you don't know how the default model binder works, you might think "because the model binder doesn't understand part of this model, I'll have to write a model binder for the whole model", and do this:

public class UserModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext,
                            ModelBindingContext bindingContext)
    {
        // stuff ...
    }
}

And register the class during application startup:

ModelBinders.Binders.Add(typeof (User), new UserModelBinder());

This probably isn't the approach you want to use for a couple reasons:

1) The model binder is not only responsible for claims, but also for all the other properties (name, email, etc).

2) You've only solved the problem of binding claims in a single model type. That's fine if AuthorizationClaims only appears in a single model type, but maybe it doesn't (and maybe it won't in the future).

Remember the default model binder delegates the work of binding each property. Knowing how the default model binder works, it's easier to focus in on just the piece you need to customize.

public class AuthorizationClaimsModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext,
                            ModelBindingContext bindingContext)
    {
        /* implementation details */
    }
}

And:

ModelBinders.Binders.Add(typeof(AuthorizationClaims),
                new AuthorizationClaimsModelBinder());

Now the claims binding will work anywhere - even when claims are nested in another type, and it doesn't require code changes in the future.

However ...

Isn't there always a catch?

In order for the default model binder to delegate the work of creating an AuthorizationClaims it first has to think there is an AuthorizationClaims available. It does this using "value providers" and "prefixes". We'll talk about these concepts and how to implement the model binder in a future post (but not right away - too much model binding at once is boor - riiiing).

Recursive Model Binding

Thursday, July 15, 2010 by K. Scott Allen

In the last post we saw how a model binder has to show up for work even when all we need is a simple int parameter on an HTTP GET request.

Now it's time for a pop quiz!

Given this route definition:

routes.MapRoute(
    "SearchRoute",
    "Home/Browse/{category}",
    new {controller = "Home", action = "Browse"});

And this class definition:

public class BrowseRequest 
{
    public int StartYear { get; set; }
    public string Manufacturer { get; set; }
    public string Category { get; set; }
    public string Controller { get; set; }
    public string Action { get; set; } 
}

And given this request arrives as a GET:

http://server/home/browse/appliances?startyear=2009&manufacturer=GE

.. at this method of HomeController:

public ActionResult Browse(BrowseRequest search)
{
    // ...
    return View();
}

Then what will BrowseRequest look like?

Answer:

The DefaultModelBinder will create a new BrowseRequest object and populate it with the following values:

  • Action = "browse" (from route data)
  • Category = "appliances" (from route data)
  • Controller = "home" (from route data)
  • Manufacturer = "GE" (from the query string)
  • StartYear = 2009 (from the query string)

The default model binder is adept at building up entire objects using information it finds in the request environment. Binding removes all the clumsy code you would otherwise write to find and shuffle data around. The default model binder can even build up collections and complex object graphs

It's Recursive (Sort Of)

When the MVC runtime realizes it needs a BrowseRequest object, it looks for a model binder for the BrowseRequest type (a topic for a future post) and invokes the binder's BindModel method (it's part of the IModelBinder contract that every model binder must implement).

If the binder in question is the DefaultModelBinder, then it doesn't just jump in and start setting properties in one operation. The default model binder's brain works something like this*:

Default Model Binder: "Hmm, this looks like a complex thing with lots of properties. I'm going to loop through each property and tell some other model binder to do this work for me. Let's start with this Manufacturer property - it's of type string. Hey! MVC! Give me the model binder for string types!"

MVC Runtime: "Here is the model binder. Thank you for asking, please come again." 

Default Model Binder: "I will setup a new binding context for this binder and call BindModel --"

     Default Model Binder: "Hey - I'm binding a string named Manufacturer. Found it! Done! Pop!"

Default Model Binder: " -- and now that manufacturer is done, let me look at this StartYear of type int. Hey! MVC! Give me the model binder for int types!"

MVC Runtime: "Here is the model binder. Thank you for asking, please come again."

And this conversation continues until the binder visits all the properties. When you ask the model binder to bind a simple primitive type like string and int - it will do so, but anything more complex** and the binder effectively breaks up the big job into a series of smaller jobs. It turns out that most of the time the default model binder is recursively calling itself to do these smaller binding jobs, but the flow doesn't have to run this way.

Why Is This Important?

If you want to plug in a custom model binder this recursive behavior is important to understand. You can verify that binding a BrowseRequest object takes 6 calls to BindModel using a debugger and the following code:

public class MyModelBinder : DefaultModelBinder
{
    public override object BindModel(
        ControllerContext controllerContext, 
        ModelBindingContext bindingContext)
    {
        // set a break point inside this method
        return base.BindModel(controllerContext, bindingContext);
    }
}

And put the following into Application_Start:

ModelBinders.Binders.DefaultBinder = new MyModelBinder();

However, the default model binder doesn't know it's calling itself. It's just trying to delegate work to whatever model binder is registered for a given type. If you register a model binder for typeof(string) or typeof(int), the default model binder in this scenario would be calling into those other model binders.

In a future post we'll exploit this delegating behavior to simplify a binding scenario.

* There are a few simplifications made in this depiction. It's the essence that counts.

** There are always special cases - collections are an example of an exception to the this rule.

Hard Working Model Binder

Wednesday, July 14, 2010 by K. Scott Allen

The job of a model binder in ASP.NET MVC is to take pieces of data in an HTTP request and place them into objects. It's easy to sense a model binder at work when you use one of the Update API's.

bool success = TryUpdateModel(movie); // here

// .. or ...

try
{
    UpdateModel(movie); // here, too!
}
catch (InvalidOperationException ex)
{
    // ... model binding errors ...
}

If the first line of code with TryUpdateModel could speak, it would say something like "Here is a movie. I want you to look around and find information to populate the movie. Go look in the posted form values, in the routing data picked out of the URL, and in the query string to see if you can find something called "Title". If you do find a title, move the value into the "Title" property of the movie. Do the same for "TagLine", "Summary", and the rest of my movie properties, and do it fast!".

Ok, it doesn't really say "do it fast", but we'd like to think it will be fast.

Conceptually, a model binder is a match maker who pairs things together based on their name.

Binding - Not Just For Models

unhappy by gagilas.The "model" part of the model binding name does lead to some confusion.

Don't tell the model objects this because they might get upset - but models aren't special.

A model binder can work against any type of object. The object doesn't have to be an official "model" or even complex type. In fact, a model binder might be at work in more places than you suspect.

Take, for example, the following HTTP GET request.

http://server/home/index/3

or

http://server/home/index?id=3

Assuming you have the default routing rule in place, a model binder runs to execute this action:

public ActionResult Index(int id)
{
    // ...
}

When an action is invoked, the action invoker sees the id parameter and asks a model binder to bind the parameter. Unless you've configured a different model binder, then it is the MVC DefaultModelBinder that will locate the value for "id". The model binder will find this value in the routing data (if the URL used is index/3), or it will find it in the query string (if the URL is index?id=3).

In summary, model binding isn't just for updating model objects in an HTTP POST. There is a model binder at work for simple parameter types like integers during mundane HTTP GET requests. We'll need to remember this fact when we look at more characteristics of these hard-working, recursive MVC denizens in a future post.

Ruby: initialize and super

Tuesday, July 13, 2010 by K. Scott Allen

One of the reasons to like Ruby if you come from a C#/C++/Java background is how certain constructs will tend to "just make sense" even though Ruby will throw in a twist here and there.

Consider the case of inheritance and initialize methods.

class Employee < Person
end

emp = Employee.new

Let's say you run the code and get an error on the line of code creating the Employee object : "wrong number of arguments". Seems odd, because Employee doesn't look like it needs an argument for creation, but then you poke around and find the definition for Person (the base class).

class Person    
    def initialize(name)
        @name = name
    end    
end

Ah, so we need a name to build a person object. The C# developer might instantly think of this scenario:

class Person
{
    public Person(string name)
    {
        this.name = name;
    }

    string name;
}

class Employee : Person
{
}

 

With C# you have to give Employee a constructor that will forward a name parameter to the base constructor.

class Employee : Person
{
    public Employee(string name) : base(name)
    {            
    }
}

In Ruby you can take this approach, too. It's a good approach if you need to perform some extra initialization for employees, like require a salary figure.

class Employee < Person
    def initialize(name, salary)
        super(name)
        @salary = salary
    end
end

emp = Employee.new("Chuck", 100)

It's Ruby's super keyword that acts like the base keyword in C#. The twist here is how Ruby will just make things work in the trivial case.

class Employee < Person
end

emp = Employee.new("Chuck")

In this code, "Chuck" will arrive at the initialize method of Person without any explicit code from us.

You might call it magic, or you might call it wonderful.

OData and Ruby

Sunday, July 11, 2010 by K. Scott Allen

The Open Data Protocol is gaining traction and is something to look at if you expose data over the web. .NET 4 has everything you need to build and consume OData with WCF Data Services. It's also easy to consume OData from outside of .NET - everything from JavaScript to Excel.

I've been working with Ruby against a couple OData services, and using Damien White's ruby_odata. Here is some ruby code to dump out the available courses in Pluralsight's OData feed.

require 'lib/ruby_odata'

svc = OData::Service.new "http://www.pluralsight-training.net/Odata/"
svc.Courses
courses = svc.execute
courses.each do |c|
   puts "#{c.Title}"
end

ruby_odata builds types to consume the feed, and also maps OData query options.

svc.Courses.filter("substringof('Fundamentals', Title) eq true")
fundamentals = svc.execute
fundamentals.each do |c|
    puts "#{c.Title}"
end

There is one catch - the Pluralsight model uses inheritance for a few of the entities:

<EntityType Name="ModelItemBase">
    <Property Name="Title" Type="Edm.String" ...="" />
    <!-- ... -->
</EntityType>
<EntityType Name="Course" BaseType="ModelItemBase">
    <Property Name="Name" Type="Edm.String" Nullable="true" />
    <!-- ... -->
</EntityType>

Out of the box, ruby_odata doesn't handle the BaseType attribute and misses inherited properties, so I had to hack around in service.rb with some of the Nokogiri APIs that parse the service metadata (this code only handles a one level of inheritance, and gets invoked when building entity types):

def collect_properties(edm_ns, element, doc)
    props = element.xpath(".//edm:Property", "edm" => edm_ns)
    methods = props.collect { |p| p['Name'] }
    unless element["BaseType"].nil?
        base = element["BaseType"].split(".").last()
        baseType = doc.xpath("//edm:EntityType[@Name=\"#{base}\"]",
                             "edm" => edm_ns).first()
        props = baseType.xpath(".//edm:Property", "edm" => edm_ns)
        methods = methods.concat(props.collect { |p| p['Name']})
    end
    return methods    
end

The overall Ruby <-> OData experience has been quite good.

Multithreaded Robocopy

Thursday, July 8, 2010 by K. Scott Allen

I was working with a fresh install of Windows Server 2008 when I noticed a new parameter in Robocopy's usage output:

            /MT[:n] :: Do multi-threaded copies with n threads (default 8).
                       n must be at least 1 and not greater than 128.
                       This option is incompatible with the /IPG and /EFSRAW options.

/MT is available in both 2008 and Win7. I did an informal benchmark against 12 GB of data spread over 300 files. The copy source was on the other end of a 100Mb switch.

With /MT:8 robocopy ran for 16 minutes and 24 seconds (984s).

With 1 thread robocopy ran for 18 minutes and 45 seconds (1125s).

7 threads yielded a savings of 12%.

I thought the copy operation would be 99% I/O bound with only 300 files to move, but I suspect the savings might be even more significant with the same data spread over 3,000 or 30,000 files.