Cleaning up a folder structure from Visual Studio artifacts from the shell

A few years ago I wrote a post that showed how to write a NAnt script to clean a folder structure from the artifact’s folders used by Visual Studio.

Today what I wanted to show you is a way that doesn’t require NAnt installed on your computer, but that uses just a very simple command for Windows’ shell.

Actually, it’s just a very tiny variation of the same command that Jon Galloway wrote to clean a folder structure from SVN files.

But without further ado, here it is:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN] @="Delete SVN Folders"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN\command]
@="cmd.exe /c \"TITLE Removing SVN Folders in %1 && COLOR 9A && FOR /r \"%1\" %%f IN (.svn) DO RD /s /q \"%%f\" \""

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteBinObj]
@="Delete Visual Studio Artifact Folders"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteBinObj\command]
@="cmd.exe /c \"TITLE Removing BIN and OBJ Folders in %1 && COLOR 9A && FOR /r \"%1\" %%f IN (bin obj) DO RD /s /q \"%%f\" \""

To install it, all you have to do is copy the text above into a txt file, rename it to .reg and double click on it. And after that you will have two new commands that will appear in the right-click menu in Windows Explorer.

Menu

HTH

Technorati Tags: ,
 

Lucene.net is powering Subtext 2.5 search

Back in August and September I started a series with the main concepts of Lucene.net and I started to explain the design behind the forthcoming Lucene.net-powered search engine for Subtext. In the last few months I finally had the time to sit down and implement the search engine for Subtext.

In this post I want to show you how I implemented it and since I kept the points of contact with the Subtext domain model to the minimum, how you can modify it to use it in your own application.

Another reason behind this post is… asking to long time Lucene users for comments on the implementation. So comments will be welcome.

Let’s review how it is implemented starting from the main class, SearchEngineService, which contains all the Lucene.net logic.

The Search Engine Service

Starting from the constructor

public SearchEngineService(Directory directory,
        Analyzer analyzer,
        FullTextSearchEngineSettings settings)
{
    _directory = directory;
    _analyzer = analyzer;
    _settings = settings;
}

As you can notice it is not a singleton, even if it should be because there can be only one Writer that is writing to the index. To achieve the single instance status we are using our IoC Container, Ninject. The registration of the service in the container is as follows

Bind<Directory>()
    .ToMethod(c => FSDirectory.Open(new DirectoryInfo(
        c.Kernel.Get<HttpContext>().Server.MapPath("~/App_Data"))))
    .InSingletonScope();
Bind<Analyzer>().To<SnowballAnalyzer>().InSingletonScope()
    .WithConstructorArgument("name",
        c => c.Kernel.Get<FullTextSearchEngineSettings>().Language)
    .WithConstructorArgument("stopWords",
        c => c.Kernel.Get<FullTextSearchEngineSettings>().StopWordsArray);

Bind<ISearchEngineService>().To<SearchEngineService>().InSingletonScope();

What the constructor does is simply setting all the dependencies.

The creation of the Writer

We are deferring the creation of the index writer till the first time it really needs to be used, and it is done from inside the EnsureIndexWriter method. This method is always called from inside a lock as we want to avoid threading issue. Otherwise we might have two different requests trying to create an index writer at the same time, and this is bad as there can only be one index writer per index. This is done because of a small issue with Ninject that, either because of a bug or because how we use it, created the service twice even if it was registered as InSingletonScope.

The EnsureIndexWriter is called before any method that needs a writer to exists, which must be called through the DoWriterAction<T> method.

private T DoWriterAction<T>(Func<IndexWriter,T> action)
{
    lock (WriterLock)
    {
        EnsureIndexWriter();
    }
    return action(_writer);
}

// Method should only be called from within a lock.
void EnsureIndexWriter()
{
    if(_writer == null)
    {
        if(IndexWriter.IsLocked(_directory))
        {
            Log.Error("Something left a lock in the index folder: deleting it");
            IndexWriter.Unlock(_directory);
            Log.Info("Lock Deleted... can proceed");
        }
        _writer = new IndexWriter(_directory, _analyzer,
                        IndexWriter.MaxFieldLength.UNLIMITED);
        _writer.SetMergePolicy(new LogDocMergePolicy(_writer));
        _writer.SetMergeFactor(5);
    }
}

