First time here? You are looking at the most recent posts. You may also want to check out older archives or the tag cloud. Please leave a comment, ask a question and consider subscribing to the latest posts via RSS. Thank you for visiting! (hide this)

June 2007 Blog Posts

Too many Code Monkeys joining the developer community?

This seems to become one of the hottest topics about the socials of software development.

After last weeks' posts by Ayende on whether Microsoft should target "Mort" instead of the Alpha Geeks (and all the other post about that topic around the community), Scott Dorman said that there is an even worse problem: the "mass market developer":

A "mass market developer" is usually at the low end of the developer spectrum.A more frustrated code monkey, ibid. They have no formal training and are what could generally be considered to be a "code monkey", but in the derogatory sense. These are the people who stitch together snippets of code found on the Internet and in books to make an application, without having an appreciation or understanding what the principles behind the code or the concept of coding are.

And Scott also expresses his frustration noticing what everybody has probably already seen itself: "monkey questions".

The trend that I have been seeing is the increasing number of discussion forum posts by individuals claiming to be developers (mostly professional developers) asking what I can only call "monkey questions". These are questions that are so basic that they really shouldn't even be asked. Questions that show a complete lack of understanding of programming concepts and the programming language as well as a sheer lack of initiative to learn.

Last week there was an intense thread on the NZ.NET mailing list, and one of the messages said more or less:

