vrijdag 29 augustus 2008

Google maps support for your asp.net site

I used the club starter kit as a base website template for my soccer team.  It has a location feature where you can put the locations of certain important events (where our next game is, where do we meet up front, where are we having drinks afterwards, etc...).  I though it would be nice to add support for Google maps so we can see where we'll have to play and give my teammates directions.  This way I would already resolve the lame excuses that they usually have for being late.

At first I just looked at the Google website.  Where else would you check how to integrate Google maps in your web app?  I found an entire JavaScript api ready for use so I started hacking away.  Now I must admit JavaScript is not my favorite language, I can manage but that's about it.  Since I believe there will be other developers just like me, someone must have written server controls for it.  And yes there is one available Googlemaps.subgurim (Free for non commercial use)

Just drag an drop the map control into your page, size it decently and put code to position the map in the page_load event handler.  The website contains many useful and simple samples so I won't bore you with implementation details.  You can see the map in action on my soccer's team (gilsboys) website (click the location list hyperlink for more locations).  But I have to warn you if you decide to explore more of the site is in Dutch and my team is not famous for the way we play soccer but more for the drinks and parties afterwards.  I guess it's my way of apologizing already for the pictures that are already available :-)

Check with you later !

dinsdag 26 augustus 2008

Template your way into the hearts of your users !

This week we discussed our communication strategy at work.  As already told previously we are writing a security service which involves creating users, adding and removing permissions and so on...  Any of these actions can be performed by various actors (the user himself, an administrator, some batch job, ....) and thus the user must be notified about any change!  Of course requirements are that the business should be able to change the emails, so hard coding them is out of the question (as always :-).

I had a look at a couple of template engines this weekend to solve the problem.  Since I used Stringtemplate before I decided to go along with that one.  The beauty of a template engine is that you can pass in an object graph and let the template figure out what to write and more importantly how to write it.  First task was to make a simple email template that could be sent to the user:

1 group TemplateEmail; 2 3 Email(person, action) ::= << 4 5 \<html\> 6 \<body\> 7 Dear <person.name>, 8 \<br\> 9 \<br\> 10 11 You receive this email because the following action \<b\> "<action.Name>" \</b\> has occurred. 12 \<br\> 13 \<br\> 14 15 This leads to changes in the permissions you have on our applications. 16 \<br\> 17 18 Please logon into our application to validate your permissions. 19 20 \<br\> 21 \<br\> 22 \<br\> 23 Sincerly, 24 Patrick 25 \</html\> 26 \</body\> 27 >>

Done, this template creates a personal email with a header including the user's name and a subject containing the action that has occurred.  Please not that the html syntax is entirely escaped because the < and > are used to refer to parameters and other templates.  According to the documentation you should be able to use $ as well, but in my template these templates were never replaced.  Is it because the dollar is that low?  :-)). 

The two templates that need replacing are <person.name> and <action.name>, the engine will try to find a property name on both of these objects (person and action), which need to be handed to the template engine.  (If it cannot find this, the templates results in an empty string).  Next we need to convert this template into a email with all values filled in, the following code does just about that:

1 var group = new StringTemplateGroup(new StreamReader("templates\\TemplateEmail.st")); 2 var template = group.GetInstanceOf("Email"); 3 4 template .SetAttribute("person", person); 5 template .SetAttribute("action", action); 6 7 var emailBody = query.ToString();

Again, piece of cake, if you put the result of the toString() into your email body you have nicely formatted email.  How did this work?  The first line reads the file from the disk in which the templates are stored.  You get a group of templates as result, you then ask it for your named template.  If you require attributes you can set them here by using the SetAttribute methods.  Finally let the template engine do its work by calling the toString() on it.

All right, seems that basic templating is easy, let's switch to the next gear and divide our template into several little reusable templates.  After all we will want to send different mails based on what action has been performed, the type of user who has performed the action, ....  So let us create some templates for a mail header, mail subject and mail footer:

1 WriteMailHeader(person) ::= << 2 3 \<html\> 4 \<body\> 5 \<div\> 6 Dear <person.name>, 7 \</div\> 8 \<br\> 9 \<br\> 10 >> 11 12 WriteMailAction(action) ::= << 13 14 You receive this email because the following action \<b\> "<action.Name>" \</b\> has occurred. 15 \<br\> 16 \<br\> 17 >> 18 19 WriteEmailFooter() ::= << 20 \<br\> 21 \<br\> 22 \<br\> 23 Sincerly, 24 Patrick 25 \</html\> 26 \</body\> 27 >>

As you can see all multi line templates start with the template name followed by the argument list.  The ::= << sign means the templates starts here and ends with the >> sign.  Our mail template can now be rewritten as follows:

1 group TemplateEmail; 2 3 Email(person, action) ::= << 4 <WriteEmailHeader(person)> 5 <WriteEmailAction(action)> 6 7 This leads to changes in the permissions you have on our applications. 8 \<br\> 9 10 Please logon into our application to validate your permissions. 11 <WriteEmailEnding()> 12 >> 13