During the creation I also check for a possible lock on the index file (if the application ends abruptly sometimes the lock file is not deleted) and set a custom merge policy based on the number of documents instead of the size in bytes.

Adding documents

Adding a document to the index is a pretty simple operation:

  • I delete any previous document with the same document id (line 6)
  • I add the document to the index (line 10)
  • When I’m done with all the posts I commit the writes (line 19)
  • Finally, if done through a mass indexing, I optimize the index (line 22)
   1:  public IEnumerable<IndexingError> AddPosts(IEnumerable<SearchEngineEntry> posts, bool optimize)
   2:  {
   3:      IList<IndexingError> errors = new List<IndexingError>();
   4:      foreach (var post in posts)
   5:      {
   6:          ExecuteRemovePost(post.EntryId);
   7:          try
   8:          {
   9:              var currentPost = post;
  10:              DoWriterAction(writer => writer.AddDocument(CreateDocument(currentPost)));
  11:          }
  12:          catch(Exception ex)
  13:          {
  14:              errors.Add(new IndexingError(post, ex));
  15:          }
  16:      }
  17:      DoWriterAction(writer =>
  18:      {
  19:          writer.Commit();
  20:          if(optimize)
  21:          {
  22:              writer.Optimize();
  23:          }
  24:      });
  25:      return errors;
  26:  }

The CreateDocument is just an utility method that creates fields for the Lucene document.

As you notice, all the operation that require a Writer are called through the DoWriterAction method.

Performing Queries

We have two different types of queries in Subtext: the normal full-text query and the similarity query. They both rely on the same PerformQuery method.

private IEnumerable<SearchEngineResult> PerformQuery(
        ICollection<SearchEngineResult> list,
        Query queryOrig, int max, int blogId, int idToFilter)
{
    Query isPublishedQuery = new TermQuery(new Term(Published, true.ToString()));
    Query isCorrectBlogQuery = GetBlogIdSearchQuery(blogId);
    
    var query = new BooleanQuery();
    query.Add(isPublishedQuery, BooleanClause.Occur.MUST);
    query.Add(queryOrig, BooleanClause.Occur.MUST);
    query.Add(isCorrectBlogQuery, BooleanClause.Occur.MUST);
    IndexSearcher searcher = Searcher;
    TopDocs hits = searcher.Search(query, max);
    int length = hits.scoreDocs.Length;
    int resultsAdded = 0;
    float minScore = _settings.MinimumScore;
    float scoreNorm = 1.0f / hits.GetMaxScore(); 
    for (int i = 0; i < length && resultsAdded < max; i++)
    {
        float score = hits.scoreDocs[i].score * scoreNorm;
        SearchEngineResult result = CreateSearchResult(searcher.Doc(hits.scoreDocs[i].doc), score);
        if (idToFilter != result.EntryId
             && result.Score > minScore
             && result.PublishDate < DateTime.Now)
        {
            list.Add(result);
            resultsAdded++;
        }
            
    }
    return list;
}

This method receives the main query as parameter and enriches it by adding more clauses: publish status and the blog id.

The method then does the search on the index and for each result returned it computes the score and filters out posts under a certain score and those that are published in the future.

Normal full-text search

To perform the simple search, the term entered by the user must be duplicated to be searched in all the textual fields: title, body and tags.

public IEnumerable<SearchEngineResult> Search(string queryString, int max, int blogId, int entryId)
{
    var list = new List<SearchEngineResult>();
    if (String.IsNullOrEmpty(queryString)) return list;
    QueryParser parser = BuildQueryParser();
    Query bodyQuery = parser.Parse(queryString);

    
    string queryStringMerged = String.Format("({0}) OR ({1}) OR ({2})",
                               bodyQuery,
                               bodyQuery.ToString().Replace("Body", "Title"),
                               bodyQuery.ToString().Replace("Body", "Tags"));

    Query query = parser.Parse(queryStringMerged);
    

    return PerformQuery(list, query, max, blogId, entryId);
}

Similarity (more like this)

This other kind of search is a bit more complicate, and makes use of the similarity search that is available in the contrib package.

