# Sunday, December 07, 2008

Filters in ASP.NET MVC provide a great way to attach functionality around controllers. By building on top of the MVC framework, my ResourceUri class (which inherits from Controller) gets all the filter goodness as well.

My library also has a SubResourceUri class. Any filters applied to the parent ResourceUri are also executed for the SubResourceUri.

[ResourceUriTemplate("customers/{CustomerId}")]
[MyLoggingFilter]
public class CustomerUri : ResourceUri { ... }

[ResourceUriTemplate("orders/{OrderId}")]
public class OrderUri : SubResourceUri<CustomerUri> { ...}

For example, when we GET an order the filter still catches the request and outputs logging information.

Another use is authorization. You can place an authorization filter on top level URI and it will protect all sub-URIs beneath it.

 

Keep track of the latest developments on the code here: http://svn2.assembla.com/svn/snooze/branches/aspnet

.net | mvc | REST | web
Sunday, December 07, 2008 9:34:25 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Sunday, November 30, 2008

Continued work on my resource-oriented library for ASP.NET MVC has expanded to include an XDocument based view engine for ASP.NET MVC.

This means we can now use VB.NET XML literals to define XHTML views (or any XML views).

Get the latest from SVN.

.net | html | mvc | REST | vb.net | web | xml
Sunday, November 30, 2008 10:49:44 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [2]  | 
# Wednesday, November 26, 2008

Now that the ASP.NET MVC API has settled down I decided to bring some of my ideas about REST and resource-oriented programming to it.

The following screencast shows my current prototype in action:
http://www.aboutcode.net/screencasts/snooze-aspnet-mvc.wmv

I'm keen for comments and feedback.

The source code is currently available via SVN here:
http://svn2.assembla.com/svn/snooze/branches/aspnet

.net | c# | mvc | REST | screencast | web
Wednesday, November 26, 2008 3:23:02 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [1]  | 
# Saturday, November 08, 2008

Nemerle includes SQL macros. These make writing basic ADO.NET code a lot easier. They won't replace a complex ORM solution, but are fantastic for quick data access code. The main win is compile time query checking! That's right... if you misspell a column, table, etc, you get a compile error.

Watch the Screencast

Before

using System;
using System.Data.SqlClient;
 
namespace Demo
{
    module Program
    {
        Main() : void
        {
            using (conn = SqlConnection(@"Data Source=(local)\SQLEXPRESS;Initial Catalog=Customers;Integrated Security=SSPI"))
            {
                conn.Open();
 
                using (cmd = SqlCommand("select Id, FirstName, LastName from Customer where IsPrefered=1", conn))
                {
                    using (reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            def id = reader.GetInt32(0);
                            def firstName = reader.GetString(1);
                            def lastName = reader.GetString(2);
                            Console.WriteLine("{0}: {1} {2}", id, firstName, lastName);
                        }
                    }
                }
            }
 
            _ = Console.ReadLine();
        }
    }
}

After

using System;
using System.Data.SqlClient;
using Nemerle.Data;
 
[assembly: ConfigureConnection("System.Data.SqlClient.SqlConnection", @"Data Source=(local)\SQLEXPRESS;Initial Catalog=Customers;Integrated Security=SSPI")]
 
namespace Demo
{
    module Program
    {
        Main() : void
        {
            using (conn = SqlConnection(@"Data Source=(local)\SQLEXPRESS;Initial Catalog=Customers;Integrated Security=SSPI"))
            {
                conn.Open();
 
                ExecuteReaderLoop("select id, firstName, lastName from Customer where IsPrefered=1", conn, {
                    Console.WriteLine("{0}: {1} {2}", id, firstName, lastName);
                });
            }
 
            _ = Console.ReadLine();
        }
    }
}
Saturday, November 08, 2008 5:59:28 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [1]  | 

Correctly implementing structural equality involves a lot of code. My macro implements this for you.

Watch the Screencast

Before

using System;
using System.Console;
using Nemerle.Utility;
 
