Logo

Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Azure, PHP, OpenXML, VSTS, ...

About the author

Maarten Balliauw is an MVP ASP.NET and is currently employed as .NET Software Engineer at RealDolmen. His interests are mainly web applications developed in ASP.NET (C#) or PHP.
More about me More about me
Send mail E-mail me


Microsoft Most Valuable Professional - MVP - ASP.NET

Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn RealDolmen - Rock-solid passion for ICT
I'm a speaker at TechDays Belgium and TechDays Finland

Search

Latest Twitter

    Follow me on Twitter...

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    © Copyright Maarten Balliauw 2010

    Vote to help me speak at the MIX 2010 conference!

    Everybody knows the Microsoft MIX event, right? The one in Las Vegas? The one with all the fancy web-related stuff? Rings a bell? Ok, great. In the beginning of December 2009, Microsoft did an open call for speakers, which I answered with some session proposals. Who doesn’t want to go to Vegas, right?

    The open call proposals have been processed (150+ sessions submitted, wow!) and a voting has started. Yes, you hear me coming: please go ahead and vote for a session I submitted. Voting ends January 15th, 2010.

    Since I could not decide which color of the voting banner matched best with my blog’s theme, I decided to put them all three online:

    image

    Thanks in advance!

    Maarten

    PS: There's also Elijah Manor, Justin Etheredge, K. Scott Allen, and many others who submitted good looking sessions.

    kick it on DotNetKicks.com


    Byebye 2009, welcome 2010!

    Fireworks!

    A year just ended, a new has begun. Congratulations! Happy newyear 2010! And welcome in the next decennium. It’s time for a 2009 wrap-up post. And perhaps, even the time for some things I want to do in 2010. First things first: the top 5 blog posts of 2009.

    Top 5 blog posts of 2009

    1. More ASP.NET MVC Best Practices – A blog post gathering best practices from different sources and adds some more of my own.

    2. Code based ASP.NET MVC GridView (2008: 4th) – This post gives a shot at a gridview for the ASP.NET MVC framework, built using expressions.

    3. Code performance analysis in Visual Studio 2008 (2008: 2nd) – Visual Studio developer, did you know you have a great performance analysis (profiling) tool at your fingertips?

    4. Building an ASP.NET MVC sitemap provider with security trimming (2008: 5th) – Building an ASP.NET MVC sitemap provider that can be used with standard ASP.NET sitemap controls.

    5. ASP.NET load balancing and ASP.NET state server (aspnet_state) (2008: 3rd) – A how-to on load balancing with ASP.NET. Also related to ASP.NET Session State Partitioning and ASP.NET Session State Partitioning using State Server Load Balancing.

    I did a similar list last year, and you can see that I actually can stop blogging. 4 posts are in the top 5 again, with one newcomer on the 1st place.

    Open-source in 2009

    What should I say about this one… I did a lot of that :-) I continued to work on PHPExcel, PHPLinq and PHPPowerPoint, started work (with Microsoft) on the Windows Azure SDK for PHP, released the ASP.NET MVC SiteMap Provider, released TwitterMatic on CodePlex and did some contributions to Zend Framework. Then there’s also my port of MEF to PHP, which I will be releasing somewhere in Q1 2010.

    That’s a lot! And I really hope to keep the same pace going in 2010. I’m constructing a house though, which also takes some time… Luckily: no windows yet, so I can consider it open-source as well :-)

    Presentations in 2009

    Let’s see what we have there… A lot! And I hope to do the same amount (or more) in 2010. TechDays Belgium, TechDays Finland and PHPBenelux conference have been confirmed already, a good start. Anyway: here’s the 2009 list. Note that there’s also some more at various schools in Belgium, and internal sessions for RealDolmen.

    Cloud computing and the Windows Azure Services Platform

    This session covers the basics of the Windows Azure Services Platform and drills into some architectural challenges. Learn what components the Windows Azure Services Platform is built of and how they can be leveraged in building a scalable and reliable application.

    KU Leuven, December 7, 2009

    Slides: http://www.slideshare.net/maartenba/cloud-computing-and-the-windows-azure-services-platform-ku-leuven

    MSDN - Converting an existing ASP.NET application to Windows Azure

    Put your stuff in the cloud! Windows Azure allows you to take advantage of cloud computing infranstructure for hosting, computing, and storage of your applications. In this demo filled session we take an existing ASP.Net Application and move it to be hosted in Windows Azure, while taking advantage of Windows Azure storage.

    MSDN Live Meeting for MSDN Belgium, November 24, 2009

    Slides: http://www.slideshare.net/maartenba/msdn-converting-an-existing-aspnet-application-to-windows-azure
    Demo code: MSDN - Converting an existing ASP.NET application to Windows Azure.zip (2.01 mb)
    Live recording: http://www.microsoft.com/belux/MSDN/fr/chopsticks/default.aspx?id=1491

    ASP.NET MVC Wisdom

    Building a Twitter clone in 60 minutes, featuring what's new in ASP.NET MVC 2 preview 1 and focusing on some of the core ASP.NET MVC features like security and routing.

    Remix Belgium 2009, Brussels, September 29, 2009

    Slides: http://www.slideshare.net/maartenba/aspnet-mvc-wisdom
    Demo code: ASP.NET MVC Wisdom - ReMix.zip (8.91 mb)
    Live recording: http://blog.maartenballiauw.be/post/2009/10/23/Recording-of-my-session-at-Remix-2009-ASPNET-MVC.aspx

    PHP and Silverlight

    So you have an existing PHP application and would like to spice it up with a rich and attractive front-end. Next to Adobe Flex, you can also choose Silverlight as a solution. This session shows you around in Silverlight and shows that PHP and Silverlight can go together easily.

    DevDays 2009, The Hague, May 29, 2009  -  May 29, 2009
    Dutch PHP Conference, Amsterdam, June 12, 2009  -  June 12, 2009

    Slides: http://www.slideshare.net/maartenba/php-and-silverlight-devdays-session?type=powerpoint
    Demo code: PHP and Silverlight - DevDays.zip (1.00 mb)
    Live recording (audio): http://techportal.ibuildings.com/2009/12/21/introduction-to-silverlight-for-php-developers/

    PHPPowerPoint – More OpenXML from PHP

    Session on the newly released open source project PHPPowerPoint, which enables you to build PPTX files from PHP. This session will provide you a general view of PHPPowerPoint and some architectural insights into the API.

    DII Workshop, London, May 18, 2009  -  May 18, 2009

    Mocking

    This session provides an introduction to mocking and shows how test-driven development and the use of mocking frameworks such as Moq can speed up application development.

    VISUG Belgium, May 7, 2009  -  May 7, 2009

    Slides: http://www.slideshare.net/maartenba/mocking-visug-session?type=powerpoint
    Demo code: MockingDemoCode.zip (1.64 mb)

    ASP.NET MVC (model-view-controller)

    This session provides an introduction to the ASP.NET MVC framework. Starting with a short intro to the model-view-controller pattern and Microsoft's vision on implementing this pattern for ASP.NET, over some of the key differences between ASP.NET Webforms and ASP.NET MVC to doing some more advanced things like scaffolding and action filters.

    MSDN Belgium, April 23, 2009  -  April 23, 2009

    Slides: http://www.slideshare.net/maartenba/msdn-aspnet-mvc?type=powerpoint

    Azure User Group Belgium

    image Together with Kurt Claeys and Yves Goeleven, we did a first session with the new Azure User Group Belgium. AZUG.BE is a Belgian user group with focus on development and architecture of the Windows Azure Platform. Our goal is to share knowledge and experiences with the .NET community on Windows Azure, .NET Services and SQL Azure.

    Expect more activity and sessions in 2010!

    I wrote a book!

    image That’s correct: I did write a book. My first one, but probably not the last one. Don’t know when and on what, but I’ll probably find the energy to do this effort again. Here’s a quite from my announcement post:

    It’s been quite a job, but there it is: Packt just announced my very first book on their site. It is titled “ASP.NET MVC 1.0 Quickly”, covering all aspects ASP.NET MVC offers in a to-the-point manner with hands-on examples. The book walks through the main concepts of the MVC framework to help existing ASP.NET developers to move on to a higher level. It includes clear instructions and lots of code examples. It takes a simple approach, thereby allowing you to work with all facets of web application development. Some keywords: Model-view-controller, ASP.NET MVC architecture and components, unit testing, mocking, AJAX using MS Ajax and jQuery, reference application and resources.

    That’s it for the marketing part: let’s do a retrospective on the writing process itself. Oh and yes, those are my glasses on the cover. Photo was taken on the beach near Bray-Dunes (France).

    Most valuable professional

    image In July 2009, I became an MVP ASP.NET. Let’s see if we can repeat this for 2010 :-)

    My focus was still on ASP.NET MVC in 2009, but also more and more on Windows Azure. These two make a great combination, and will be the main topics for my blog in 2010 as well.

    Traveling

    Some traveling in 2009 as well. I went on a ski vacation and a summer vacation, but next to that I did some traveling for work as well:

    If only I knew that these last two would provide me a lot of airmiles… Subscribed at www.milesandmore.com for possible traveling in 2010 :-)

    Thank you!

    I do take credit for all that I did in 2009, but I would also like to thank my company RealDolmen for providing enough room to do some of this during work hours, as well as for challenging me in this. Really appreciated guys!

    Now is also a great moment to thank my family for not whining too much and also giving me the room to do all of this, often taking time out of family life. Thanks for letting me do all this!

    Summary and look ahead

    It’s been a relaxing year. No, seriously: I’ve been busy, and I expect the same for 2010… Not sure if I can do 79 blog posts again, but I will sure try. And in order to do that, I need some input from you:

    • What topics would you like to see covered?
    • Is there anything you want to learn more about?
    • A great conceptual idea, no time to work on it? Shoot! Maybe I will work on it.
    • Any other feedback for me?

    Enjoy 2010! I will.


    Categories: General | ICT | Internet | Personal

    Hoping they will learn… Usability!

    How about ending the year 2009 with a blog post on something annoying I see on the Internet, as well as some others? I’m talking about automatic localization… Please, go ahead and read some tweets by @KvdM and @patrickv. And then, there’s my own annoyance on Windows Mobile Marketplace. The base for al this frustrated year-end whining has to do with the fact that there are assumptions being made about the location of a user, rather than about a user itself…

    On every request my browser makes, my preferred language is being sent out. Where I am, that would be “nl-BE” (Dutch, in Belgium). At my customer’s location, that would be “nl-NL” (Dutch, in the Netherlands). If everything works according to plan, both of these should be telling the website that I want to display it in Dutch. However, some websites out there like Twitter, Facebook, … look at the second part, serving me a “Belgian” version of the site in the first case and a “Netherlands” version in the second case. According to Wikipedia, a site that actually does the above trick in the correct fashion, Belgium has three official languages: Dutch, French and German. Since history however linked the French language to Belgium, most websites think that the default language for Belgium should be French. While I actually do send out my preferences on every request my browser makes.

    No problem, I do speak (a little) French, so I am able to find the language switch on most websites in no time. It would be a bit nicer though if my preference was respected or switched to English if no Dutch version is available. The Internet is mostly English, I’m fine with that. Don’t get me wrong, I’m not one of those Flemish nationalists saying French is bad and the Walloon part of Belgium is bad. No, all I’m saying is that some websites are making wrong assumptions, forcing me to add an extra click (switching the language) to some of the sites I’m visiting. Not the ideal situation in an era where usability is something being focused on more and more.

    Things do get worse sometimes. In the above situation, there was still a language switch. And then, there’s Windows Mobile Marketplace… The website does recognize I’m “nl-BE” and displays in Dutch. After installing the software on my cell phone and linking my Windows Live ID, it seems that the only market I can download software in is… Belgium – French! No problem, the software listed is the same as the one in the “Belgium – Dutch” market so I can download what I want, and I do speak enough French to find my way around. However: no language switch… Marketplace is something great, but there’s a small usability catch…

    Someone pointed out that there’s something available which can switch the language for Marketplace, but it’s an extra tool I have to download and install. Usability? And for the other situation: I have “en-US” (English, USA) registered as the default language my browser sends out:

    Default culture settings in Internet Explorer

    This does fix a lot of usability frustration, but I think it’s not the way all of this was meant to be. So, when planning a new web application in 2010, do make use of all the information clients provide you. Don’t make assumptions, default to English if you don’t have the requested language available. And while you are thinking: also make use of OpenID or something like that for doing account registration. Small things can make a website much more usable!

    That being said: enjoy the last days of 2009, enjoy the time-warp to 2010!


    Categories: General | ICT | Internet | Personal

    I’m an MVP ASP.NET!

    MVPLogoYesterday evening, I received the following e-mail:

    Dear Maarten Balliauw,

    Congratulations! We are pleased to present you with the 2009 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others. We appreciate your outstanding contributions in ASP/ASP.NET technical communities during the past year.

    (...)

    Toby Richards
    General Manager
    Community Support Services

    Translated in short: I’m now officially an MVP ASP.NET! I am really honored to be recognized as an MVP. Thank you for the nomination!

    The past year has been quite fun, doing lots of blog posts, a book on ASP.NET MVC, various speaking sessions at VISUG, DevDays, PHP Conference, … Guess now I’m obligated to stay active in community :-) The next two weeks will be community less however, since I’m off on a vacation. See/write/… you in a week or two!


    Categories: ASP.NET | General | ICT | Internet | Personal | MVP

    Revised: ASP.NET MVC and the Managed Extensibility Framework (MEF)

    A while ago, I did a blog post on combining ASP.NET MVC and MEF (Managed Extensibility Framework), making it possible to “plug” controllers and views into your application as a module. I received a lot of positive feedback as well as a hard question from Dan Swatik who was experiencing a Server Error with this approach… Here’s a better approach to ASP.NET MVC and MEF.

    kick it on DotNetKicks.com

    The Exception

    Server Error

    The stack trace was being quite verbose on this one:

    InvalidOperationException

    The view at '~/Plugins/Views/Demo/Index.aspx' must derive from ViewPage, ViewPage<TViewData>, ViewUserControl, or ViewUserControl<TViewData>.

    at System.Web.Mvc.WebFormView.Render(ViewContext viewContext, TextWriter writer) at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.<InvokeActionResultWithFilters>b__e() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.<>c__DisplayClass13.<InvokeActionResultWithFilters>b__10() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) at System.Web.Mvc.Controller.ExecuteCore() at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext) at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext) at System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext httpContext) at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

    Our exception seemed to be thrown ONLY when the following conditions were met:

    • The View was NOT located in ~/Views but in ~/Plugins/Views (or other path)
    • The View created in our MEF plugin was strong-typed

    Problem one… Forgot to register ViewTypeParserFilter…

    Allright, go calling me stupid… Our ~/Plugins/Views folder was not containing the following Web.config file:

    <?xml version="1.0"?>
    <configuration>
      <system.web>
        <httpHandlers>
          <add path="*" verb="*"
              type="System.Web.HttpNotFoundHandler"/>
        </httpHandlers>

        <!--
            Enabling request validation in view pages would cause validation to occur
            after the input has already been processed by the controller. By default
            MVC performs request validation before a controller processes the input.
            To change this behavior apply the ValidateInputAttribute to a
            controller or action.
        -->
        <pages
            validateRequest="false"
            pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
            pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
            userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
          <controls>
            <add assembly="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
          </controls>
        </pages>
      </system.web>

      <system.webServer>
        <validation validateIntegratedModeConfiguration="false"/>
        <handlers>
          <remove name="BlockViewHandler"/>
          <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
        </handlers>
      </system.webServer>
    </configuration>

    Now why would you need this one anyway? Well: first of all, you do not want your views to expose their source code. Therefore, we add the HttpNotFoundHandler for this folder. Next, we do not want request validation to happen again (because this is already done when invoking the controller). Next: we want the MvcViewTypeParserFilter to be used for enabling strong-typed views (more on this by Phil Haack).

    Problem two: MEF’s approach to plugins and ASP.NET’s approach to rendering views…

    When compiling a view, ASP.NET dynamically compiles the markup into a temporary assembly, after which it is rendered. This compilation process knows only the assemblies loaded by your web application’s AppDomain. Unfortunately, assemblies loaded by MEF are not available for this compilation process… I went ahead and checked with Reflector if we could do something about this on ASP.NET side: nope. The main classes we need for this are internal :-( The MEF side could be easily tweaked since its source code is available on CodePlex, but… it’s still subject to change and will be included in .NET 4.0 as a framework component, which would limit my customizations a bit for the future.

    Now let’s describe this problem as one, simple sentence: we need the MEF plugin assembly loaded in our current AppDomain, available for all other components in the web application.

    The solution to this: I want a MEF DirectoryCatalog to monitor my plugins folder and load/unload the assemblies in there dynamically. Loading should be no problem, but unloading… The assemblies will always be locked by my web server’s process! So let’s go for another approach: monitor the plugins folder, copy the new/modified assemblies to the web application’s /bin folder and instruct MEF to load its exports from there. The solution: WebServerDirectoryCatalog. Here’s the code:

    public sealed class WebServerDirectoryCatalog : ComposablePartCatalog
    {
        private FileSystemWatcher fileSystemWatcher;
        private DirectoryCatalog directoryCatalog;
        private string path;
        private string extension;

        public WebServerDirectoryCatalog(string path, string extension, string modulePattern)
        {
            Initialize(path, extension, modulePattern);
        }

        private void Initialize(string path, string extension, string modulePattern)
        {
            this.path = path;
            this.extension = extension;

            fileSystemWatcher = new FileSystemWatcher(path, modulePattern);
            fileSystemWatcher.Changed += new FileSystemEventHandler(fileSystemWatcher_Changed);
            fileSystemWatcher.Created += new FileSystemEventHandler(fileSystemWatcher_Created);
            fileSystemWatcher.Deleted += new FileSystemEventHandler(fileSystemWatcher_Deleted);
            fileSystemWatcher.Renamed += new RenamedEventHandler(fileSystemWatcher_Renamed);
            fileSystemWatcher.IncludeSubdirectories = false;
            fileSystemWatcher.EnableRaisingEvents = true;

            Refresh();
        }

        void fileSystemWatcher_Renamed(object sender, RenamedEventArgs e)
        {
            RemoveFromBin(e.OldName);
            Refresh();
        }

        void fileSystemWatcher_Deleted(object sender, FileSystemEventArgs e)
        {
            RemoveFromBin(e.Name);
            Refresh();
        }

        void fileSystemWatcher_Created(object sender, FileSystemEventArgs e)
        {
            Refresh();
        }

        void fileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
        {
            Refresh();
        }

        private void Refresh()
        {
            // Determine /bin path
            string binPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin");

            // Copy files to /bin
            foreach (string file in Directory.GetFiles(path, extension, SearchOption.TopDirectoryOnly))
            {
                try
                {
                    File.Copy(file, Path.Combine(binPath, Path.GetFileName(file)), true);
                }
                catch
                {
                    // Not that big deal... Blog readers will probably kill me for this bit of code :-)
                }
            }

            // Create new directory catalog
            directoryCatalog = new DirectoryCatalog(binPath, extension);
        }

        public override IQueryable<ComposablePartDefinition> Parts
        {
            get { return directoryCatalog.Parts; }
        }

        private void RemoveFromBin(string name)
        {
            string binPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin");
            File.Delete(Path.Combine(binPath, name));
        }
    }

    Download the example code

    First of all: this was tricky, and the solution to it is also a bit tricky. Use at your own risk!

    You can download the example code here: RevisedMvcMefDemo.zip (1.03 mb)

    kick it on DotNetKicks.com


    Categories: ASP.NET | C# | Debugging | General | ICT | Internet | MEF | MVC | Personal

    Sample chapter from ASP.NET MVC 1.0 Quickly

    image Here’s a shameless, commercial blogpost… With yesterday’s 1.0 release of the ASP.NET MVC framework, I’m sure the following sample chapter from my book ASP.NET MVC 1.0 Quickly will be of use for people starting ASP.NET MVC development: Your first ASP.NET MVC application.

    When downloading and installing the ASP.NET MVC framework SDK, a new project template is installed in Visual Studio. This chapter describes how to use the ASP.NET MVC project template that is installed in Visual Studio. All ASP.NET MVC aspects are touched briefly by creating a new ASP.NET MVC web application based on this Visual Studio template. Besides view, controller, and model, new concepts including ViewData—a means of transferring data between controller and view, routing—the link between a web browser URL and a specific action method inside a controller, and unit testing of a controller are also illustrated here.

    In this chapter, you will:

    • Have an overview of all the aspects of an ASP.NET MVC web application
    • Explore the ASP.NET MVC web application project template that is installed in Visual Studio 2008
    • Create a first action method and corresponding view
    • Create a strong-typed view
    • Learn how a controller action method can pass strong-typed ViewData to the view
    • Learn what unit testing is all about, and why it should be used
    • Learn how to create a unit test for an action method by using Visual Studio's unit test generation wizard and modifying the unit test code by hand

    Download the free sample chapter here. Or order the full book, here. That’s a better option ;-)

    By the way, if you are interested in the book writing process itself, check my previous blog post on that.

    kick it on DotNetKicks.com


    Announcing my book: ASP.NET MVC 1.0 Quickly

    ASP.NET MVC 1.0 Quickly It’s been quite a job, but there it is: Packt just announced my very first book on their site. It is titled “ASP.NET MVC 1.0 Quickly”, covering all aspects ASP.NET MVC offers in a to-the-point manner with hands-on examples. The book walks through the main concepts of the MVC framework to help existing ASP.NET developers to move on to a higher level. It includes clear instructions and lots of code examples. It takes a simple approach, thereby allowing you to work with all facets of web application development. Some keywords: Model-view-controller, ASP.NET MVC architecture and components, unit testing, mocking, AJAX using MS Ajax and jQuery, reference application and resources.

    That’s it for the marketing part: let’s do a retrospective on the writing process itself. Oh and yes, those are my glasses on the cover. Photo was taken on the beach near Bray-Dunes (France).

    When did you have the idea of writing a book?

    I'm not sure about that. I've been blogging a lot on ASP.NET MVC last year, wrote an article for .NET magazine, did some presentations, ... It occurred to me that I had a lot of material which I could bundle. Together with that, my project manager jokingly said something like: "When will you write your first book? With all that blogging." So I did start bundling stories. First of all, I overlooked the whole ASP.NET MVC technology (preview 2 at that moment) and decided there were enough topics to talk about. A draft table of contents was built quite quick, but I gave up on writing. Too much information, not enough time, ...

    A few weeks later, it must have been around the beginning of May, 2008, I did start writing a first chapter, thinking I'ld see how the writing itself would turn out, if it fit in my schedule, ... It worked out quite well, each 10-20 days gave me a new chapter. I also started looking for a publisher when I was finished with chapter 6 or so. Having reviewed some books for Packt, I contacted them with a proposal for my book.

    After having a look at the other 6 upcoming books (here and here), we decided we could go for it, focusing on a hands-on book which rapidly guides you into the wonderful world of ASP.NET MVC.

    How was your experience of writing your book?

    Looking back, it was an interesting experience. I decided to write in English, which is not my native language. That was actually quite a hard one: writing in English is no problem, but writing a good, solid and interesting piece of text is just not that easy when writing longer texts than the average blog post. Another thing is that I tortured myself writing about a product that was not even beta yet! I started writing with ASP.NET MVC preview 3, updated it all to preview 4, 5, beta, release candidate, ... Lots of changes in the ASP.NET MVC API or concepts meant lots of changes to make in chapters I already wrote. Luckily, I survived :-)

    I only contacted a publisher when I had finished 60% of my book. If you are considering writing: don't do this! Contact a publisher at a very early stage: they normally give you lots of advice upfront, which I only received after contacting them. Advice earlier along the way is always better, so that's something I would definately do different.

    Speaking of advice: when writing was done, the book entered review phase. Different people received the draft version and could provide comments and suggestions. Thanks Stefan, Troy, Vivek, Jerry, Joydip and people at Packt for your time in reviewing my draft version! Reviewer comments really made the book better and required me to do some small rewrites, elaborate more on certain topics.

    What tools did you use for writing?

    There are some tools that you really need when writing a technical book. One of them is a text editor, in my case Microsoft Word 2007. Together with that, Visual Studio 2008 and regularly updated ASP.NET MVC versions were required. Being scared of losing data, I decided to also use a source control system for sample code ánd for my Word documents. All of these files were stored in a Subversion repository located on my server, being backed up every day to different locations. Doug Mahugh laughed at me when I said I was using Subversion, but it did a great job!

    Other tools I used were Paint.NET and MwSnap, both for creating screenshots in my virtual PC running Windows Vista and Visual Studio 2008. I also used Achievo for time tracking purposes, since I was curious how much time this book writing would actually cost me.

    How much time did you spend writing?

    First of all, this is not going to be 100% accurate. I did track writing and development time during writing, but I already had a lot of material to work with. But here's an overview (numbers in hours):

    image

    That is right: writing a book consumes only a little more than 100 hours! But still, I already had lots of material. I'd say to double the number for an accurate timeframe.

    Now I hear the next question coming... Here's the answer already: Yes, I have a girlfriend. We are working on our home (planning phase is done, searching a contractor at the moment), visiting family, doing daily stuff, blogging, work, ... It al worked out to fit together, but still: there have been some busy moments on evenings and weekends. Thanks, people around me, for being patient and caring during these busy moments!

    Are you getting rich out of this?

    Of course, I can grab a couple of beers (for a couple of times), but don't think writing a book will buy you a car... I just felt that I had lots of valuable information that I had to share, and writing a book seemed like the best option to do that. Creating a "to read"-list? Make sure to add ASP.NET MVC 1.0 Quickly to it.

    kick it on DotNetKicks.com


    Replacement during my vacation: Wilson

    This morning, I arrived at work after a great week of skiing in Pitztal, Austria. Unfortunately, I found my chair occupied by a new colleague looking a bit like Wilson. Good to see he enjoyed working early, like I do. But still, that was my seat and PC he was using… Thank you, dear colleagues, to see myself replaced by a plastic, smiling ball…

    Wilson, my replacement

    kick it on DotNetKicks.com


    Categories: Fun | General | Personal | Offtopic

    PHPLinq 0.4.0 released on CodePlex!

    PHPLinq I’m pleased to announce that PHPLinq 0.4.0 has been released on CodePlex. PHPLinq is currently one year old, and I decided to add a huge step in functionality for the 0.4.0 release. This blog post will focus on the current status of PHPLinq and what it is capable of doing for you in a PHP project.

     

    What is PHPLinq?

    PHPLinq is a class library for PHP, based on the idea of Microsoft’s LINQ technology. LINQ is short for language integrated query, a component in the .NET framework which enables you to perform queries on a variety of data sources like arrays, XML, SQL server, ... These queries are defined using a syntax which is very similar to SQL.

    Using PHPLinq, the same functionality is created in PHP. Since regular LINQ applies to enumerators, SQL, datasets, XML, ..., I decided PHPLinq should provide the same infrastructure. Here’s an example PHPLinq query, which retrieves all names with a length less than 5 from an array of strings:

    // Create data source
    $names = array("John", "Peter", "Joe", "Patrick", "Donald", "Eric");

    $result = from('$name')->in($names)
                ->where('$name => strlen($name) < 5')
                ->select('$name');

    Notice the in()-function? This is basically a clue for PHPLinq to determine how t query data. In this case, PHPLinq will work with a string array, but is perfectly possible to hint PHPLinq with a database table, for example. I’ll show you more on that later in this post.

    PHPLinq components

    This functionality is achieved by the fact that each PHPLinq query is initiated by the PHPLinq_Initiator class. Each PHPLinq_ILinqProvider implementation registers itself with this initiator class, which then determines the correct provider to use. This virtually means that you can write unlimited providers, each for a different data type!

    PHPLinq architecture

    What can I do with PHPLinq?

    Basically, PHPLinq is all about querying data. No matter if it’s an array, XML tree or a database table, PHPLinq should be able to figure out what to do witht the data, without you being required to write complex foreach loops and stuff like that.

    Querying data from an array

    Let’s have a look at an example. The following array will be a dataset which we’ll be working with. It is a list of Employee objects.

    // Employee data source
    $employees = array(
        new Employee(1, 1, 5, 'Maarten', 'maarten@example.com', 24),
        new Employee(2, 1, 5, 'Paul', 'paul@example.com', 30),
        new Employee(3, 2, 5, 'Bill', 'bill.a@example.com', 29),
        new Employee(4, 3, 5, 'Bill', 'bill.g@example.com', 28),
        new Employee(5, 2, 0, 'Xavier', 'xavier@example.com', 40)
    );

    I would like to have the name and e-mail address of employees named “Bill”. Here’s a PHPLinq query:

    $result = from('$employee')->in($employees)
                ->where('$employee => substr($employee->Name, 0, 4) == "Bill"')
                ->select('new {
                        "Name" => $employee->Name,
                        "Email" => $employee->Email
                      }'
    );

    Wow! New things here! What’s this $employee => … thing? What’s this new { … } thing? The first is a lambda expression. This is actualy an anonymous PHP function we are creating, accepting a parameter $employee. This function returns a boolean (true/false), based on the employee’s name. The new { … } thing is an anonymous class constructor. What we are doing here is defining a new class on-the-fly, with properties Name and Email, based on data from the original $employee.

    Here’s the output of the above query:

    Array
    (
        [0] => stdClass Object
            (
                [Name] => Bill
                [Email] => bill.a@example.com
            )
        [1] => stdClass Object
            (
                [Name] => Bill
                [Email] => bill.g@example.com
            )
    )

    How cool is that! Things are getting a lot cooler when we use PHPLinq together with the Zend Framework’s Zend_Db_Table

    Querying data from a database

    PHPLinq has a second PHPLinq_ILinqProvider built in. This provider makes use of the Zend Framework Zend_Db_Table class to provide querying capabilities. First things first: let’s create a database table.

    CREATE TABLE employees (
        Id                INTEGER NOT NULL PRIMARY KEY,
        DepartmentId    INTEGER,
        ManagerId        INTEGER,
        Name            VARCHAR(100),
        Email            VARCHAR(200),
        Age                INTEGER
    );

    We’ll be using this table in a Zend_Db_Table class:

    // EmployeeTable class
    class EmployeeTable extends Zend_Db_Table {
        protected $_name = 'employees'; // table name
        protected $_primary = 'Id';
    }
    $employeeTable = new EmployeeTable(array('db' => $db));
    $employeeTable->setRowClass('Employee');

    Allright, what happened here? We’ve created a database table, and told Zend_Db_Table to look in the employees table for data, and map these to the Employee class we created before. The Zend_Db_Table employee table will be accessible trough the $employeesTable variable.

    Ok, let’s issue a query:

    $result = from('$employee')->in($employeesTable)
                ->where('$employee => substr($employee->Name, 0, 4) == "Bill"')
                ->select('new {
                        "Name" => $employee->Name,
                        "Email" => $employee->Email
                      }'
    );

    Here’s the output of the above query:

    Array
    (
        [0] => stdClass Object
            (
                [Name] => Bill
                [Email] => bill.a@example.com
            )
        [1] => stdClass Object
            (
                [Name] => Bill
                [Email] => bill.g@example.com
            )
    )

    Did you notice this query is actually the same as we used before? Except for the $employeesTable now being used instead of $employees this query is identical! The only thing that is different, is how PHPLinq handles the query internally. Using the array of objects, PHPLinq will simply loop the array and search for correct values. Using Zend_Db_Table, PHPLinq actually builds a SQL query which is executed directly on the database server, delegating performance and execution to the database engine.

    We can have a look at the generated query by setting an option on PHPLinq, which will tell PHPLinq to pass the generated query to PHP’s print function.

    PHPLinq_LinqToZendDb::setQueryCallback('print');

    Let’s run the previous query again. The console will now also display the generated SQL statement:

    SELECT "$employee".* FROM "employees" AS "$employee" WHERE (SUBSTR('$employee'."Name",  0,  4)  =  "Bill")

    Cool! Are you kidding me?!? PHPLinq just knew that the PHP code in my where clause translates to the above SQL statement! It’s even cooler than this: PHPLinq also knows about different databases. The above example will translate to another query on a different database engine. For that, let’s look at another example. Here’s the PHPLinq query:

    $result = from('$employee')->in($employeeTable)
                ->where('$employee => trim($employee->Name) == "Bill"')
                ->select('$employee->Name');

    The generated SQL statement in SQLite:

    SELECT "$employee".* FROM "employees" AS "$employee" WHERE (TRIM('$employee'."Name")  =  "Bill")

    The generated SQL statement in Microsoft SQL Server (only knows LTRIM() and RTRIM(), not TRIM()):

    SELECT "$employee".* FROM "employees" AS "$employee" WHERE (LTRIM(RTRIM('$employee'."Name"))  =  "Bill")

    I don't know about you, but I think this is very useful (and COOL!)

    Querying data from an XML source

    Here’s another short example, just to be complete. Let's fetch all posts on my blog's RSS feed, order them by publication date (descending), and select an anonymous type containing title and author. Here's how:

    $rssFeed = simplexml_load_string(file_get_contents('http://blog.maartenballiauw.be/syndication.axd'));
    $result = from('$item')->in($rssFeed->xpath('//channel/item'))
                ->orderByDescending('$item => strtotime((string)$item->pubDate)')
                ->take(2)
                ->select('new {
                                "Title" => (string)$item->title,
                                "Author" => (string)$item->author
                          }'
    );

    Where to go now?

    There’s lots of other features in PHPLinq which I covered partially in previous blog posts (this one and this one). For full examples, download PHPLinq from www.phplinq.net and see for yourself.

    By the way, PHPExcel (another project of mine) and PHPLinq seem to be listed in Smashing Magazine's Top 50 list of extremely useful PHP tools. Thanks for this recognition!


    Updated CarTrackr to ASP.NET MVC RC

    image As you may have noticed, ASP.NET MVC 1.0 Release Candidate has been released over the night. You can read all about it in ScottGu’s blog post, covering all new tools that have been released with the RC.

    Since I’ve been trying to maintain a small reference application for ASP.NET MVC known as CarTrackr, I have updated the source code to reflect some changes in the ASP.NET MVC RC. You can download it directly from the CodePlex project page at www.cartrackr.net.

    Here’s what I have updated (copied from the release notes):

    Specifying View Types in Page Directives

    The templates for ViewPage, ViewMasterPage, and ViewUserControl (and derived types) now support language-specific generic syntax in the main directive’s Inherits attribute. For example, you can specify the following type in the @ Master directive:

    <%@ Master Inherits="ViewMasterPage<IMasterInfo>" %>

    An alternative approach is to add markup like the following to your page (or to the content area for a content page), although doing so should never be necessary.

    <mvc:ViewType runat="server" TypeName="ViewUserControl&lt;ProductInfo>" />

    The default MVC project templates for Visual Basic and C# views have been updated to incorporate this change to the Inherits attribute. All existing views will still work. If you choose not to use the new syntax, you can still use the earlier syntax in code.

    ASP.NET Compiler Post-Build Step

    Currently, errors within a view file are not detected until run time. To let you detect these errors at compile time, ASP.NET MVC projects now include an MvcBuildViews property, which is disabled by default. To enable this property, open the project file and set the MvcBuildViews property to true, as shown in the following example:

    <Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
      <PropertyGroup> 
        <MvcBuildViews>true</MvcBuildViews> 
      </PropertyGroup>

    Note: Enabling this feature adds some overhead to the build time.

    You can update projects that were created with previous releases of MVC to include build-time validation of views by performing the following steps:

    1. Open the project file in a text editor.

    2. Add the following element under the top-most <PropertyGroup> element:

    <MvcBuildViews>true</MvcBuildViews>

    3. At the end of the project file, uncomment the <Target Name="AfterBuild"> element and modify it to match the following example:

    <Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'"> 
        <AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)\..\$(ProjectName)" />
    </Target>

    kick it on DotNetKicks.com


    Categories: ASP.NET | C# | CodePlex | General | ICT | Internet | MVC | Personal | Projects