public IEnumerable<SearchEngineResult> RelatedContents(int entryId, int max, int blogId)
{
    var list = new List<SearchEngineResult>();

    //First look for the original doc
    Query query = GetIdSearchQuery(entryId);
    TopDocs hits = Searcher.Search(query, max);

    if(hits.scoreDocs.Length <= 0) 
    {
        return list;
    }

    int docNum = hits.scoreDocs[0].doc;

    //Setup MoreLikeThis searcher
    var reader = DoWriterAction(w => w.GetReader());
    var mlt = new MoreLikeThis(reader);
    mlt.SetAnalyzer(_analyzer);
    mlt.SetFieldNames(new[] { Title, Body, Tags });
    mlt.SetMinDocFreq(_settings.Parameters.MinimumDocumentFrequency);
    mlt.SetMinTermFreq(_settings.Parameters.MinimumTermFrequency);
    mlt.SetBoost(_settings.Parameters.MoreLikeThisBoost);

    var moreResultsQuery = mlt.Like(docNum);
    return PerformQuery(list, moreResultsQuery, max+1, blogId, entryId);
}

Disposing the service

Since Lucene makes use of external resources in the filesystem and it’s super-important to close all the resources used before disposing the service.

~SearchEngineService(){
    Dispose();
}

public void Dispose()
{
    lock(WriterLock)
    {
        if(!_disposed)
        {
            //Never checking for disposing = true because there are
            //no managed resources to dispose

            var writer = _writer;

            if(writer != null)
            {
                try
                {
                    writer.Close();
                }
                catch(ObjectDisposedException e)
                {
                   Log.Error("Exception while disposing SearchEngineService", e); 
                }
                _writer = null;
            }

            var directory = _directory;
            if(directory != null)
            {
                try
                {
                    directory.Close();
                }
                catch(ObjectDisposedException e)
                {
                    Log.Error("Exception while disposing SearchEngineService", e);
                }
            }

            _disposed = true;
        }
    }
    GC.SuppressFinalize(this);
}

The Indexing Service and the UI components

This post grew over the size I was planning, and I still haven’t talked about the other components of the search engine feature of Subtext. I’ll talk about them in a future post.

If you want to start having a look at the code, you can either get the source or just browse the code online.

Please, review this code

One of the reasons behind this post was also asking to people that used Lucene.net a few comments about our implementation. So, please, comments are welcome. Thank you

 

Where I'll be during the MVP Summit

And finally the Summit has arrived: on Monday I'm leaving from Milano (at 6:50am, which means waking up at 3:00am) and I'll arriving in Bellevue on Monday afternoon. I'll be staying at the Hyatt Regency Bellevue.

It will be a pretty packed up week, with sessions all the days, and parties all the nights. This is my "tentative" schedule for the parties.

I'll then spend the Saturday visiting around and then I'll fly back to Milano on Sunday morning (arriving in Milano on Monday morning).

I'm pretty excited of all this, mainly because I'll have to chance to meet in person most of the guys (and gals) I interact on twitter and via the various OSS project mailing lists.

See you there.

 

So Long Avanade, and Thanks for All the Fish

If you follow me on twitter you might already have understood something: last week I gave my two months notice to my employer, Avanade Italy. I've been working with them since the end of 2007, and during the almost 2 years and half I learned a lot. Especially I added to my skills-set some competencies I never had the chance to practice working for a web agency and for a product company: the so called consulting skills. I also had the great opportunity to coach on the job some junior developer that just come out from university (or with little experience): some were more receptive, other less, but at the end I hope they learnt some of the principles of good coding and software design.

And also worked with many great colleagues, some which I’m really going to miss.

So, why am I leaving?

Avanade is a great company, so why am I leaving?

  • Web Development - In Avanade one thing was really lacking: some real web development. I'm a web developer at heart, and in Italy all of the "real" web development (where with real I mean big B2C websites or big online magazine/newspaper) is developed by web agencies like the one I worked before going to NZ.
  • Product expert vs software developer - It seems like all the big consulting companies are trying to sell solutions based on products that require very little to almost no development work: like SharePoint, CRM, BizTalk, Commerce Server and so on. I’m not interested in becoming an expert on customizing a specific product: I’m more interested in “custom development” and in the way people work together.
  • Italy is getting worse and worse every day - Italy is a mess: it might have great natural and historical places but if you are not a tourist Italy is not a good place to live.
  • No “my office” - And the last reason is that the working condition of the consulting industry are really bad: 90% of your time is spent at the customer site, working a small 15” laptops, sitting in temporary places, with just enough space to fit your laptop and move the mouse. And I really miss a place I can call “my office”.