[I don't like idea of moving the ML to a public accessible repository because] then the ML will be spammed with questions by n00bs from India, China, pick-your-spam-country, asking "How can I do basic xyz? It's urgent!"

Is this becoming more and more a threat for the professional developer? Or will companies be smart enough to understand that "good developers costs a bit more then bad ones, but are 10 times more productive"?

Here is the original post: Programming for the masses.

CC.NET Monitor almost v1.0

In the last days I've been working on my Vista Sidebar Gadget with the intent to make it v1.0 before going back to Italy at the beginning of August.

I'd like to make version 1 of my gadget a replacement for the CCTray application that ships with CruiseControl.NET: last month I silently released version 0.9 with the possibility to force a build on the server and now I'm trying to add the possibility to play a sound when a build breaks or, even better, launch a batch file.

I'm also adding small enhancements to the UI, like the ones requested by David Gardiner or the ones by David Mitchell.

This is the list of the items that will be included in version 1.0:

I will probably release a 0.9.5 version next week to get from you some feedback, and will probably release version 1.0 before the end of July.

Would you like to have some other feature in the gadget? Do you have any suggestion? Please leave a comment and let me know what you think about it.

Technorati tags: ,

Ajax TreeView

For the project I'm working on I have to display thousands of user grouped by team, company, accounts, resellers and, sometimes, reseller of resellers. And I need to display the hierarchy using a treeview. Unfortunately the treeview control that is available with ASP.NET 2.0 cannot handle so many "nodes" with a decent level of performance, and even if he could, an html page with some thousands of users added inside nested <ul> tags will probably be more than 1 or 2 Mb: not something you want for your web application.

Unfortunately the is no TreeView control inside the ASP.NET AJAX Control Toolkit, so I looked around for something similar to the MSDN Library contents tree.

I found a few ajax treeviews, but none of them is built as an ASP.NET Ajax control or extender:

I need something that is easy to implement, easy to understand, with a nice look&feel out-of-the-box but also easily customizable.

ext_tree After a quick look at the three components above I decided to go with the Ext one.

As you can see in the image at the left (here is a live example), it's very nice looking, nice transition effects, nice loading indicator.

And it's also quite easy to implement:

just add the reference to the extjs library, add a div in the position where you want the tree view to appear and write 10 lines of javascript to add the root tree node to the tree panel and to configure the ajax tree loader.

Then you have to write your own ajax loader that returns a JSON formatted list of nodes.

The only drawback is that it needs a 450Kb javascript library and a 80Kb style sheet just for a small functionality.

I already trimmed down the CSS to small 4Kb style sheet, removing all the styles used in the other controls of the suite, but I still have to find out a way to reduce the size of the javascript library: they have a nice "Build your own Ext" that should build your custom ext library with only the classes you need for your functionalities, but I still have to find all the dependencies I need in order to have my tree view working, so, for the moment, I'm including the full library: I'll reduce the size in the future.

If you want to try it yourself, you can download it here.

Technorati tags: , , ,

Make yourself as indestructible as possible (cit. Mark Twight)

Cima di Cantun North Face Last week I found at a bookshop here in Wellington a book I had been looking for since a few years: Extreme Alpinism: Climbing Fast, Light and High

This book was written by Mark Twight, "Punk Climber" in the '80s, and now President of Grivel North America (for those how are not into mountain climbing, Grivel is one of the best alpine tool factory in the World). And the book is about training for mountain climbing.

I'm reading it now and I just found a sentence that I want to share:

The goal of training for alpine climbing can be summed up in one phrase: to make yourself as indestructible as possible. The harder you are to kill, the longer you will last in the mountains.

Mark Twight is my hero, my inspiration for climbing. He also wrote another book, Kiss or Kill: Confessions of a Serial Climber.

If you are into alpinism or mountain climbing, I really recommend the last book. While the first is a (unusual, very unusual) training manual, the second is the best book about mountain climbing I ever read in my life: this is one of the reasons why I swapped my outdoor activities from sailing and water sports to climbing and mountaineering. And he also suggests a very "inspiring" playlist.

Sunset from Monte Rosa

The two pictures are: Cima di Cantun, North Face and a breathtaking sunset from the Mt. Rosa over all the Valle d'Aosta.

How to refresh an UpdatePanel from javascript

I thought that updating an UpdatePanel from javascript was one of the most frequently asked question about ASP.NET Ajax, but even looking around a lot I didn't find a clean and polished solution for what should be a common task.

I didn't want to create an ASP.NET Ajax extender for such a simple task, but after a few hours of Google-ing, I found a few nice articles on Ben Rush's blog, which is a very valuable source of knowledge on the internals of ASP.NET Ajax, ScriptManager and other ASP.NET Ajax goodies.

The first article explains a very nice way to trigger the update of an UpdatePanel from JavaScript, while the other two are very detailed overviews on the internals of how an UpdatePanel is updated.

The only thing you need to do to refresh from javascript is to register a Button (hidden via CSS) Click event as async trigger for an UpdatePanal and then call the following method from your javascript method:

__doPostBack('<%= Button_Search.ClientID %>','');

Yes, that easy. Nice, isn't?

But in my page I also had to pass a value to the UpdatePanel, so the button was not enough.

So I adapted a bit Ben's solution, and I add hidden text box, and update its value before calling the doPostBack method.

To implement that you need to add 4 "things" in your ASP.NET web form.

Add the hidden textbox

You need a textbox to store the value you want to pass over to the UpdatePanel, but you don't want to show it in the page, so it must be hidden via CSS.

<asp:TextBox ID="text" runat="server" style="display:none;"></asp:TextBox>
<asp:Button ID="button" runat="server"
        OnClick="button_Click" style="display:none;"/>

Register the async trigger for the UpdatePanel

<asp:UpdatePanel runat="server" ID="UpdatePanel1" UpdateMode="Conditional">
   <ContentTemplate>
     <asp:Label ID="label" runat="server"></asp:Label>
   </ContentTemplate>
   <Triggers>
     <asp:AsyncPostBackTrigger ControlID="button" EventName="Click" />
   </Triggers>
 </asp:UpdatePanel>

You see that I registered an AsyncPostBackTrigger on the Click event of the button.

I also added a label that will be updated by the event raised by the textbox. Remember to set the UpdateMode to Conditional, otherwise the UpdatePanel will always be refreshed, not only when there is a postback inside or when a trigger fires.

Add the JavaScript method to refresh the UpdatePanel

<script type="text/javascript"> function UpdPanelUpdate(value)
{
var obj = document.getElementById("<%= text.ClientID %>");
obj.value=value;
__doPostBack("<%= button.ClientID %>","");
}
</script>

Using the ClientID property of the control will ensure that you get the right ID even if the control is inside a masterpage, a webcontrol, a repeater or whatever might change the ID.

I set the value on the hidden textbox but I do the postback on the button.

Update the contents of the UpdatePanel

And finally, you are ready to update the contents of the UpdatePanel based on the value set by the javascript method on the client:

protected void button_Click(object sender, EventArgs e)
{
label.Text = text.Text;
}

This changes the text in the label inside the UpdatePanel with the value set in the hidden textbox and passed through by the async postback.

Here is a file with a working sample: UpdatePanelAndJS.aspx

Technorati tags: , , ,

kick it on DotNetKicks.com

Please Nominate Subtext For A SourceForge Community Choice Award

Steve Harman and Phil Haack both posted a request to nominate Subtext for a SourceForge 2007 Community Choice Award.

The SourceForge.net team is proud to present our second annual Community Choice Awards. Winners are selected by community members like you, and it’s that time again! Cast a ballot for your favorite projects now and make your voice heard.

To nominate Subtext just click on the following badge:

nomProj_1

Nomination are accepted till 29th June (Pacific Time, so almost 30th June here in NZ).

I think the best categories to nominate Subtext are:

  • Most Collaborative Project: The project most likely to accept your patches and value your input
  • Best Project for Communications: The best project for talking to your friends or sharing information
  • Best Project: This is the one! The all-over best project.

If Subtext makes it to the finals, you can vote for us starting from 9th of July... but don't worry, if that happens you will see another post about that.

PS: pardon if you already subscribed my Italian blog: I posted on both blogs to make sure I reached both the Italian and English speaking audience

Technorati tags: , ,

Milan l'é semper Milan

milano Might be the fact that I'll be going back to Milano in a little more than one month, or the fact that now here in Wellington the weather is a bit cold, windy and rainy and winter-ish, but I'm becoming a bit nostalgic and starting to miss my hometown Milano (ok, I already had that feeling when I code-named a release after the suburb I grew up in Milano)

Today, looking on 02blog I found a very nice video made by Matteo G.P. Flora, a member of the UGIdotNET user group.
The title of the video is: Why I love Milan.

The picture of Milano on the top is "Duomo di Milano" by anglogean on flickr

Technorati tags:

What is a Mac doing in a Die Hard movie?

Today I just stumbled upon a trailer of the 4th episode of the Die Hard saga (Live Free or Die Hard) and it seemed to me that one of the actor was the guy that personifies the Mac in the Get a Mac Apple's campaign.

justinlong Get_a_Mac_ad_characters

A quick search on Google and I found out that this guy has a name, Justin Long, a few parts in other movies and also an official web site. And it seems that he is one of the new rising Hollywood's stars.

Technorati tags: , ,

SQL Server 2005 password complexity enforcing

Today I was installing the developer version of SQL Server 2005 on my laptop and when the wizard asked me for the SA password I entered: password.

I got a message saying that the password wasn't complex enough for the SA account.

So I entered: pass. And the wizard didn't complain.

Is pass more complex then password? I don't think so.

Technorati tags: ,

How to persist settings in a Subtext plugin

Almost one week after the Introduction to Subtext plugins, I just added to the subtextplugins website a new document: How to mange plugin settings.

This article explains the differences between the 3 types of settings available to a plugin and how to read and write them.

Here is the ToC:

  1. Introduction
  2. Settings available to the plugin
  3. How to read and write settings
    1. Application-wide settings
    2. Blog Settings
    3. Entry Settings
  4. What's next

Next article will explain how to add to the setting page inside Subtext admin a panel to collect settings from the blog author.

Technorati tags: , ,

Another mountain addicted coder blogs on Subtext

This morning, going through my weekly ego-search, and I found a blog by Simon Philip, a snowboarder and .NET developer living in Scotland.

We share a lot things: same name, passion for mountains, same job.

He moved to Subtext a week ago, and has a very nice looking skin. I love the random mountain images he has in the header of his blog: something I might add to my skin in the future.

Technorati tags: , ,

CruiseControl.NET 1.3 released

I just got the announcement about the latest release of CruiseControl.NET 1.3.

The new version is now build with NET 2.0, so it needs the NET 2.0 redistributable to run.

The main feature are:

  • support for integration queues to control build concurrency and manage dependencies between projects
  • performance improvements in the web dashboard, especially for cctray polling via http
  • ccnet has been migrated to .net 2.0 and now takes advantage of some of the features of .net 2.0 including switching the EmailPublisher to use SMTP
  • support for the Accurev SCM

For more details look at the release notes on the JIRA CC.NET server.

They also fixed a bug that was preventing XmlHttpRequest to parse correctly the Dashboard Xml API.

But the biggest new feature is the Integration Queue: now you can specify a dependency tree among the project being integrated on the build server and so preventing some project to be built concurrently. For more details on this new feature please read the docs on the official wiki.

In the next few days I'm going to test my CC.NET Monitor in order to see if the new version introduced some breaking change in the dashboard XML API.

Technorati tags: ,

Milano 11th in the list of the most expensive cities in the World

02blog_logo Just found this very nice blog about Milano (in Italian): www.02blog.it (02 is the local phone prefix).

One of the most impressive news I found is this: Milano is the 11th most expensive city in the World.

Last year Milano was at the 13th position. The most expensive city is Moscow while the only city in the top 50 from Oceania is Sidney, 21st.

The list of the top 50 is available on Mercer site: Top 50 most expensive cities in the World

Rhino Mocking NHibernate Expressions

A few days ago I wrote a post about how to test your business layer using Rhino Mocks.

Last time I set an expectation on an method that accepts a normal int. Today I'll show how to work on something more complicated: a NHibernate Expression.

Marmot exiting from hibenation

How to Mock the FindOne(ICriterion[])

I've to test a method that returns a user given its username.

   1:  public User GetByUsername(string username)
   2:  {
   3:    User returnUser =
   4:     _repository.FindOne(Expression.Eq("EmailAddress", username));
   5:    if (returnUser == null)
   6:    {
   7:      returnUser = new UnknownUser();
   8:    }
   9:    return returnUser;
  10:  }

The FindOne repository method builds a NHibernate Criteria and calls its UniqueResult method.

The test is exactly the same as the one I wrote in the previous post: the only difference is that at line 10 I set a different expectation:

Expect.Call(mockedRepository.FindOne(
  Expression.Eq("EmailAddress", "email@address.com"))
  ).Return(expectedUser);

This tells the mocked repository to expect a call to the FindOne method with the parameter Expression.Eq.

Unfortunately the Expression.Eq method returns a different Expression each time it is called, so the default reference equality performed by Rhino Mocks to understand if the call is among the ones expected will fail.

But Ayende thought about this scenario, so Rhino Mocks also provide a way to override the default behavior: Constraints.

With constrains you can ask the mock engine to accept, for example, any parameter different from null, or any number less than 10, or any string that match a certain regex pattern and many other operations on the parameters. You can even say to ignore the parameters and always match the expectation.

For example you can ask an hypothetical method that accepts a string parameter to "match" every time the string ends with ".com":

Expect.Call(mocked.testDomain("domain.com") ).Constraints(
       Text.EndsWith(".com")).Return(true);

Unfortunately none of the default constrains are helping with the NH Expression object. So I have to create my own constraint extending the AbstractConstraint.

Extending Rhino Mocks AbstractConstraint

Creating a new Constraint is pretty easy: you just inherit from AbstractConstraint and implements two methods plus the constructor:

  • constructor: it sets up the rules specific to your constraint, and is called during the setup of the expectation
  • bool Eval (object): this is the method that is called by the mocking engine to verify if the parameter is among that ones that are expected. The parameter of that method is the parameter that is passed to the call of the mocked object method.
  • string Message: this property is used when all the possible matches fail, and is printed in the debug console.

The problem here is to understand how to get from the array of Expressions something that can be used to test for equality.

Luckily a ICriterion.toString() returns a string of the type "property = value". For example:

ICriterion crit = Expression.Eq("EmailAddress", "email@address.com");
string str = crit.toString(); //EmailAddress = email@address.com

So, since I'm dealing with an array, I loop through all the elements in the array, and if one match with the expected string I return true.

public class NHSimpleExpressionConstraint:
                        AbstractConstraint
{
  private string _testStr;

  public NHSimpleExpressionConstraint(string testStr)
  {
     _testStr = testStr;
  }

  public override bool Eval(object obj)
  {
     ICriterion[] nhCriteria = obj as ICriterion[];
     if (nhCriteria.Length == 0)
        return false;
     foreach (ICriterion criterion in nhCriteria)
     {
        if(criterion.ToString().Equals(_testStr))
           return true;
     }
     return false;
  }

  public override string Message
  {
     get { return "Testing for " + _testStr; }
  }
}

Using a NHSimpleExpressionConstraint

Now that I've this new type of constraint I can use it on my mock object to verify that the Expression used in the call is the one I'm expecting.

Expect.Call(mockedRepository.FindOne(
          Expression.Eq("EmailAddress", "email@address.com"))
          ).Constraints(
          new NHSimpleExpressionConstraint("EmailAddress = email@address.com")
          ).Return(expectedUser);

The Constraint above works only with SimpleExpression (Eq, Lt, Gt, ...) not with more complex expressions. But it will be easy to extend to support also more complex expressions whose toString doesn't return a string in the format "property = value".

Technorati tags: , , ,

kick it on DotNetKicks.com

Gran Paradiso marketing material: spot the difference

800x600 gran_paradiso

Today the Firefox marketing team released some marketing material to promote the next release of Firefox 3, codename Gran Paradiso, but I think they didn't get the real meaning of the reference to Gran Paradiso.

According to Wikipedia:

"Gran Paradiso" (trans. "Great Paradise"), like other Firefox development names, is an actual place; in this case the highest mountain group in the Graian Alps. With the release of version 3.0 alpha 1 on December 8, 2006, it adopted the "Gran Paradiso" codename.

And also according to all codenames in the history of Firefox, they are all about real places or real parks (and Gran Paradiso is the name of a National park as well).

So somebody should explain that Gran Paradiso is not the name of some city in Sicily, but the name of the highest all-Italian mountain.

Actually the Gran Paradiso translates to "Big Paradise", referring to the fact that there is another small peak nearby.

UPDATE: A comment on the italian version of this same post says that they probably got the inspiration from the hotel Gran Paradiso in Ischia, an island in the gulf of Naples.

PS: the picture of the Gran Paradiso mountain depicts the North Face of it, an north face climb, 1300m of climb, D/D+, 50°-60°

How to mock a NHibernate Repository

 In my current project I'm trying to apply the best practices for building "great software" (cit.).

Beware the Rhino! by metal-dogOne of the best practices is using a (kind of) TDD approach, using Inversion of Control and Dependency Injection to test only the relevant parts of your code without testing all the layers of your applications, DB included, during each test.

Which are the benefits of this approach?

  • First of all your tests run quicker because they are not hitting the database all the times.
  • Second, you don't need to restore the initial state for the database.
  • Third, if you are working in a team with many developers, the ones that are working on the presentation layer can test their code even if the business layer or the database side of the application is not working yet.
  • Last, if your application is accessing 3rd party webservices you don't your tests to fail because of a network problem or, as it happened to me last week, if the database server dies unexpectedly.

Rhino Mocks

I decided to Ayende's Rhino Mocks to mock my layers.

At the moment I'm still in an early phase of the development, so my problem was mocking the database access layer, which is developed using a very trimmed down version of the IRepository<T> that is inside Rhino Commons.

IRepository<T> is a class that wraps NHibernate and provide a generic interface to its ISession methods.

Now let's see how to to test the Persistence Service that retrieves an User calling the IRepository<User>.

How to Mock the IRepository<T> and the Get(object) method

First I want to test the GetById method. Here a simple implementation of it:

   1:  public User GetById(int id)
   2:  {
   3:    User returnUser = _repository.Get(id);
   4:    if (returnUser == null)
   5:      {
   6:        returnUser = new UnknownUser();
   7:      }
   8:    return returnUser;
   9:  }

The Get method then calls the NH Session Get method.

And here is test that uses Rhino Mock to simulate the real IRepository<User>.

   1:  [Test]
   2:  public void CanGetUserById()
   3:  {
   4:    MockRepository mocks = new MockRepository();
   5:    IRepository<User> mockedRepository = 
   6:      mocks.CreateMock<IRepository<User>>();
   7:    User expectedUser = new User();
   8:    expectedUser.EmailAddress = "email@address.com";
   9:    expectedUser.Name = "Test User";
  10:    Expect.Call(mockedRepository.Get(666)).Return(expectedUser);
  11:    mocks.ReplayAll();
  12:    UserPersistenceService service =
  13:      new UserPersistenceService(mockedRepository);
  14:    User user = service.GetUserById(666);
  15:    Assert.AreEqual("email@address.com", user.EmailAddress);
  16:  }

Line 4: I create a new MockRepository to store all the mock object I will create and the expectations I will set on them.

Lines 5,6: I create a Mock object to mimic the behavior of our real  IRepository<User>.

Lines 7-9: I build the object what I want the mock object to return when I call the method.

Line 10: This is the most important line of the snippet. It instructs the Mock object to "Expect" a "Call" to the Get method on the mocked repository with an parameter of value 666 and, when this happens, to "Return" the object expectedUser.

Line 11: "starts" the mocked repository.

Lines 12,13: The mocked repository is "injected" inside the persistence service.

Line 14: I call the GetUserById method on the persistence service with 666 as parameter, this method calls the Get method of the repository (that is our mocked repository) which returns immediately the expectedUser without calling the real repository and hitting the DB.

Line 15: Now I can test the equality between the username of the user retrieved from the DB repository and what I expected to find.

In another post I'll write about mocking another methods of the repository, a method that accepts an array of NH Expressions. And I'll show how to extend Rhino Mock to "understand" this new type of parameter.

UPDATE: Small edit to the code of the samples after 2 suggestions from Simone Busoli.

Technorati tags: , , , ,

kick it on DotNetKicks.com

Twitter Publisher for CC.NET

Thomas Freudenberg, an active blogger and CS MVP from Germany, just released a very useful CC.NET publisher task: Twitter publisher.

I joined the Twitter band-wagon more or less one month ago, and I'm using Twitteroo to receive my "friends" notifications on the desktop, so I think it will be a good idea to receive a notification every time a build is triggered on the Subtext build server.

I downloaded the publisher, installed it on Subtext build server, added 2 lines of configuration in the ccnet.config file and in 5 minutes I had the twitter publisher up and running.

After you change the config file remember to restart CC.NET to load the new build publishing task.

Here it is a new build notification on my Twitteroo client:

twitter_publisher

And on Subtext build twitter page you can see the list of all the builds, or add subtextbuild to the list of your Twitter "friends".

twitter_webnotification

How to write your first SubText plugin

Less then a week after the official announcement of the SubtextPlugins website, today I added the first tutorial on writing a Subtext Plugin.

The first document covers the basics of building a Subtext plugin.

This the TOC of the article:

  1. Introduction to Subtext Plugins
  2. How to develop a plugin for Subtext
    1. Download and install the latest Subtext v2.0
    2. Create a new VS project
    3. Extend PluginBase
    4. Add Plugin information with attributes
    5. Handle events
    6. Install the Plugin
    7. Enable the Plugin
    8. Test the Plugin
  3. What's next

In next document I'll write about building a more advanced plugin, that uses the plugin API to store and read blog and entry specific settings.

Technorati tags: , ,

What convinced me to adopt a (kind of) Test Driven Design approach

I've to admit it: I never wrote many tests for the code I wrote. Probably one of the reason is that the last time I wrote something from scratch, with enough time to convince the other members of the team to try a new approach, was before the TDD became known to the general audience. I only wrote some test for small part of the code, or to expose some bugs and later fix them.

But 2 months ago, I had to design from scratch a small web application: and again I didn't have the time to sit down, look around and try a TDD approach for it. So I ended up writing my Data Access Layer, my Business Layer and testing them trying them out with a console application that acted as a client for the DAL and the BL.

But while writing in my console application the code to call the DAL, I noticed that it was the same code that I would have written inside a unit test. The difference is that you cannot check automatically if the console application behave correctly, but you have to do it manually, stepping thorough the code and checking if the database is populated with the correct data. 

That was a small project so I went on with the console application approach, but I promised that my next project would have been developed using the TDD approach.

Two weeks ago I started a new project, and I decided to use this approach: I write my DAL and, instead of trying it with some code that will be thrown away, I test the functionalities inside a unit test. And it's even easier to work with because you can choose which test to run, you can have a coverage report on your library and, if the application is well designed, you can even test the UI or the Business Logic without hitting the database, using some mocking library.

So, if you want to find a practical reason to start writing unit tests think about this:

If you write any library (a DAL, some Business Logic, some general purpose utilities), you have to try it somehow. And to do it you have to write some code just for testing: so why don't you put the same code inside a unit testing project? With the same effort you will have "best-practice" testing procedure to improve a lot the quality of your code.

This was the motivation that worked for me. I hope it will convince also other people to write more tests for their code.

Technorati tags: ,

kick it on DotNetKicks.com

Apple announces... Safari for Windows

Among the other announcements at the WWDC (and a new slightly different graphics for their site), the most unexpected one was about the release of the new version of Safari for Windows: claimed to render HTML 2 times faster than any other browser, for sure will make life easier for web developer that have to test their work on Safari (even if probably now web developer are already running on OS X).

Here are some screenshots:

installing_safari

Installing Safari

safari_icon 
Safari icon on Windows

safari_about 
Safari about window:
running over my CCNET Monitor gadget

codeclimber_on_safari 
CodeClimber running on Safari on Vista

My wife has a Mac and she is running Firefox, and a lot of other people I know say that Safari for Mac is not as good as Firefox. But maybe version 3 is better. Only time will tell.

Scott Hanselman blogged his first impressions about Safari on Windows: I agree that they could have used ClearType instead of reinventing a new font smoothing system on Windows.

Technorati tags: , ,

Subtext Plugin Framework aka Red Moon: web site is online

One month ago a new Red Moon was rising...

Red Moon is the codename for one of the most important new feature in Subtext "Poseidon": Plugin Framework.

Today the official web site went online: subtextplugins.com

At the moment there are not many information on the site, but I'm planning to add some docs in the next week.

Just a quick overview on the Plugin Framework:

  • the plugin model is event based like HttpModules and Community Server plugins
  • plugin can store their own settings on the DB, both for a per-blog and per-entry basis
  • for the first release, plugins must be added by the "webmaster", placing the dlls in the \bin folder and adding some configuration in the web.config file
Technorati tags: , ,

The Friday's drinks taken to the next level

Seems like Connected Ventures, the company behind Vimeo, CollegeHumor, Busted Tees, and Defunker is taking the Friday's afternoon to the next level.

Here is what they produced...


Lip Dub - Flagpole Sitta by Harvey Danger from amandalynferri on Vimeo

Rss2BlogML: export any RSS feed to a BlogML file

BlogML is an XML format for storing the entire content of a blog. You can use BlogML as a way to archive the contents of blogs or to act as a standard format for transferring content from one blog to another - this could include migrating a blog from one blogging engine to another.

To create a BlogML archive, you must:

  1. have a blog engine that can export to BlogML, as core feature or with an external plugin
  2. the latest version of your blogging engine or the export plugin must be installed on your server

If your blog doesn't comply with the 2 requirements above you cannot export to BlogML.

At the moment BlogML is supported only by:

  • Community Server
  • DasBlog
  • Subtext
  • SingleUserBlog
  • Windows Live Space
  • WordPress
  • Blogger

rss2blog-logo Last week a friend of mine asked if I knew a way to move all his posts from his current blog (hosted on .Text on a server where he doesn't have access on) to Subtext. At first I said that he was stuck on his hold blog, but seemed to me an unfair answer, so I decided to help him and I started working on a tool that can take any RSS feed, and convert it to BlogML: Rss2BlogML was born.

Rss2BlogML is desktop tool that downloads any RSS feed, downloads the comment RSS (if provided), and then put everything inside the BlogML archive.

Since it's very rare that a blog engine can give you all the post in just one single feed, Rss2Blog allow you to specify many RSS feeds to download and merge: during this process you can also specify one (or more) feed per category just in case your blogging engine doesn't embed categories information inside the main feed.

rss2blogml-mainHere you can see the main window of Rss2BlogML:

you can enter any number of RSS feed, and you can specify the category of the posts contained in the feed. And you can also check the "main feed" flag to use the feed as the one that contains the information about the blog (like title, description, author).

On the right bottom corner of the grid there is a drop-down list with the RSS dialects supported and you can choose from to generate the BlogML archive.

At the moment I tested only with .Text and with the core blog module of DNN, but if you want to import RSS generated by other blog engines you can implement your own RssMapper and add it to the supported "dialects".

Unfortunately the RSS feed doesn't contain all the information need for a complete export of your posts (for example it doesn't contain the number of views, or the trackbacks received, or the extended attributes of some blog engines), but at least allow you to backup your posts and comments, which are the most important contents in a blog.

Technorati tags: , , ,

Kalymnos - Climbing in... Paradise?

Last September I spent a week climbing in the beautiful island of Kalymnos, Aegean Sea, in Greece.
And last month I wrote an article about my rock-climbing experience in this "climbing paradise" for the May 07 edition of Vertigo, the monthly e-zine of the Wellington Section of the New Zealand Alpine Club.

Read the article...

How to use the command line CodePlex Client

CodePlex screwdriver In the last days I've been working on a small tool that will be included inside BlogML, but I didn't want to install the Team Explorer since it's quite a big download for just a source control client (246Mb).

So, while I wait June 18th for the deploy of the bridge that will allow access to CodePlex using any SVN client as TortoiseSVN, I decided to go the hard way and install the standalone command line tool: the CodePlexClient.

Being a command line is a bit more complex to run, so here is quick step by step tutorial on how to install and use it.

1 - Installation

  • Download the CodePlex Client June 2007 release
  • Unizip the contents of the file in a directory of your choice
  • to speed up later usage of the client add the folder you just created to the PATH enviromental variable

To test if everything is installed correctly, just open a command prompt and type:

cpc listprojects codeplexname

This command will list all the projects you have commit right for.

2 - First usage

The first time you use the client you have to get all the souce for the project you are working on: open a command prompt, cd to the folder you want the source repository to be and type:

cpc checkout MyProjectName

3 - Add, Edit and Delete files

Unlike Team Foundation, the CodePlex Client works in "edit-merge-commit" mode, like SVN: so change your files, edit, delete or add them without first checking them out.

When you are ready to commit the changes to the server, you can do it in 3 different ways:

Manually schedule all the files for add and delete

cpc add filename
cpc delete filename

Status command

this will open a TortoiseSVN like window, with the list of all the files that changed status since you last updated the repository.
Left-clicking on each file name you can schedule it for add, delete or you can revert to the original version of the file:

cpc status /gui

status

Syncup command

that will automatically schedule for delete all the files that have been deleted, will run an update (and also merging with the changes found on the server), and finally schedule for add all the new files that it finds in the folder. For this command to work correctly you have to configure the ignore file (described later) in order to add only the files needed for the repository, and not, for example, the bin folder:

cpc syncup

4 - Commit

To commit the changes made and scheduled in step 3, just type the following command:

cpc commit /gui

This will open up a window where you can add your commit comment

commit

These are the basic commands to work with the CodePlex Client. For a list and explanation of all the commands look on CodePlex help. You will also find how to use the new feature introduced with the June release: create patch and accept patches commands.

5 - Configuration

To speed up the work with the cpc client you can set a few configurations option inside the cpc.exe.config file.

Instead of typing /gui everytime you can default the status and the commit commands to open the gui window. Add the following lines in the cpc.exe.config:

<add key='DefaultToGuiForCommit' value='true'/>
<add key='DefaultToGuiForStatus' value='true'/>

As we said in step 3, you can add an ignore file to exclude from all the operations certain files:

<add key='IgnoreFile' value='_tfs-ignore'/>

Then create a file named _tfs-ignore in the root of the local repository and add the following content:

<ignore xmlns='http://www.codeplex.com/schema/IgnoreListSchema-1.0.xsd'>
  <add recursive='true'>bin</add>
  <add recursive='true'>obj</add>
  <add recursive='true'>_Resharper*</add>
  <add recursive='true'>*.resharper</add>
  <add recursive='true'>*.suo</add>
  <add recursive='true'>*.user</add>
  <add>*.xml</add>
</ignore>

This is the sample ignore file suggested by the CodePlex team.

You can also add other configuration options to set up the text editor, the merge and diff tools: more info on these options on the codeplex client wiki.

Technorati tags: ,

kick it on DotNetKicks.com

Twittering

I joined twitter a few weeks ago, after Steve asked me if I was on Twitter.

But I was a bit reluctant posting this on my blog because I didn't get the point of reading what others are doing, or saying to my list of followers what I was doing at any give moment.

Not that now I get it completely, but more than I did when I signed up a few weeks ago smile_regular

What is Twitter?

Someone (don't remember who, sorry for the anonymous citation) said that twitter is what you do between a blog post and another.

Someone else says it's like a chat, but much better. Jeff Atwood calls it the combination of blogging and IM.

I'd say, if a blog post is like sending an email cc'ed to the World, sending a twitter update is like sending an IM to the World or, as Steve suggested, like sending an IM status update to the World.

There are various way to interact with twitter:

  • you can do it with your mobile phone, sending and receiving updates as SMS (or TXT as they call them in NZ)
  • you can sent and receive updates using your favorite IM client
  • you can use the web UI and the RSS feed of your list of friend
  • or you can a desktop client like Twitteroo

Now, if I'm wondering why Phil is taking so long to answer the email I can just look at the list of his events and see he is "playing soccer and watching a polo game", or I can see random thoughts of the people in my list.

So, if you want to know what I'm doing right now, just go to my personal twitter page twitter.com/simonech, and you might even want to add me as friend in order to get my thoughts and "status updates" delivered as soon as I post them.

 

Technorati tags: , ,