kenegozi.com

<form id='kenegozi' action='post'></form>

   
2008 Sep 23

MSDN Killed my using directive

tagged as: miscellanea | c#

I'm now sitting in a certain lecture by a well known MS speaker.

The title is "ASP.NET Hidden Gems", but that's not the point.

 

During the presentation the dude is showing nice things like Custom Build Providers, Custom Expression Builders, Virtual Path Provider (that's a nice one), Session State Partitioning (nice), and other stuff.

 

This is all great and cool and nice and blah blah blah.

 

However, now he's just showed how he's using a CustomBuildProvider to "make data access more efficient", by setting a custom build provider for data-set xsd files, creating cleaner Data objects instead of TypedDataSets.

 

That's a very nice thing.

 

However, his demo code, splashed over two 100" mega screens, included a use of SqlConnection and DataReaders, without using "using".

heck, he didn't even dispose the objects on "finally".

 

I mean - WTF?

 

That's the reason I hate DEMO codes. People in the crowd is looking at that, and then they go ahead and write the same code in their day job. And then I get called in to fix it.

 

Was it so difficult for the guy to write better code? heck, the "using" keyword would have eliminated at least 4 lines from the demo, so it would even be more presentable.

 

I simply don't get it.

2008 Sep 22

IoC.NET Smackdown

tagged as: architecture | tools | castle

I've just came across a comparison on IoC containers in the .NET world:

 

Haven't read it yet cuz Im actually off-computer right now (the lappy is attached to the living room TV, and the break in the movie is almost over), but MAN is has COLOUR charts, so you can bet your arse I'm gonna read it later.

 

Not that I'm excited. I'm pretty sure that (INSERT WINNER HERE LATER) will prove to be the best IoC ever.

2008 Sep 15

Creating a custom parameter binder for MonoRail actions - IParameterBinder

tagged as: castle | monorail
Background

When using SmartDispatcherController as a base class for a MonoRail's Controller, there are built-in smarts for binding values from the client (Form, QueryString, Request.Params) into .NET data types.
So, assuming the request holds  "age=30", and there's an action

public void SomeAction(int age) ...
then the integer variable 'age' will get populated with the value 30.

This will work for every .NET primitive (int, string, bool) and even DateTime and Guid.
If the value is missing from the request, a default value will be set, for example - 0 for integers, or null of nullable types.

There's also DataBindAttribute that allow you to bind values to a non-primitive DTO object.
Say you have

public class User
{
    string Name {get;set;}
    int Age {get;set;}
}
and that your request is holding "User.Name=Ken&User.Age=30", then the following action
public void SomeAction([DataBind("User")] User user) ...
will bind the age and name into a new instance of User.

 

Problem

Yesterday, on Castle devs mailing list Andre Loker was asking about a way to bind a value to an action argument, but with the value having a name that cannot match a c# variable name.
For example, let's say that the request is holding "User.Age=30", but you do not want to bind to a User instance (through DataBind) but you want only the Age part, into an integer variable.
You certainly cannot have your action signature look like

public void SomeAction(int User.Age) ...

Solution:

Luckily for us, MonoRail was built with extensibility in mind (and whenever a user feels something more is required in the field of extensibility, a patch is always welcome :) ).
The extension point here is the IParameterBinder interface, which is being used in DataBindAttribute to let the framework know that the attribute is to be used for data binding.

IParameterBinder:

/// <summary>
/// Implemented by attributes that wants to perform 
/// some conversion to populate a smart dispatcher 
/// action argument.
/// </summary>
public interface IParameterBinder
{
    /// <summary>
    /// Calculates the param points. Implementers should return value equals or greater than
    /// zero indicating whether the parameter can be bound successfully. The greater the value (points)
    /// the more successful the implementation indicates to the framework
    /// </summary>
    /// <param name="context">The context.</param>
    /// <param name="controller">The controller.</param>
    /// <param name="controllerContext">The controller context.</param>
    /// <param name="parameterInfo">The parameter info.</param>
    /// <returns></returns>
    int CalculateParamPoints(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo);

    /// <summary>
    /// Binds the specified parameters for the action.
    /// </summary>
    /// <param name="context">The context.</param>
    /// <param name="controller">The controller.</param>
    /// <param name="controllerContext">The controller context.</param>
    /// <param name="parameterInfo">The parameter info.</param>
    /// <returns></returns>
    object Bind(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo);
}

 

The CalculateParamPoints function is used by the framework to help SmartDispatcherController decide with overload of a given action should be used.

the Bind function, well, binds the request data into the given parameter.

 

Here is a naive BindFrom attribute, which is to be used like that:

public void SomeAction([BindFrom("User.Age")] int age) ...

The code:

[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] public class BindFromAttribute : Attribute, IParameterBinder { private readonly string parameterName; private readonly IDataBinder binder = new DataBinder(); public BindFromAttribute(string parameterName) { if (string.IsNullOrEmpty(parameterName)) {

throw new ArgumentException("parameterName must not be null or empty", "parameterName"); } this.parameterName = parameterName; } public string ParameterName { get { return parameterName; } } public int CalculateParamPoints(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo) { var token = context.Request[parameterName]; if (CanConvert(parameterInfo.ParameterType, token)) return 10; return 0; } static bool CanConvert(Type targetType, string token) { if (token == null) return false;

try

{ Convert.ChangeType(token, targetType); return true; } catch(FormatException) { return false; } } public object Bind(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo) { var token = context.Request[parameterName]; if (CanConvert(parameterInfo.ParameterType, token) == false) return null; return Convert.ChangeType(token, parameterInfo.ParameterType); } }

 

Conclusion

The IParameterBinder interface is very important as it allow a user to extend MonoRail to his exact needs. If you want to learn more about that interface and it's uses, the best places to look are DataBindAttribute.cs in Castle.MonoRail.Framework/Attributes, and ARDataBindAttribute.cs in Castle.MonoRail.ActiveRecordSupport

 

As a side note, I'm thinking about adding the discussed behaviour into the default DataBindAttribute, so one would be able to bind into primitives, say from "User.Age=30&User.Name=Ken" using

public void SomeAction([DataBind("User")] int age, [DataBind("User")] string name) ...
2008 Sep 12

New design to my search page

tagged as: miscellanea | personal

I've revisited my google-ajax-enabled search page (at www.kenegozi.com)

homepage

 

It can still look better of course, but it is much better than the former one.

Now I need to revisit my blog's design a wee bit ...

 

btw, I use this page as the home page on all my browsers. It makes googling much faster and productive, and you are all invited to use it for your search needs. I try to keep it as lightweight as possible so it would load as fast as possible. Suggestions etc. are always welcome.

2008 Sep 11

Context aware service overrides - customising behaviour

tagged as: architecture

Assume you are building some kind of an information system. Say it's an issue tracker (yeah I know, I have a blank spot in the creative-part of my brain).

 

Now say you want some visual customisation based on the current context - like a different look'n'feel for each customer on a multi-tenant application, or a slightly different menu for an Admin.

Kinda easy - right? you'd stick some overriding CSS rules for the former (say on CUSTOMER_ID.css), and some kind of a simple view logic for the latter (say <% if (isAdmin) { %> ... <%}%>, or some type of CodeBehind crap if you're a WebForms lover).

 

But - what if you want to customise the behaviour according to context? say that for some actions, for a given customer, an email should be sent, or a webservice be called, or some default data should be set for a given form.

 

The first option would be to create an interface ICustomerActions, and a DefaultCustomerActions which will be in charge of the, well, default behaviour. then for each customer you'd derive from DefaultCustomerActions (or directly from the interface if it's completely different).

Then you'd use some kind of a Factory (or your container) to resolve the needed ICustomerActions instance according to the context (say a customerId in the Session).

 

There are two problems in this approach

  1. A possible and probable break of SRP. The ICustomerActions interface will grow to be in charge of lots of things, on different parts of the logic, some that belongs in view rendering, and you end up with a huge Mega-Class.  That's bad.
  2. The inheritance will start to be annoying. Cuz a new customer#3 will behave like customer#2 in some of the situations, and like customer #1 in others, like the default on some cases, and have a specific implementation for ICustomerActions.SomeTypeOfThing.  So you will probably end up with a bunch of template methods lying around, and logic scattered around the inheritance tree.

 

So how do you think I solved this problem?  How would you do that?

2008 Sep 3

Israel is finally on the (Google) map

Not tagged yet

For a long time now, we in Israel did not have a free and convenient mapping solution. If you wanted to mashup mapping, you had to buy highly priced licenses from one of the mapping companies, like AtlasCity, eMap or Mapa.

These suppliers also did not support querystring based mapping location, so you just couldn't share a quick link to a location.

 

However, as of today, Israel's maps are showing up on Google maps website.

Street names are still missing, and the satellite images are not detailed enough, but now I can link to a map showing Bat-Yam (where I live) in conjunction with Tel Aviv and Ben Gurion airport (at the bottom right corner)

 

I once was helping a friend with a startup that involved geo-location and mashups, and since he wanted a next-no-nothing cost for the proof of concept, and since it relied on mapping mashups, and none was available freely, he couldn't have complete that stage and the thing has gone away.

I guess now we'll start seeing all kinds of interesting masups with the maps, considering Israel is known to breed tons of new startups.

search page | Blog's home | About me