And where am I going?

I think you might have heard of my new employer: it’s called the European Union, and specifically I’ll be working in at the Council of the European Union.

Avanade-To-EU

I applied to the open competition for becoming an EU official in the field of IT when I was still in New Zealand, in summer 2007. It took one year and half to pass all the stages of the competition, and then one year for someone to pick me up from the pool of possible employees. Starting from the the 1st of April, I’ll join the IT department as Team Lead and Architect of the team that is building all the public facing web sites of the Council… and as you have probably seen yourself, there is lot of work to do.

So, after more then 3 years I’ll work on public websites again. And my first task will be moving the team away from the VSS Hell and trying to steer it to a more Agile way of developing software.

Moving away from Italy

But I’m not only changing job, I’m also changing country: I’m going to live in Brussels, Belgium.

Unlike 3 years ago, I’m not going abroad because I want to live in that specific country, but because I want to go away from Italy: I already know I’ll miss the Alps, the lakes, but, as I said before, living here is becoming very difficult. So I’ll consider myself in self-exile and I’ll come back to Italy if/when things get better.

And, if you were wondering, I’m moving with my wife Daniela, which resigned as well, and will look for a job as UX in Belgium after she learn some French.

What changes in my development community involvement?

A nice thing about Belgium is that there is a vibrant development community, both in the .NET space and in the opensource space. I already know some developers from Belgium, like Ivan which I met in New Zealand, and some other MVPs I know through blogs and twitter. And I’ll try to know more of them at the upcoming MVP Summit in two week.

And also being in the middle of Europe, it means it will be easier to go to all the conferences held in London, Amsterdam and in Scandinavia.

But I’ll also keep on working together with Emanuele and Claudio to organize the future editions of the Italian ALT.NET Conference.

PS: Since many people are asking: “So Long, and Thanks for All the Fish” is the title of a book from the  Hitchhiker's Guide to the Galaxy series written by Douglas Adams. But also a geeky way to say goodbye with an hidden meaning.

PPS: If you know Italian, there is also a similar announcement on my Italian blog: Self-Exile.

 

When will WebForm vs MVC become like ListView vs Repeater?

Lately I’ve been reading again lot of discussions going on about whether WebForm is a much wiser choice for developers, if it will die in favor of ASP.NET MVC, or how much ASP.NET MVC brings productivity away because it forces you to learn another framework or because it makes you think more about pattern, or name-your-other-rather-random-opinion.

Even if I wrote a book about ASP.NET MVC, I’ve to say I’m getting pretty bored about this discussions: like it or not many big companies cannot afford to rebuild their whole web applications on ASP.NET MVC, even if they want the TDD experience or the fine control over HTML markup. The only possible outcome is that projects will be a mix of both WebForms and ASP.NET MVC: probably it has been marketed in the wrong way by Microsoft itself (you remember the “4 pillars of ASP.NET”?), or probably it was the only way to do it at the time since ASP.NET MVC and Dynamic Data came out as OOB release and as part of a Service Pack.

But with the forthcoming ASP.NET 4 and probably even more in the next version (either they call it 4.5 or 5) we are starting to see a lot of cross pollination between the 3 UI frameworks:

  • ASP.NET WebForms gained a lot of the good things that were born with ASP.NET MVC: routing, cleaner html, cleaner client id, less ViewState, SEO specific APIs. And you can easily put a Dynamic Data control inside a WebForm.
  • ASP.NET MVC got the Templated Helpers, model validation, inspired by Dynamic Data. And it already got MasterPages and some of the good things of WebForms

And probably we will see even more for ASP.NET vNext; to the point that in 2 years we’ll probably decide whether to use ASP.NET MVC or WebForm in the same way we had to decide between a ListView and a Repeater back in the ASP.NET 2.0 days.

UPDATE: Just noticed that Jimmy Bogard wrote a similar post: My picture of an MVC-WebForms marriage.

 