module Program
{
    [Record]
    public class Location
    {
        public Latitude : double;
        public Longitude : double;
 
        public override Equals(other : object) : bool
        {
            match (other)
            {
                | null => false
                | l is Location => l.Latitude == Latitude && l.Longitude == Longitude
                | _ => false;
            }
        }
 
        public override GetHashCode() : int
        {
            Latitude.GetHashCode() ^ Longitude.GetHashCode()
        }
 
        public static @==(l1 : Location, l2 : Location) : bool
        {
            def l1IsNull = object.ReferenceEquals(l1, null);
            def l2IsNull = object.ReferenceEquals(l2, null);
            match (l1IsNull, l2IsNull)
            {
                | (true, true) => true
                | (false, false) => l1.Equals(l2)
                | _ => false
            }
        }
 
        public static @!=(l1 : Location, l2 : Location) : bool
        {
            !(l1 == l2)
        }
    }
 
    module Program
    {
        Main() : void
        {
            def l1 = Location(30, 70);
            def l2 = Location(30, 70);
            def l3 = Location(40, 90);
 
            WriteLine("l1.Equals(l2) -> {0}", l1.Equals(l2));
            WriteLine("l1 == l2 -> {0}", l1 == l2);
            WriteLine("l1 != l2 -> {0}", l1 != l2);
            WriteLine("l1.GetHashCode() == l2.GetHashCode() -> {0}", l1.GetHashCode() == l2.GetHashCode());
            WriteLine("l1 != l3 -> {0}", l1 != l3);
 
            _ = ReadLine();
        }
    }
}

After

using System;
using System.Console;
using Nemerle.Utility;
using SampleMacros;
 
module Program
{
    [Record]
    [ImplementEquality(Latitude, Longitude)]
    public class Location
    {
        public Latitude : double;
        public Longitude : double;
    }
 
    module Program
    {
        Main() : void
        {
            def l1 = Location(30, 70);
            def l2 = Location(30, 70);
            def l3 = Location(40, 90);
 
            WriteLine("l1.Equals(l2) -> {0}", l1.Equals(l2));
            WriteLine("l1 == l2 -> {0}", l1 == l2);
            WriteLine("l1 != l2 -> {0}", l1 != l2);
            WriteLine("l1.GetHashCode() == l2.GetHashCode() -> {0}", l1.GetHashCode() == l2.GetHashCode());
            WriteLine("l1 != l3 -> {0}", l1 != l3);
 
            _ = ReadLine();
        }
    }
}

ImplementEquality.n

using Nemerle;
using Nemerle.Compiler;
using Nemerle.Compiler.Parsetree;
using Nemerle.Macros;
 