The following step is to make our mail more useful by providing extra information.  Lets assume that our Person has a property AuthorizationSet which holds two collections (one for the applications you are authorized to use and one for the functionalities you can execute).  Our template can now read these properties and act upon these values.  So let's add the applications and functionalities you are authorized for in the mail template.

1 WriteApplicationInformation(person) ::= << 2 You have access to the following applications: 3 \<ul\> 4 <person.AuthorizationSet.Applications:{application|<WriteApplicationInformationLine(application)>}; separator="\n"> 5 \</ul\> 6 >> 7 8 WriteApplicationInformationLine(application) ::= << 9 \<li\> <application.Name> of type <application.Type> valid from <application.StartDate> till <application.EndDate> \</li\> 10 >> 11 12 WriteFunctionalityInformation(person) ::= << 13 You have access to the following functionalities: 14 \<ul\> 15 <person.AuthorizationSet.Functionalities:{functionality|<WriteFunctionalityInformationLine(functionality)>}; separator="\n"> 16 \</ul\> 17 >> 18 19 WriteFunctionalityInformationLine(functionality) ::= << 20 \<li\> <functionality.Name> with code <functionality.Code> valid from <functionality.StartDate> till <functionality.EndDate> \</li\> 21 >> 22 23

And you simply call these templates with the following 2 lines in your email template:

<WriteApplicationInformation(person)> <WriteFunctionalityInformation(person)>

Let's go a little bit deeper in the previous templates we've seen, shall we!  We have created 4 sub templates, two for application permissions (WriteApplicationInformation and WriteApplicationInformationLine) and two for functionality permissions (WriteFunctionalityInformation and WriteFunctionalityInformationLine).  The main template calls the line template for each item.  This is achieved by the following syntax: < property : { subtemplate }; separator = "\n">,.  This means that for each property (if it is an array, otherwise it will be called only once) the subtemplate is called, the "\n" character will be used in the template between every iterated call.  The subtemplate has the following pattern { parameter | <template(parameter)>}.  First you name the value for each iterated object, then you specify what other named template to call (or use an inline template).

Finally I would like to add extra information on the items depending on the value we have in the permission sets.  Every permission has a start date and an end date.  These are shown as well, but now when a permission has an end date set to sometime far in the future, it doesn't really add any extra value.  On top of that it looks unprofessional too, so let's us vary the template based on wether we have a permission that is open ended.  First add an extra property in your permission class IsOpenEnded that returns true/false based on the EndDate == DateTime.MaxValue.  Then make an if structure in your template depending on this property.  If we have an open end, we simply make do not display the end date, but show a slightly different text.

1 WriteApplicationInformationLine(application) ::= << 2 \<li\> 3 <application.Name> of type <application.Type> 4 <if(application.IsOpenEnded)> 5 valid from <application.StartDate> till piggs can fly 6 <else> 7 valid from <application.StartDate> till <application.EndDate> 8 <endif> 9 \</li\> 10 >>

So now we have a nice looking email that communicates everything we want with just providing an object tree to our template.  But of course that doesn't suffice.  We want to be able to differentiate templates between the action we have performed, that was one of the reasons why we created the small templates remember.  So if we modify the code where we load our template, we can choose a different template based on the action we had.

1 var group = new StringTemplateGroup(new StreamReader("templates\\TemplateEmail.st")); 2 var template = group.GetInstanceOf("EmaiForl"+action.Type); 3 4 template .SetAttribute("person", person); 5 template .SetAttribute("action", action); 6 7 var emailBody = query.ToString();

This means we need to have templates for the different actionTypes our application has, in our case these two templates would be required:

1 EmailForChangeAuthorization(person, action) ::= << 2 <WriteEmailHeader(person)> 3 <WriteEmailAction(action)> 4 \<br\> 5 This leads to changes in the permissions you have on our applications. 6 \<br\> 7 <WriteApplicationInformation(person)> 8 <WriteFunctionalityInformation(person)> 9 10 <WriteEmailEnding()> 11 >> 12 13 EmailForChangePassword(person, action) ::= << 14 <WriteEmailHeader(person)> 15 <WriteEmailAction(action)> 16 17 We are glad to inform you that your new password is <MakeBold(person.password)>, please 18 logon and change your password to something more personal. 19 20 <WriteEmailEnding()> 21 >>

 

That pretty much it.  If you want to have a look at it yourself, you can download the code or go have a look at the he Stringtemplate website.

zaterdag 2 augustus 2008

Simplify your life... decorate with aspects !

In the company that currently hired me tracing for instance (which is one of the areas you could benefit a lot from using aspects), is done my hand.  Every method (at least most of them)  follows the next format

