Logo

Maarten Balliauw {blog}

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

About the author

Maarten Balliauw is currently employed as .NET Technical Consultant at RealDolmen. His interests are mainly web applications developed in ASP.NET (C#) or PHP and the Windows Azure cloud platform.
More about me More about me
Send mail E-mail me


ASP.NET MVC Quickly Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn
View Maarten Balliauw's MVP profile

Search

Latest Twitter

    Follow me on Twitter...

    My projects

    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

    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# | General | MVC | Personal | Projects

    Seven things you didn’t know about me

    Seems 2009 is starting off with yet another round of tagging people. Back in 2007, I already had to write five things about myself. Since we are now two years further, I guess each year asks for another extra item to be added. Thank you Michelangelo for making me write another post.

    Seven things about me Here goes, seven things you may not know about me:

    1. The first programming language I used was Visual Basic 4. Back then, it was distributed on 4 gray 3.5” floppy disks. I was 12 years at this time, and totally interested in anything that had to do with computers and software development.
    2. You probably know this one already: I really drink lots of coffee every day. Not sure if this is healthy, but it keeps me going. I also guess this has to do with my favourite quote: “A developer is a machine that converts coffee into code”. By the way, black coffee please!
    3. I once had my own web development / web hosting company, named Squirrel. The WayBackMachine at Archive.org still knows about this. This is also the main reason I started to learn PHP: most of my customers were expecting PHP applications on Linux hosting, but I also had some ASP.NET customers for who I did ASP.NET development. Somewhere in 2006, I sold 100% of my shares and customers to Uniweb.
    4. One of the things I really don’t like doing is… sports! Really, no problem for me to do some long walks in a beautiful scenery, but please don’t make me do fitness or jogging each day. Sooo boring! One of the sports I do enjoy is skiing, which I have been doing each year since I was 5. Since 3 years, I’m going to Pitztal, Austria. This ski resort features cosy Austrian hotels and après-ski, as well as a not too crowded glacier where the slopes are located.
    5. I work for RealDolmen, one of the biggest IT players in Belgium. I’m located at a customer’s office in the Netherlands since 2 years and a half now, four days per week. The fifth day is mostly for delivering various trainings to our junior employees, to work on Visual Studio Team System solutions, to drink more coffee, …
    6. This year (and pobably next year too) will be the year where me and my girlfriend finally will be constructing our house! We’ll do lots of things ourselves, so perhaps I should start a DIY (do-it-yourself) blog too, later this year.
    7. I started a micro-blog on Twitter about a month ago.I guess it’s a good channel if you want to learn more about me.

    Since almost everyone I know in PHP land has been tagged, let’s also tag some people outside PHP land:

    Here are the rules if you are tagged:

    • Link your original tagger(s), and list these rules on your blog.
    • Share seven facts about yourself in the post - some random, some wierd.
    • Tag seven people at the end of your post by leaving their names and the links to their blogs.
    • Let them know they've been tagged by leaving a comment on their blogs and/or Twitter.

    kick it on DotNetKicks.com


    Categories: General | Personal

    PHPExcel featured in php|architect / November 2008

    Cover of php|architect / November 2008 Nice to see that there's a lot of activity going on related to PHPExcel! This weekend, I receievd my electronic copy of php|architect / November 2008 featuring an article on generating PDF and Excel files using PHP. Guess which library is being used in the second part of the article...

    While reading the article, I noticed a very cool thing: the author, Aaron Wormus, is using a convenient way to generate charts in PHPExcel using Google Charts API. Since PHPExcel currently does not support creating graphs, this is really a good method to use charts in PHPExcel generated Excel files. Here's a screenshot of the generated file in the magazine:

    image 

    Sweet!


    Categories: General | OpenXML | Personal | PHP | Publications | XML

    Using the ASP.NET MVC ModelBinder (screencast)

    A new screencast has just been uploaded to the MSDN Belgium Chopsticks page. Don't forget to rate the video!

    Using ASP.NET MVC ModelBinder

    Abstract: "This screencast demonstrates how code can be made more maintainable and testable by delegating binding to client data to the ASP.NET MVC model binder architecture."

    kick it on DotNetKicks.com


    Article on ASP.NET MVC in .NET magazine #21

    .NET magazine 21 Yesterday, I received the new Dutch edition of .NET magazine containing my article on the ASP.NET MVC framework. Since the article was written quite a while ago, soucre code is no longer up-to-date. Readers who are interested (or anyone else interested in ASP.NET MVC) can download up-to-date code examples on the ASP.NET MVC guestbook page.

    kick it on DotNetKicks.com


    Categories: ASP.NET | C# | General | MVC | Personal | Publications

    Creating an ASP.NET MVC OutputCache ActionFilterAttribute

    In every web application, there are situations where you want to cache the HTML output of a specific page for a certain amount of time, because underlying data and processing isn't really subject to changes a lot. This cached response is stored in the web server's memory and offers very fast responses because no additional processing is required.

    Using "classic" ASP.NET, one can use the OutputCache directive on a .aspx page to tell the ASP.NET runtime to cache the response data for a specific amount of time. Optionally, caching may vary by parameter, which results in different cached responses depending on the parameters that were passed in the URL.

    As an extra feature, one can also send some HTTP headers to the client and tell him to load the page from  the web browser's cache until a specific amount of time has passed. Big advantage of this is that your web server will receive less requests from clients because they simply use their own caching.

    Using the ASP.NET MVC framework (preview 3, that is), output caching is still quite hard to do. Simply specifying the OutputCache directive in a view does not do the trick. Luckily, there's this thing called an ActionFilterAttribute, which lets you run code before and after a controller action executes. This ActionFilterAttribute class provides 4 extensibility points:

    • OnActionExecuting occurs just before the action method is called
    • OnActionExecuted occurs after the action method is called, but before the result is executed (before the view is rendered)
    • OnResultExecuting occurs just before the result is executed (before the view is rendered)
    • OnResultExecuted occurs after the result is executed (after the view is rendered)

    Let's use this approach to create an OutputCache ActionFilterAttribute which allows you to decorate any controller and controller action, i.e.:

    [OutputCache(Duration = 60, VaryByParam = "*", CachePolicy = CachePolicy.Server)]
    public ActionResult Index()
    {
        // ...
    }

    We'll be using an enumeration called CachePolicy to tell the OutputCache attribute how and where to cache:

    public enum CachePolicy
    {
        NoCache = 0,
        Client = 1,
        Server = 2,
        ClientAndServer = 3
    }

    1. Implementing client-side caching

    Actually, this one's really easy. Right before the view is rendered, we'll add some HTTP headers to the response stream. The web browser will receive these headers and respond to them by using the correct caching settings. If we pass in a duration of 60, the browser will cache this page for one minute.

    public class OutputCache : ActionFilterAttribute
    {
        public int Duration { get; set; }
        public CachePolicy CachePolicy { get; set; }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            // Client-side caching?
            if (CachePolicy == CachePolicy.Client || CachePolicy == CachePolicy.ClientAndServer)
            {
                if (Duration <= 0) return;

                HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
                TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);

                cache.SetCacheability(HttpCacheability.Public);
                cache.SetExpires(DateTime.Now.Add(cacheDuration));
                cache.SetMaxAge(cacheDuration);
                cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
            }
        }
    }

    2. Implementing server-side caching

    Server-side caching is a little more difficult, because there's some "dirty" tricks to use. First of all, we'll have to prepare the HTTP response to be readable for our OutputCache system. To do this, we first save the current HTTP context in a class variable. Afterwards, we set up a new one which writes its data to a StringWriter that allows reading to occur:

    existingContext = System.Web.HttpContext.Current;
    writer = new StringWriter();
    HttpResponse response = new HttpResponse(writer);
    HttpContext context = new HttpContext(existingContext.Request, response)
    {
        User = existingContext.User
    };
    System.Web.HttpContext.Current = context;

    Using this in a OnResultExecuting override, the code would look like this:

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        // Server-side caching?
        if (CachePolicy == CachePolicy.Server || CachePolicy == CachePolicy.ClientAndServer)
        {
            // Fetch Cache instance
            cache = filterContext.HttpContext.Cache;

            // Fetch cached data
            object cachedData = cache.Get(GenerateKey(filterContext));
            if (cachedData != null)
            {
                // Cache hit! Return cached data
                cacheHit = true;
                filterContext.HttpContext.Response.Write(cachedData);
                filterContext.Cancel = true;
            }
            else
            {
                // Cache not hit.
                // Replace the current context with a new context that writes to a string writer
                existingContext = System.Web.HttpContext.Current;
                writer = new StringWriter();
                HttpResponse response = new HttpResponse(writer);
                HttpContext context = new HttpContext(existingContext.Request, response)
                {
                    User = existingContext.User
                };

                // Copy all items in the context (especially done for session availability in the component)
                foreach (var key in existingContext.Items.Keys)
                {
                    context.Items[key] = existingContext.Items[key];
                }

                System.Web.HttpContext.Current = context;
            }
        }
    }

    By using this code, we can retrieve an existing item from cache and set up the HTTP response to be read from. But what about storing data in the cache? This will have to occur after the view has rendered:

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        // Server-side caching?
        if (CachePolicy == CachePolicy.Server || CachePolicy == CachePolicy.ClientAndServer)
        {
            if (!cacheHit)
            {
                // Restore the old context
                System.Web.HttpContext.Current = existingContext;

                // Return rendererd data
                existingContext.Response.Write(writer.ToString());

                // Add data to cache
                cache.Add(
                    GenerateKey(filterContext),
                    writer.ToString(),
                    null,
                    DateTime.Now.AddSeconds(Duration),
                    Cache.NoSlidingExpiration,
                    CacheItemPriority.Normal,
                     null);
            }
        }
    }

    Now you noticed I added a VaryByParam property to the OutputCache ActionFilterAttribute. When caching server-side, I can use this to vary cache storage by the parameters that are passed in. The GenerateKey method will actually generate a key depending on controller, action and the VaryByParam value:

    private string GenerateKey(ControllerContext filterContext)
    {
        StringBuilder cacheKey = new StringBuilder();

        // Controller + action
        cacheKey.Append(filterContext.Controller.GetType().FullName);
        if (filterContext.RouteData.Values.ContainsKey("action"))
        {
            cacheKey.Append("_");
            cacheKey.Append(filterContext.RouteData.Values["action"].ToString());
        }

        // Variation by parameters
        List<string> varyByParam = VaryByParam.Split(';').ToList();

        if (!string.IsNullOrEmpty(VaryByParam))
        {
            foreach (KeyValuePair<string, object> pair in filterContext.RouteData.Values)
            {
                if (VaryByParam == "*" || varyByParam.Contains(pair.Key))
                {
                    cacheKey.Append("_");
                    cacheKey.Append(pair.Key);
                    cacheKey.Append("=");
                    cacheKey.Append(pair.Value.ToString());
                }
            }
        }

        return cacheKey.ToString();
    }

    There you go! Now note that you can add this OutputCache attribute to any controller and any controller action you  have in your application. The full source code is available for download here.

    UPDATE: Make sure to read part 2, available here.

    kick it on DotNetKicks.com


    Categories: ASP.NET | C# | General | MVC | Personal

    ASP.NET MVC custom ActionResult (ImageResult)

    The ASP.NET MVC framework introduces the concept of returning an ActionResult in Controllers since the "preview preview" release on CodePlex. The purpose of this concept is to return a generic ActionResult object for each Controller method, allowing different child classes returning different results.

    An example ActionResult (built-in) is the RenderViewResult. Whenever you want to render a view, you can simply return an object of this class which will render a specific view in its ExecuteResult method. Another example is the HttpRedirectResult which will output an HTTP header (Location: /SomethingElse.aspx).

    In my opinion, this is a great concept, because it allows you to develop ASP.NET MVC applications more transparently. In this blog post, I will build a custom ActionResult class which will render an image to the HTTP response stream.

    ASP.NET MVC Custom ActionResultAs an example, let's create a page which displays the current time as an image.

    One option for implementing this would be creating an ASP.NET HttpHandler which renders this image and can be used inline with a simple HTML tag: <img src="DisplayTime.ashx" />

    Wouldn't it be nice to be able to do something more ASP.NET MVC-like? Let's consider the following: <%=Html.Image<HomeController>(c => c.DisplayTime(), 200, 50, "Current time")%>

    1. Creating the necessary HtmlHelper extension methods

    The above example code is not available in standard ASP.NET MVC source code. We'll need an extension method for this, which will map a specific controller action, width, height and alternate text to a standard HTML image tag:

    public static class ImageResultHelper
    {
        public static string Image<T>(this HtmlHelper helper, Expression<Action<T>> action, int width, int height)
            where T : Controller
        {
            return ImageResultHelper.Image<T>(helper, action, width, height, "");
        }

        public static string Image<T>(this HtmlHelper helper, Expression<Action<T>> action, int width, int height, string alt)
            where T : Controller
        {
            string url = helper.BuildUrlFromExpression<T>(action);
            return string.Format("<img src=\"{0}\" width=\"{1}\" height=\"{2}\" alt=\"{3}\" />", url, width, height, alt);
        }

    2. The custom ActionResult class

    Our new ImageResult class will inherit the abstract class ActionResult and implement its ExecuteResult method. This method basically performs communication over the HTTP response stream.

    public class ImageResult : ActionResult
    {
        public ImageResult() { }

        public Image Image { get; set; }
        public ImageFormat ImageFormat { get; set; }

        public override void ExecuteResult(ControllerContext context)
        {
            // verify properties
            if (Image == null)
            {
                throw new ArgumentNullException("Image");
            }
            if (ImageFormat == null)
            {
                throw new ArgumentNullException("ImageFormat");
            }

            // output
            context.HttpContext.Response.Clear();

            if (ImageFormat.Equals(ImageFormat.Bmp)) context.HttpContext.Response.ContentType = "image/bmp";
            if (ImageFormat.Equals(ImageFormat.Gif)) context.HttpContext.Response.ContentType = "image/gif";
            if (ImageFormat.Equals(ImageFormat.Icon)) context.HttpContext.Response.ContentType = "image/vnd.microsoft.icon";
            if (ImageFormat.Equals(ImageFormat.Jpeg)) context.HttpContext.Response.ContentType = "image/jpeg";
            if (ImageFormat.Equals(ImageFormat.Png)) context.HttpContext.Response.ContentType = "image/png";
            if (ImageFormat.Equals(ImageFormat.Tiff)) context.HttpContext.Response.ContentType = "image/tiff";
            if (ImageFormat.Equals(ImageFormat.Wmf)) context.HttpContext.Response.ContentType = "image/wmf";

            Image.Save(context.HttpContext.Response.OutputStream, ImageFormat);
        }
    }

    3. A "DisplayTime" action on the HomeController

    We'll add a DisplayTime action on the HomeController class, which will return an instance of the newly created class ImageResult:

    public ActionResult DisplayTime()
    {
        Bitmap bmp = new Bitmap(200, 50);
        Graphics g = Graphics.FromImage(bmp);

        g.FillRectangle(Brushes.White, 0, 0, 200, 50);
        g.DrawString(DateTime.Now.ToShortTimeString(), new Font("Arial", 32), Brushes.Red, new PointF(0, 0));

        return new ImageResult { Image = bmp, ImageFormat = ImageFormat.Jpeg };
    }

    And just to be complete, here's the markup of the index view on the HomeController:

    <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
    <%@ Import Namespace="MvcApplication1.Code" %>
    <%@ Import Namespace="MvcApplication1.Controllers" %>

    <asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
        <p>
            <%=Html.Image<HomeController>(c => c.DisplayTime(), 200, 50, "Current time")%>
        </p>
    </asp:Content>

    Want the source code? Download it here! You can use it with the current ASP.NET MVC framework source code drop.

    kick it on DotNetKicks.com  


    Categories: ASP.NET | C# | General | MVC | Personal | Software

    Having fun with project managers! (or: why you should lock your desktop)

    Have you ever left your computer unattended? (I do hope that!) Do you lock your desktop when this occurs? (I hope so either!) Not locking your desktop can be a risk. Your data might get stolen, someone might install a trojan, ...

    My project manager is one of those people who do not lock their computer when away. After having explained that this is a very simple thing he still seems to forget it everytime. Since a few weeks, we are using some more persuasive manners to teach him to press the Windows-key + L whenever he leaves his computer. Some practical jokes...

    1. Are those icons?

    • Create a screenshot of the user's desktop
    • Set this screenshot as the desktop background
    • Remove all real icons from the user's desktop (copy them somewhere to cause no real harm!)
    • Wait till the user gets back and starts clicking on his desktop "icons"... NOT Cool

    2. Cake for everyone!

    • Open the user's e-mail client
    • Send a message to the entire team saying "I'm treating everyone with cake!" (other option: "I'm buying a beer for everyone!")
    • Keep reminding the user of his nice e-mail Cool

    3. Right-click here...

    Here's a simple one: switch the user's mouse buttons (control panel - mouse properties - buttons). Also press the CTRL + ALT + Down-arrow. If you're lucky and the user has an Intl graphics card, his desktop will also be upside down.

    4. www.website.com...

    • If you have administrative rights on the user's PC, find and edit his host file (c:\windows\system32\drivers\etc\hosts)
    • Add a new entry which map his favourite website to something completely different. For example, map www.google.com to the IP address 208.77.188.166.

    5. Other funny things

    We've tried the above pranks, but no luck yet... Locking his desktop remains something that's not important to him (probably because he always has to laugh with practical jokes). Here's a list of some other jokes we might try in the near future...

    Any other suggestions, preferrably not harmful? Please let me know!

    kick it on DotNetKicks.com


    Categories: General | Personal

    Finally! My own custom BlogEngine.net template!

    Right after my blog move to BlogEngine.net, I decided to create a custom template for my blog to make it more unique in the blogosphere. Less than a year later (11 months, to be precise) I found the time to fire up my HTML and image editor to create a new look for my blog. Now who said developers are lazy?

    Old blog look New blog look


    Categories: General | Personal

    Thank you, ISP!

    Living in Belgium sometimes feels like living in the desert. Over the past few years, my ISP has always offered the same: a cable modem subscription with 10Mbit downstream speed, and 256Kbit upstream speed. Great! Except for that data transfer limit of 12 GB per month and the ridiculous price of 42 EUR (that is 61 US$). And no, there are few better alternatives in this center of Europe...

    Good news though! My ISP has been teasing its customers with a marketing campaign, focussing on great improvements in every Internet access subscription they offer. Rumours came along on different user forums: price drops, no more data transfer limits, ... Now here's the real improvement: everything stays the same, except you get a faster upload speed (512Kbit, yes!). Data transfer limit stays... (press release)

    12 GB of data transfer is filled quite fast at 10Mbps... Here's what I think, and many others too...

     
    (For the record: the information on this website represents my personal opinion. My opinion may differ with other people's opinion and my employer's opinion. This website is by no means related to other people nor my employer. )

    Categories: General | Personal