Looking back at 2009, and looking forward at 2010

I know it’s already 13 days into the new year, but a year cannot start without the usual  retrospective on the year that just ended and with the resolutions for the year that is coming.

Who did 2009 go

Let’s start with evaluating how 2009 go and let’s see if it went as I hoped at the beginning of last year. I already did 2 intermediate checkpoints, one at the end of Q1 and one in mid Summer.

  • Personal Resolutions:
    • Go Back Climbing - I climbed during Q2, but then when we came back from our summer holidays in Hokkaido we didn’t go climbing any more. Overall I did a bit of climbing, but not as much as I wanted to. NEUTRAL
    • Take Part in one Triathlon Competition - part of the reason why I didn’t climb a lot after summer is because I trained for a triathlon. Actually I even did two of them, one at the beginning of September in Locarno, Switzerland and one at the end of September, in Alba. I didn’t finish in last position, but around the middle of the ranking, which is not bad since I train when I can, and don’t follow a strict planning. My best part is the cycling one, and I’m really bad at running. GOOD
  • Blogging and community involvement Resolutions:
  • Technology Resolutions:
    • Enhance my .NET skills – I planned to study more jQuery, more Linq, more Expression tree and IoC. At the end of the year I didn’t studied anything about the Expression tree and Linq (but now I can do it with the help of Justin Etheredge and his Mastering Linq series on TekPub), but I worked a bit on WCF and lately I’m playing with NHibernate (that even if used it 2 years ago I had to “relearn” it) and FluentNH. GOOD
    • Start developing for Mac/iPhone – I did a prototype of a e-banking application for Avanade in the first months of 2009: enough to see that developing on the iPhone is great for the usability stand point, but a bit strange and complicate from the coding stand point (Objective-C is a bit weird). GOOD
  • Unplanned:
    • UserGroup Meetings – I organized 2 UGIALT.NET events, I spoke at 3 different UserGroup meeting, and I attended the StackOverflow DevDays in London.
    • ASP.NET MVC Book - the book took longer then expected and was available in stores only in August. Also, a free refcard has been published in September.
    • Trip to Hokkaido – I didn’t expect I would have gone to Japan, but at the end we did it, and Hokkaido is a great place. I really like Japan.
    • Cross-Country Skiing: I already started xc-skiing in 2008, but only in December, when I bought a new set of skating ski I really got fond of XC-Skiing.

So, just 1 FAIL, 3 GOOD and 4 NEUTRAL. 2009 didn’t went great, but at least aligned with my expectations after all.

My resolutions for 2010

This year I want to reiterate the experiment: I think it helped me evaluate how the year was going and helped keep me focused with what I planned to do.

  • Personal Resolutions
    • Climbing - Last year I didn’t climb as much as I wanted (even if more than the year before): in 2010 I’d try climb a bit more.
    • Triathlon - Last year I really enjoyed doing triathlons, lots of nice people at the races. And I think it’s also a good way to stay fit: know, running,cycling and swimming. I don’t want to get too mad about this, but doing the Locarno race again and maybe another one would be great. And I’ve to focus more on the running leg of the race since my current 5 min/km (8:03 min/mile) takes me to the bottom of the run leg ranking.
    • XC-Skiing – I just started using the skating technique, and I hope I can go XC-Skiing more and acquire a bit more of technique (and hopefully stamina) before the end of this skiing season.
  • Blogging and community involvement Resolutions:
    • Redesign my blog – number one priority is finalizing my new blog design before it becomes outdated. Daniela was very proactive and last year she designed it following the 2010 design trends, but not sure if they will last till 2012.
    • Write an eBook – Last year I helped publish one, but this year I’d like to publish one myself: maybe about ASP.NET MVC v2 or about Lucene.net
    • Be more constant in my blogging – Even if I published a good number of technical post, in 2009 I was not very constant: I had prolific periods followed by one month or more of less technical blogging. This year I’d like to be more constant.
    • Make a better blog - Last year I bought the book 31 Days to Build a Better Blog, I read it, followed some of its advices, but never stuck to a plan. (BTW, if you are interested, if you buy the book by Tuesday 19th you get 3 cool bonus)
    • Subtext – One of the reason I started working on Subtext 5 years ago is because I wanted plugins: two years ago we kind of added them, but then something bad happened, we had to revert back, and we lost everything: next year I want to add plugin support to Subtext.
    • Produce more content in Italian – Last year I did only 3 screencasts, but Italian people don’t like reading in English, so I should try harder and helping them.
  • Technology/Work Resolutions:
    • JavaScript/jQuery/CSS – I used to be quite good at these when I worked in my first job in a web agency, but since I moved to New Zealand and then to Avanade I’m not doing any real web development any more. I’d love to work more in the client side of web site
    • HTML5 – Find the time to experiment with HTML5 and all its new API and elements.
    • Work on public B2C web sites – This doesn’t really depend on me, but more on the kind of projects my company finds on the market,  but I’d love to work on a project where the problems of the client side (good javascript, client side optimization, performances) are as important as the backend ones.
    • NHibernate – I used it 2 year and half ago, but then I stopped using it when I moved to Avanade. In my latest project I started to use it again, and in the next year I’d love to get deeper into it.
    • Be an agent of change in my team – I’m a strong believer of quality vs the “do it quickly” approach, of agile methodologies and “craftsmanship”. I’d like to introduce this way of thinking into my team as well.