public bool Method(params string[] inputValues) { Trace("Enter", "MethodName", inputValues); // trace all input parameters ..... bool someValue; ...... Trace("Exit", "MethodName", someValue); // trace parameters leaving the method return someValue }

If you only have to write code once and then never touch it again, maybe this way of developing would be acceptable.  But I rarely (read never) have been on a project where this was true.  Code will be refactorred and not only once.  Keeping the tracing parameters in sync with the constant refactorings is something that is often forgotten.  Compare it with the method documentation you write, if you would generate your ndoc now does it truly reflect your code??  My thoughts exactly, so help is needed, aspect orientation to the rescue.  If you Google aspect orientation (that's right I even saved you the time to do that) you will find many useful resources and implementations, today I will be taking a closer look into PostSharp

PostSharp performs a post compilation step to inject IL code, which means it can 'adapt' your entire code base even private methods,fields...  You can use PostSharp in two ways, the easiest is to download the msi file and install it on your machine.  If you are anything like me you hate installing software on your machine, you might have a look at this blog post from Gael Fraiteur the lead developer for the project.  He explains what happens under the hood and how the post compile step is called in msbuild.   

If now you add the required assemblies (PostSharp.public and optionally PostSharp.Laos) to your project, the post compilation step will automatically gets called from msbuild.  It will search your assembly for all required tasks to process and then updates the IL code.

First on my list is to improve my above tracing problem.  This is easily solved by overriding the OnMethodBoundaryAspect (provided as one of the higher level aspects of the PostSharp.Laos library) , this provides the following methods:

  • OnEntry : called when entering the method
  • OnExit : always called when exiting a method
  • OnException: called when the method resulted in an exception
  • OnSuccess: called when the method executed successfully

and leads to the following code:

public override void OnEntry(MethodExecutionEventArgs eventArgs) { Trace.WriteLine( string.Format("Enter {0}.{1}.", typename, methodname), this.category); } public override void OnExit(MethodExecutionEventArgs eventArgs) { Trace.WriteLine( string.Format("Leaving {0}.{1} with {2}", typename, methodname, eventArgs.ReturnValue), this.category); } public override void OnException(MethodExecutionEventArgs eventArgs) { Trace.WriteLine( string.Format("Exception {0}.{1}.", eventArgs.Exception.Message, eventArgs.Exception.StackTrace), this.category); } public override void OnSuccess(MethodExecutionEventArgs eventArgs) { // Usually you don't need this }

Another way to achieve this is to override the OnMethodInvocation.  This provides you with different methods to work with but you have the same functionality at your disposal.  The major difference is that this method does not modify your original method (as would happen with the above sample), but intercepts the call en invokes your OnInvocation method).  Check reflector to see the differences here!!

public override void OnInvocation(MethodInvocationEventArgs eventArgs) { // Perform tracing here Trace.WriteLine( string.Format("Enter {0}.{1}.", typename, methodname), this.category); try { base.OnInvocation(eventArgs); // Invoke your method here! } catch(Exception ex) { Trace.WriteLine( string.Format("Exception {0}.{1}.", ex.Message, ex.StackTrace), this.category); } finally { Trace.WriteLine( string.Format("Leaving {0}.{1} with {2}", typename, methodname, eventArgs.ReturnValue), this.category); } }

So far so good.  Applying these attributes is as simple as using other attributes in .NET, just decorate your method/class with them.  If off course you wish to perform tracing on an entire assembly or part of it, You will be adding a lot of these attributes, so a better way has been provided:  The following configuration intercepts all method calls from the Tracing.Model, Tracing.Repository and Tracing.Service namespace.    You could tweak this further.

[assembly: Trace(AttributeTargetTypes = "Tracing.Model.*")] [assembly: Trace(AttributeTargetTypes = "Tracing.Repository.*")] [assembly: Trace(AttributeTargetTypes = "Tracing.Service.*")]

You could specify on which the aspects (or attributes) can be applied by specifying the AttributeUsage and MulticastAttributeUsage, see the official documentation about that here (UserGuide -> Using PostSharp LAOS -> Wildcards and multicasting).

Secondly my I wanted to simplify my validation code.  One solution is to decorate my fields with the specification they have to obey.  For instance

  • A String field should contains maximally 16 characters
  • A Number must be between 1-100 (see the following code sample)
  • A Date must be in the future
[Serializable] public class RangeSpecification : OnFieldAccessAspect { public Int32 _minimum = 0; public Int32 _maximum = 100; public RangeSpecification(Int32 minimum, Int32 maximum) { _minimum = minimum; _maximum = maximum; } public override bool CompileTimeValidate(System.Reflection.FieldInfo field) { Console.WriteLine("RangeSpecification"); // this comes in the output window when compiling if (field.FieldType.Name != typeof(Int32).Name) { // "Why would you want to use this specification on a non number field?" return false; } return true; } public override void OnSetValue(FieldAccessEventArgs eventArgs) { Int32 exposedValue = Int32.Parse(eventArgs.ExposedFieldValue.ToString()); if (exposedValue < _minimum || exposedValue > _maximum) { // keep the old value when an invalid value was passed in eventArgs.ExposedFieldValue = eventArgs.StoredFieldValue; } base.OnSetValue(eventArgs); } }

So far the first exploration of PostSharp, I  realize this was only the top of the possibilities but I hope everybody can see how much code can be saved and might not clutter your production code by applying these aspects correctly in your code.

See you next time.