namespace SampleMacros
{
    [MacroUsage(MacroPhase.BeforeInheritance, MacroTargets.Class)] 
    public macro ImplementEquality(typeBuilder : TypeBuilder, params members : list[PExpr]) 
    { 
        ImplementEqualityModule.AddEqualsMethod(typeBuilder, members); 
        ImplementEqualityModule.AddEqualityOperator(typeBuilder); 
        ImplementEqualityModule.AddInequalityOperator(typeBuilder); 
    } 
 
 
    module ImplementEqualityModule 
    { 
        public AddEqualsMethod(typeBuilder : TypeBuilder, members : list[PExpr]) : void 
        { 
            def other = Macros.NewSymbol(); 
            def comparisons = members.Map(m => { 
                def s = Splicable.Name(Name(m.ToString())); 
                <[ (this.$s).Equals($(other : name).$s) ]> 
            }); 
 
 
            def b = comparisons.Tail.FoldLeft(comparisons.Head, (c, acc) => <[ $acc && $c ]>); 
            typeBuilder.Define(<[ decl: 
                public override Equals(obj : object) : bool 
                { 
                    match (obj) { 
                        | null => false 
                        | $(other : name) is $(typeBuilder.ParsedTypeName) => $b 
                        | _ => false 
                    } 
                } 
            ]>); 
 
 
            def hashCodes = members.Map(m => { def s = Splicable.Name(Name(m.ToString())); <[ this.$s.GetHashCode() ]> }); 
            def hashCode = hashCodes.Tail.FoldLeft(hashCodes.Head, (c, acc) => <[ $acc ^ $c ]>); 
            typeBuilder.Define(<[ decl: 
                public override GetHashCode() : int 
                { 
                    $hashCode 
                } 
            ]>); 
        } 
 
 
        public AddEqualityOperator(typeBuilder : TypeBuilder) : void 
        { 
            typeBuilder.Define(CreateEqualityOperator(typeBuilder.ParsedTypeName, false)); 
        } 
 
 
        public AddInequalityOperator(typeBuilder : TypeBuilder) : void 
        { 
            typeBuilder.Define(CreateEqualityOperator(typeBuilder.ParsedTypeName, true)); 
        } 
 
 
        CreateEqualityOperator(typeRef : PExpr, invert : bool) : ClassMember.Function 
        { 
            def op = Splicable.Name(Name(if (invert) "!=" else "==")); 
 
 
            <[ decl: 
                public static $op(p1 : $(typeRef), p2 : $(typeRef)) : bool 
                { 
                    def p1Null = object.ReferenceEquals(null, p1); 
                    def p2Null = object.ReferenceEquals(null, p2); 
                    match (p1Null, p2Null) { 
                        | (true, true) => true 
                        | (false, false) => $(if (invert) <[false == p1.Equals(p2)]> else <[p1.Equals(p2)]> ) 
                        | _ => false 
                    } 
                } 
            ]> 
        } 
    } 
 
 
 
}
Saturday, November 08, 2008 5:18:15 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [3]  | 

InheritConstructors is a handy macro when you need to simply pass all arguments to a base constructor.

Watch the Screencast 

Before

using System;

 

namespace MacrosDemo

{

    public class MyBaseClass

    {

        public this(name : string, foo : int, bar : bool)

        {

            _name = name;

            _foo = foo;

            _bar = bar;

        }

 

        _name : string;

        _foo : int;

        _bar : bool;

 

        public virtual Test() : string

        {

            "Hello from MyBaseClass"

        }

    }

 

    public class MySubClass : MyBaseClass

    {

        public this(name : string, foo : int, bar : bool)

        {

            base(name, foo, bar)

        }

 

        public override Test() : string

        {

            "Hello from MySubClass"

        }

    }

 

    module Program

    {

        Main() : void

        {

        }

    }

}

After

using System;

using Nemerle;

 

namespace MacrosDemo

{

    public class MyBaseClass

    {

        public this(name : string, foo : int, bar : bool)

        {

            _name = name;

            _foo = foo;

            _bar = bar;

        }

 

        _name : string;

        _foo : int;

        _bar : bool;

 

        public virtual Test() : string

        {

            "Hello from MyBaseClass"

        }

    }

 

    [InheritConstructors]

    public class MySubClass : MyBaseClass

    {

        public override Test() : string

        {

            "Hello from MySubClass"

        }

    }

 

    module Program

    {

        Main() : void

        {

        }

    }

}

Saturday, November 08, 2008 5:13:02 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

This is a simple macro I use to make transactions feel like apart of the Nemerle language.

Watch the Screencast

Before

using System;
using System.Transactions;
 
namespace Demo
{
    module Program
    {
        Main() : void
        {
            using (trans = TransactionScope())
            {
                // Do some stuff in a transaction
                // ...
 
                // Remember to call Complete when finished!
                trans.Complete();
            }
        }
    }
}

After

using System;
using System.Transactions;
using SampleMacros;
 
namespace Demo
{
    module Program
    {
        Main() : void
        {
            transaction 
            {
                // Do some stuff in a transaction
                // ...
 
            }
        }
    }
}

transaction.n

using System;
using System.Transactions;
 