Is this too much for just one year? I guess it’s not. We’ll see at the beginning of April when I’ll do my first update on how my plans for 2010 are going.

[Ilanaaq, the inukshuk by Tim on Flickr]

 

Tortoise SVN tip: Repair move

Did you ever rename a file from inside Visual Studio? Did you ever move a file from one folder to another from inside Visual Studio? I think you did.

And what happened when you tried to commit your changes to a SVN repository with Tortoise SVN?

You probably got this:

Tortoise doesn't recognize the two files as one

Here I moved a file named MonitoringControllerTest.cs file from the root to the Controller folder: Tortoise SVN didn’t recognize the file as just moved, but instead it found a new file in the Controller folder, and a missing file in the root folder.

If you want Tortoise to understand “moves” you have to do it from the File Explorer, dragging the file to the destination folder with the secondary mouse button while holding the Shift key. But this is annoying because you always have to move back and forth between Visual Studio and Explorer.

A few days ago I found this feature, maybe I was the only one in the world not aware of it: Repair Move.

If, from inside the commit dialog, you select the two files that are supposed to be the same, and right click on them, you will find this new menu command: Repair Move.

Repair Move command in the contextual menu

When you click on it, Tortoise SVN will recognize the two files as a move operation instead of a new file and a delete, and the commit dialog will show it in the way it shows moved files (a delete and an added +).

Risultato

The same command also fixes rename operations.

I don’t know since how long this feature is available, but if I had found it out before, this would have saved me quite a few time.

Another option would have been adding something like VisualSVN or AnkhSVN that will automatically marks moves (together with a lot of other things). But I don’t like the integrated SVN clients.

 

Public Service Announcement: email not working (or why Aruba sucks)

UPDATE: My DNS have now been updated, email seems to be working fine, also from Exchange servers, sorry again for any problem that might have caused.

If you sent me an email in the last days and you got an error back, please try it again now in a few day, or contact me on twitter @simonech. Same problem happened if you contacted my through the contact page of my blog.

Also, if you are sending emails through an Exchange server (like if you are from Microsoft) you probably got a similar DNS error since the beginning of December: I'm really sorry for this and please sent the me your email again, and I'll try to answer it immediately.

If you are interested in why that all happened continue reading...

Why that all happened

During last autumn I decided I would have discontinued my WebHost4Life account

to moved everything to Linked Labs: websites, blogs and DNS. And I also decided to move all the domain registrations I had shattered around various registrars and hosters to the same one, the one I already used to register my .it domains: Aruba.

I thought that moving sites was difficult, but transferring a domain to another host is even more: the biggest problem is when you cannot afford to have a single moment without having the correct DNS records for your domain, especially for your email service to keep on working.

I had to contact Aruba via a support ticket to ask them to pre-configure the DNS with my records, because they change the authoritative NS to they own (instead of keeping the old ones) and they don't let you do it yourself before the domain has been successfully transferred to them. They probably screwed something up, and I was not able to receive emails from people sending from Exchange.