namespace SampleMacros
{
    public macro transaction(block) syntax ("transaction", block)
    {
        <[ 
            using (t = TransactionScope()) {
                $block;
                t.Complete();
            }
        ]>
    }
}
Saturday, November 08, 2008 5:08:54 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

The [Record] macro is applied to classes and makes it very easy to create simple data-transfer objects.

Watch the Screencast

Before

using System;

 

namespace MacrosDemo

{

    public class CustomerDto

    {

        public Id : int;

        public FirstName : string;

        public LastName : string;

        public IsPrefered : bool;

 

        public this(id : int, firstName : string, lastName : string, isPrefered : bool)

        {

            Id = id;

            FirstName = firstName;

            LastName = lastName;

            IsPrefered = isPrefered;

        }

    }

 

    module Program

    {

        Main() : void

        {

            def dto = CustomerDto(1, "John", "Smith", true);

        }

    }

}

 

After

using System;

using Nemerle.Utility;

 

namespace MacrosDemo

{

    [Record]

    public class CustomerDto

    {

        public Id : int;

        public FirstName : string;

        public LastName : string;

        public IsPrefered : bool;

    }

 

    module Program

    {

        Main() : void

        {

            def dto = CustomerDto(1, "John", "Smith", true);

        }

    }

}

 

Saturday, November 08, 2008 5:04:29 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Sunday, August 24, 2008

There are currently two approaches when using L2S. Either adding attributes to classes to denote columns, or creating an external XML mapping definition. Neither of these is great. Attributes mix non domain concerns, namely database schema, into domain objects. XML mapping needs to be kept in sync with the classes it describes. During the early stages of a new project, the structure of classes can vary and morph over time. So manual mapping is annoying.

My suggestion is to create a "convention-based" mapping. Where you can define POCOs and then have reflection to build the mapping, based on some simple naming conventions. This mapping can then be used by a DataContext and a database created from it. (Note that I am only considering green field developments, where we are working "code-first".)

The conventions I have thought about so far include:

  • A property named "Id" will be the primary key.
  • If Id is an int then make it auto incrementing.
  • All primitive, string and DateTime properties are columns.
  • All properties having the type of another entity in the DataContext are associations.
  • All properties of type EntityRef<T> are associations.
  • There must be a foreign key Id property defined for associations.
  • Any property with subtype a of IList<T> is an association.

One-to-many associations need to be a bit smart with their names. Consider:

class Customer {
  public Employee ReferringEmployee { get; set; }
}
class Employee {
  public List<Customer> ReferredCustomers { get; set; }
}

The mapping needs to understand the "ing" and "ed" relation. Also, we'll perhaps need support for TechSupportEmployee <--> TechSupportedCustomers.

The conventions should follow the usual rules of English grammar. I hope, therefore, that they do not interfere with the universal language discovered by domain driven design.

As a project begins to settle down, there will be requirements that the convention mapping doesn't support. Rather than having to switch to full manual XML mapping, perhaps an augmentation layer could applied. This could describe specific cases of the mapping that are different. For example, a certain primary key column using GUIDs instead of integers.

c# | linq | linq-to-sql | orm
Sunday, August 24, 2008 11:09:43 AM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, July 23, 2008

I decided to spend the day creating Spectacle.

Spectacle is a spec-driven/bdd/{buzzword-of-choice} embedded DSL for Nemerle. It creates NUnit compatible test fixtures from very human readable code.

So in the spirit of release early, etc...
Project site: http://www.assembla.com/wiki/show/spectacle
Also: 3 minute screencast:
http://screencast.com/t/4dPdsg35Uj
You'll probably be needing to the pause to read stuff!
Enjoy :) all feedback is welcome.

An example spec:

spec "Account with 100"
    account = Account(100)

    getting account.Balance returns 100

    doing account.Deposit(100) means
        account.Balance == 200

    doing account.Withdraw(50) means
        account.Balance == 50

    doing account.Withdraw(200) throws ArgumentException

Wednesday, July 23, 2008 5:41:23 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  |