I discovered this problem just before Christmas, and yesterday, when I finally had time to sit down and try to fix the problem I asked them to move the authoritative NS to the one of Linked Labs, which is holding all my other DNS records. The problem is that they immediately deleted all my DNS records on their servers (piyosailing.com is not working either). This wouldn't have been a problem if the NS change was done automatically upon the request from the admin tool. Unfortunately for me it seems like NS changes have to be manually approved. So, as result, I'm without email for the weekend because, obviously, their support team is not working on weekends.

I hope everything goes back to normal in few days. Sorry for the problems

Tags: ,,
 

Best of 2009: the 5 most popular posts

The end of the year is approaching and it’s time for a recap on what happened during the last 12 months. As I did in 2008 I blogged a lot about ASP.NET MVC (around 40 posts) and few about jQuery (just 6 posts), but unlike last year where the most popular posts were about jQuery, this year it’s all ASP.NET MVC. Probably that’s because the technology is more mature than it was during 2008.

The most popular posts of 2009

1. 13 ASP.NET MVC extensibility points you have to know – This post goes through all the extensibility points that are important to understand if you want to fully exploit the ASP.NET MVC framework

2. 12 ASP.NET MVC Best Practices – A list of some best practices for developing good asp.net mvc applications. This is the content of a presentation I held in October at the Gladiator Fest in Rome.

3. How to create a DropDownList with ASP.NET MVC – Building a dropdown list in ASP.NET MVC requires a different approach from what you were used with WebForms, but also differs from the other HtmlHelpers: this post explains how to use the DropDownList HtmlHelper

4. How to use Ninject with ASP.NET MVC – Ninject comes with a sister project that helps registering controllers inside Ninject’s Kernel: this post is the first of series of 5 posts that explain how to use Ninject inside ASP.NET MVC. This post was about Ninject v1. Later in the year I also wrote a post about Ninject v2.

5. How to improve the performance of ASP.NET MVC web applications – This was written in response to another post that showed how to improve the performance of ASP.NET MVC applications. My point was: caching data is the best performance optimization you can do.

Looking at the posts from 6-10 there are other 3 posts about ASP.NET MVC (my stack, how to use Ninject 2 with ASP.NET MVC and one with some suggestions for RoR developers that what to start using the MVC framework by MS), one about Lucene.net and one about jQuery and Ajax.

And what about the most popular of all time?

Since I skipped the usual blog-versary post I also want to quickly list the top 10 posts since I started blogging.

  1. How to make a Gmail-like loading indicator with ASP.NET Ajax (67376 views)
  2. How to refresh an UpdatePanel from javascript (65561 views)
  3. Ajax TreeView (40261 views)
  4. How to manage ASP.NET validation from Javascript with jQuery (33433 views)
  5. Milan l'é semper Milan (30082 views)
  6. How to add a required validator to a CheckBoxList (25876 views)
  7. Rss2BlogML: export any RSS feed to a BlogML file (20688 views)
  8. .NET Ajax Survey results (18940 views)
  9. 13 ASP.NET MVC extensibility points you have to know (16454 views)
  10. The book writing process (15064 views)

The top spots didn’t chance since last year but it’s nice to see that one post I wrote this year already made the top 10 of all time.

How 2009 was different from 2008

In 2009 I posted 110 posts, almost 40% less posts than 2008 (where I wrote 183 posts). And on the traffic side, it grew by almost 50%, going from 250k views to 370k views. Also the number of subscribers grew, going from the 1000 RSS subscribers of the end of 2008, to the almost 2400 RSS subscribers of today.

What’s going to happen in 2010?

Since I started using Twitter the types of blog posts change from what it used it be in the past years: personal and quick thoughts are now on Twitter, and only technical posts make it to the blog. And I expect next year to be the same: I’ll post more about ASP.NET MVC, more about Subtext and everything that I come across during my future projects.

If you haven’t already, consider subscribing to my free updates via RSS

kick it on DotNetKicks.com

 

Merry Christmas and Happy New Year from CodeClimber

Print

This 2009 has been in important year in my career, more on the community than in the real day-time work side of things, but I’ll come on this later. For now, I just want to send to my almost 2400 readers my best wishes for a

Merry Christmas and an Happy New Year