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

    ASP.NET MVC MvcSiteMapProvider 1.0 released

    image Back in March, I blogged about an experimental MvcSiteMap provider I was building. Today, I am proud to announce that it is stable enough to call it version 1.0! Download MvcSiteMapProvider 1.0 over at CodePlex.

    Ever since the source code release I did back in March, a lot of new features have been added, such as HtmlHelper extension methods, attributes, dynamic parameters, … I’ll leave most of them up to you to discover, but there are some I want to quickly highlight.

    kick it on DotNetKicks.com

    ACL module extensibility

    By default, MvcSiteMap will make nodes visible or invisible based on [Authorize] attributes that are placed on controllers or action methods. If you have implemented your own authentication mechanism, this may no longer be the best way to show or hide sitemap nodes. By implementing and registering the IMvcSiteMapAclModule interface, you can now plug in your own visibility logic.

    public interface IMvcSiteMapAclModule
    {
        /// <summary>
        /// Determine if a node is accessible for a user
        /// </summary>
        /// <param name="provider">The MvcSiteMapProvider requesting the current method</param>
        /// <param name="context">Current HttpContext</param>
        /// <param name="node">SiteMap node</param>
        /// <returns>True/false if the node is accessible</returns>

        bool IsAccessibleToUser(MvcSiteMapProvider provider, HttpContext context, SiteMapNode node);
    }

    Dynamic parameters

    Quite often, action methods have parameters that are not really bound to a sitemap node. For instance, take a paging parameter. You may ignore this one safely when determining the active sitemap node: /Products/List?page=1 and /Products/List?page=2 should both have the same menu item highlighted. This is where dynamic parameters come in handy: MvcSiteMap will completely ignore the specified parameters when determining the current node.

    <mvcSiteMapNode title="Products" controller="Products" action="List" isDynamic="true" dynamicParameters="page" />

    The above sitemap node will always be highlighted, whatever the value of “page” is.

    SiteMapTitle action filter attribute

    In some situations, you may want to dynamically change the SiteMap.CurrentNode.Title in an action method. This can be done manually by setting  SiteMap.CurrentNode.Title, or by adding the SiteMapTitle action filter attribute.

    Imagine you are building a blog and want to use the Blog’s Headline property as the site map node title. You can use the following snippet:

    [SiteMapTitle("Headline")]
    public ViewResult Show(int blogId) {
       var blog = _repository.Find(blogIdId);
       return blog;
    }

    You can also use a non-strong typed ViewData value as the site map node title:

    [SiteMapTitle("SomeKey")]
    public ViewResult Show(int blogId) {
       ViewData["SomeKey"] = "This will be the title";

       var blog = _repository.Find(blogIdId);
       return blog;
    }

    HtmlHelper extension methods

    MvcSiteMap provides different HtmlHelper extension methods which you can use to generate SiteMap-specific HTML code on your ASP.NET MVC views. Here's a list of available HtmlHelper extension methods.

    • HtmlHelper.Menu() - Can be used to generate a menu
    • HtmlHelper.SiteMap() - Can be used to generate a list of all pages in your sitemap
    • HtmlHelper.SiteMapPath() - Can be used to generate a so-called "breadcrumb trail"

    The MvcSiteMap release can be found on CodePlex.

    kick it on DotNetKicks.com


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

    Signed Access Signatures and PHP SDK for Windows Azure

    PHP SDK for Windows Azure The latest Windows Azure storage release featured a new concept: “Shared Access Signatures”. The idea of those is that you can create signatures for specific resources in blob storage and that you can provide more granular access than the default “all-or-nothing” approach that is taken by Azure blob storage. Steve Marx posted a sample on this, demonstrating how you can provide read access to a blob for a specified amount of minutes, after which the access is revoked.

    The PHP SDK for Windows Azure is now equipped with a credentials mechanism, based on Signed Access Signatures. Let’s see if we can demonstrate how this would work…

    kick it on DotNetKicks.com

    A quick start…

    Let’s take Steve’s Wazdrop sample and upload a few files, we get a set of permissions:

    https://wazdrop.blob.core.windows.net/files/7bf9417f-c405-4042-8f99-801acb1ea494?st=2009-08-17T08%3A52%3A48Z&se=2009-08-17T09%3A52%3A48Z&sr=b&sp=r&sig=Zcngfaq60OXtLxcsTjmPXUL9Q4Rj3zTPmW40eARVYxU%3D

    https://wazdrop.blob.core.windows.net/files/d30769f6-35b9-4337-8c34-014ff590b18f?st=2009-08-17T08%3A54%3A19Z&se=2009-08-17T09%3A54%3A19Z&sr=b&sp=r&sig=Mm8CnmI3XXVbJ6y0FN9WfAOknVySfsF5jIA55drZ6MQ%3D

    If we take a detailed look, the Azure account name used is “wazdrop”, and we have access to 2 files in Steve’s storage account, namely “7bf9417f-c405-4042-8f99-801acb1ea494” and “d30769f6-35b9-4337-8c34-014ff590b18f” in the “files” container.

    Great! But if I want to use the PHP SDK for Windows Azure to access the resources above, how would I do that? Well, that should not be difficult. Instantiate a new Microsoft_Azure_Storage_Blob client, and pass it a new Microsoft_Azure_SharedAccessSignatureCredentials instance:

    $storageClient = new Microsoft_Azure_Storage_Blob('blob.core.windows.net', 'wazdrop', '');
    $storageClient->setCredentials(
        new Microsoft_Azure_SharedAccessSignatureCredentials('wazdrop', '')
    );

    One thing to notice here: we do know the storage account (“wazdrop”), but not Steve’s shared key to his storage account. Which is good for him, otherwise I would be able to manage all containers and blobs in his account.

    The above code sample will now fail every action I invoke on it. Every getBlob(), putBlob(), createContainer(), … will fail because I cannot authenticate! Fortunately, Steve’s application provided me with two URL’s that I can use to read 2 blobs. Now set these as permissions on our storage client:

    $storageClient->getCredentials()->setPermissionSet(array(
        'https://wazdrop.blob.core.windows.net/files/7bf9417f-c405-4042-8f99-801acb1ea494?st=2009-08-17T08%3A52%3A48Z&se=2009-08-17T09%3A52%3A48Z&sr=b&sp=r&sig=Zcngfaq60OXtLxcsTjmPXUL9Q4Rj3zTPmW40eARVYxU%3D',
        'https://wazdrop.blob.core.windows.net/files/d30769f6-35b9-4337-8c34-014ff590b18f?st=2009-08-17T08%3A54%3A19Z&se=2009-08-17T09%3A54%3A19Z&sr=b&sp=r&sig=Mm8CnmI3XXVbJ6y0FN9WfAOknVySfsF5jIA55drZ6MQ%3D'
    ));

    We now have instructed the PHP SDK for Windows Azure that we have read permissions on two blobs, and can now use regular API calls to retrieve these blobs:

    $storageClient->getBlob('files', '7bf9417f-c405-4042-8f99-801acb1ea494', 'C:\downloadedfile1.txt');
    $storageClient->getBlob('files', 'd30769f6-35b9-4337-8c34-014ff590b18f', 'C:\downloadedfile2.txt');

    The PHP SDK for Windows Azure will now take care of checking if a permission URL matches the call that is being made, and inject the signatures automatically.

    A bit more advanced…

    The above sample did demonstrate how the new Signed Access Signature is implemented in PHP SDK for Windows Azure, but it did not yet demonstrate all “coolness”. Let’s say the owner of a storage account named “phpstorage” has a private container named “phpazuretestshared1”, and that this owner wants to allow you to put some blobs in this container. Since the owner does not want to give you full access, nor wants to make the container public, he issues a Shared Access Signature:

    http://phpstorage.blob.core.windows.net/phpazuretestshared1?st=2009-08-17T09%3A06%3A17Z&se=2009-08-17T09%3A56%3A17Z&sr=c&sp=w&sig=hscQ7Su1nqd91OfMTwTkxabhJSaspx%2BD%2Fz8UqZAgn9s%3D

    This one allows us to write in the container “phpazuretest1” on account “phpstorage”. Now let’s see if we can put some blobs in there!

    $storageClient = new Microsoft_Azure_Storage_Blob('blob.core.windows.net', 'phpstorage', '');
    $storageClient->setCredentials(
        new Microsoft_Azure_SharedAccessSignatureCredentials('phpstorage', '')
    );

    $storageClient->getCredentials()->setPermissionSet(array(
        'http://phpstorage.blob.core.windows.net/phpazuretestshared1?st=2009-08-17T09%3A06%3A17Z&se=2009-08-17T09%3A56%3A17Z&sr=c&sp=w&sig=hscQ7Su1nqd91OfMTwTkxabhJSaspx%2BD%2Fz8UqZAgn9s%3D'
    ));

    $storageClient->putBlob('phpazuretestshared1', 'NewBlob.txt', 'C:\Files\dataforazure.txt');

    Did you see what happened? We did not specify an explicit permission to write to a specific blob. Instead, the PHP SDK for Windows Azure determined that a permission was required to either write to that specific blob, or to write to its container. Since we only had a signature for the latter, it chose those credentials to perform the request on Windows Azure blob storage.

    kick it on DotNetKicks.com


    Categories: Azure | CodePlex | General | ICT | Internet | PHP | Projects

    ASP.NET MVC 2 Preview 1 released!

    Today, Phil Haack did a blog post on the release of ASP.NET MVC 2 Preview 1! Get it while it’s fresh :-) An updated roadmap is also available on CodePlex.

    Guess now is about time to start revising my ASP.NET MVC 1.0 Quickly book…

    kick it on DotNetKicks.com

    New features in ASP.NET MVC Preview 1

    Templated helpers

    Templated helpers are not new: ASP.NET Dynamic Data already used this feature. Basically, you are creating a default control when you want to display/edit a specific data type in a view. For example, a System.String will have a user control defined that renders a textbox. However, if you want this to be a TinyMCE control by default, you’ll have to change the templated helper in one place and you’re done.

    More concrete: create a new view in your application: Views\Shared\DisplayTemplates\String.ascx. The code for that view would be:

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
    <strong><%= Html.Encode(Model) %></strong>

    There you go: every string you want to put in a view using the <%= Html.DisplayFor(c => person.Name) %> HtmlHelper will render that string in bold.

    Note that your domain class can also use UI hints to specify the templated helper to use when rendering:

    public class Person {
        [UIHint("NameTextBox")]
        public string Name { get; set; }

        // ...
    }

    This will make sure that when Person’s Name is rendered, the NameTextBox.ascx control will be used instead of the default one.

    Areas

    Finally, native support for areas! Areas help you split your application into more logical subsections, which is useful when working with large projects.Each area is implemented as a separate ASP.NET MVC. When compiling, ASP.NET MVC invokes a build task which merges all areas into the main application.

    Check MSDN for a detailed example on using areas. I’ll get this one in MvcSiteMap as soon as possible.

    Support for DataAnnotations

    The new ASP.NET MVC 2 default model binder makes use of the System.ComponentModel.DataAnnotations namespace to perform validation at the moment of binding data to the model. This concept was used for ASP.NET Dynamic Data, recently picked up by the RIA services team and now also available for ASP.NET MVC.

    Basically, what you have to do in order to validate your domain objects, is decorating the class’properties with some DataAnnotations:

    public class Person {
        [Required(ErrorMessage = "Name is required.")]
        [StringLength(60, ErrorMessage = "Name should not exceed 60 characters.")]
        public string Name { get; set; }

        // ...
    }

    Easy no? Now just use the model binder inside your controller and validation will occur “automagically”.

    Also check my blog post on TwitterMatic for another example.

    HttpPost attribute

    A small update: [AcceptVerbs(HttpVerbs.Post)] can now be written as [HttpPost]. Easier to read IMHO.

    This means that:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(Person person) {
        // ...
    }

    becomes the following:

    [HttpPost]
    public ActionResult Create(Person person) {
        //...
    }

    DefaultValueAttribute

    Default parameter values in an action method can now be specified using an attribute. This attribute currently only seems to support primitive types (such as integers, booleans, strings, …). Here’s an example:

    public class PersonController : Controller {
        public ActionResult Create([DefaultValue("Maarten")]string name) {
            // ...
        }
    }

    kick it on DotNetKicks.com


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

    Query the cloud with PHP (PHPLinq and Windows Azure)

    PHPLinq Architecture I’m pleased to announce PHPLinq currently supports basic querying of Windows Azure Table Storage. 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.

    Next to PHPLinq querying arrays, XML and objects, which was already supported, PHPLinq now enables you to query Windows Azure Table Storage in the same manner as you would query a list of employees, simply by passing PHPLinq a Table Storage client and table name as storage hint in the in() method:

    $result = from('$employee')->in( array($storageClient, 'employees', 'AzureEmployee') )
                ->where('$employee => $employee->Name == "Maarten"')
                ->select('$employee');

    The Windows Azure Table Storage layer is provided by Microsoft’s PHP SDK for Windows Azure and leveraged by PHPLinq to enable querying “the cloud”.

    kick it on DotNetKicks.com


    PHP SDK for Windows Azure - Milestone 2 release

    WindowsAzure I’m proud to announce our second milestone for the PHP SDK for Windows Azure project that Microsoft and RealDolmen started back in May. Next to our regular releases on CodePlex, we’ll also be shipping a Zend Framework version of the PHP SDK for Windows Azure. Announcements on this will be made later.

    The current milestone is focused on Windows Azure Table Storage, enabling you to use all features this service offers from any PHP application, be it hosted in-premise or on Windows Azure.

    Get it while it’s hot: PHP SDK for Windows Azure CTP2 - PHPAzure CTP2 (0.2.0)

    Detailed API documentation is provided in the download package, while more descriptive guidance is available on the project site.

    Working with Azure Table Storage from PHP

    Let’s provide a small example on the new Table Storage support in the PHP SDK for Windows Azure. The first thing to do when you have a clean storage account on the Azure platform is to create a new table:

    /** Microsoft_Azure_Storage_Table */
    require_once 'Microsoft/Azure/Storage/Table.php';

    $storageClient = new Microsoft_Azure_Storage_Table('table.core.windows.net', 'myaccount', 'myauthkey');
    $storageClient->createTable('mynewtable');

    Easy, no? Note that we did not provide any schema information here as you would do in a regular database. Windows Azure Table Storage can actually contain entities with different properties in the same table. You can work with an enforced schema, but this will be client-side. More info on that matter is available here.

    Now let’s add a person to the “mynewtable” in the cloud:

    $person = new Microsoft_Azure_Storage_DynamicTableEntity('partition1', 'row1');
    $person->Name = "Maarten";
    $person->Age  = 25;

    $storageClient->insertEntity('mynewtable', $person);

    Again, no rocket science. The Microsoft_Azure_Storage_DynamicTableEntity class used provides fluent access to entities in Table Storage. More info on this class is available here.

    Now let’s add a property to this $person instance and merge it into Table Storage:

    $person->Blog = "www.maartenballiauw.be";
    $storageClient->mergeEntity('mynewtable', $person);

    Wow! We just added a Blog property to this object! I could have also used updateEnity for this, but that one would have overwritten eventual changes that were made to my $person in the meantime.

    Now for some querying. Let’s retrieve all entities in “mynewtable” that have an Age of 25:

    $entities = $storageClient->storageClient->retrieveEntities(
        'mynewtable',
        $storageClient->select()
                      ->from($tableName)
                      ->where('Age eq ?', 25)
    );

    foreach ($entities as $entity)
    {
        echo 'Name: ' . $entity->Name . "\n";
    }

    I guess this al looks quite straightforward. The fluent query building API provides a syntax similar to how you would build a query in SQL.

    Another nice feature of the PHP SDK for Windows Azure is support for batch transactions. Here’s an example of how to work with transactions on Table Storage:

    // Start batch
    $batch = $storageClient->startBatch();

    // Insert entities in batch
    $entities = array( ...... );
    foreach ($entities as $entity)
    {
        $storageClient->insertEntity('mynewtable', $entity);
    }

    // Commit
    $batch->commit();

    The batch will fail as a whole if one insert, update, delete, ... does not work out, just like with a transaction on a regular relational database like MySQL or SQL Server.

    If you're interested in cloud computing and WIndows Azure, and want to keep using PHP, make sure to get the latest version of the PHP SDK for Windows Azure to leverage all functionality that is available in the cloud. Here's the link: PHP SDK for Windows Azure CTP2 - PHPAzure CTP2 (0.2.0)


    ASP.NET MVC TDD using Visual Studio 2010

    Phil Haack announced yesterday that the tooling support for ASP.NET MVC is available for Visual Studio 2010. Troy Goode already blogged about the designer snippets (which are really really cool, just like other parts of the roadmap for ASP.NET MVC 2.0). I’ll give the new TDD workflow introduced in VS2010 a take.

    kick it on DotNetKicks.com

    Creating a new controller, the TDD way

    First of all, I’ll create a new ASP.NET MVC application in VS2010. After installing the project template (and the designer snippets if you are cool), this is easy in VS2010:

    Step 1

    Proceed and make sure to create a unit test project as well.

    Next, in your unit test project, add a new unit test class and name it DemoControllerTests.cs.

    Step 2Go ahead and start typing the following test:

    Step 3Now when you type CTRL-. (or right click the DemoController unknown class), you can pick “Generate other…”:

    Step 4A new window will appear,  where you can select the project where you want the new DemoController class to be created. Make sure to enter the MvcApplication project here (and not your test project).

    Step 5

    Great, that class has been generated. But how about the constructor accepting List<string>? Press CTRL-. and proceed with the suggested action.

    Step 6

    Continue typing your test and let VS2010 also implement the Index() action method.

    Step 7You can now finish the test code:

    Step 8The cool thing is: we did not have to go out of our DemoControllerTests.cs editor while writing this test class, while VS2010 took care of stubbing my DemoController in the background:Step 9Run your tests and see it fail. That’s the TDD approach: first make it fail, and then implement what’s needed:

    Step 10

    If you run your tests  now, you’ll see the test pass.

    Conclusion

    I like this new TDD approach and ASP.NET MVC! It’s not ReSharper yet, but I think its a fine step that the Visual Studio team has taken.

    kick it on DotNetKicks.com


    Categories: ASP.NET | C# | CodePlex | General | ICT | Internet | MVC | VSTS | VS2010

    ConnectedShow Podcast - PHP SDK for Windows Azure

    The fifth episode of the ConnectedShow podcast is up. This podcast is all about cloud computing, Windows Azure, … Recently, they have asked me if I wanted to be in one of their podcasts on the PHP SDK for Windows Azure.

    In this episode Dmitry welcomes a new co-host, Peter Laudati. Next, we speak to Maarten Balliauw about the new PHP SDK for Windows Azure which is designed to help PHP developers use Windows Azure services.

    Here’s the link to the podcast: http://www.connectedshow.com/default.aspx?Episode=5


    Announcing PHP SDK for Windows Azure

    As part of Microsoft’s commitment to Interoperability, a new open source project has just been released on CodePlex: PHP SDK for Windows Azure, bridging PHP developers to Windows Azure. PHPAzure is an open source project to provide software development kit for Windows Azure and Windows Azure Storage – Blobs, Tables & Queues. I’m pleased that Microsoft has chosen RealDolmen and me to work on the PHP SDK for Windows Azure.

    logomicrosoft logorealdolmen

    Windows Azure provides an open, standards-based and interoperable environment with support for multiple internet protocols.  This helps reduce the cost of running a mixed IT environment.  Azure building block services use XML, REST and SOAP standards so they can be called from other platforms and programming languages.  Developers can create their own services and applications that conform to internet standards. Next to the new PHP SDK for Windows Azure, Microsoft also shipped Java and Ruby SDK for .NET Services demonstrating how heterogeneous languages and frameworks could take advantage of interoperable Identity Service (Access Control) & Service Bus using SOAP and REST-based frameworks.

    • Overview
      • Enables PHP developers to take advantage of the Microsoft Cloud Services Platform  – Windows Azure
      • Provides consistent programming model for Windows Azure Storage (Blobs, Tables & Queues)
    • Features
      • PHP classes for Windows Azure Blobs, Tables & Queues (for CRUD operations)
      • Helper Classes for HTTP transport, AuthN/AuthZ, REST & Error Management
      • Manageability, Instrumentation & Logging support

    The logical architecture of PHP SDK for Windows Azure is as follows: it provides access to Windows Azure's storage, computation and management interfaces by abstracting the REST/XML interface Windows Azure provides into a simple PHP API.

    logical_architecture

    An application built using PHP SDK for Windows Azure can access Windows Azure's features, no matter if it is hosted on the Windows Azure platform or on an in-premise web server.

    deployment_scenario

    You can contribute, provide feature requests & test your own enhancements to the toolkit by joining the user forum.

    kick it on DotNetKicks.com


    PHPPowerPoint 0.1.0 (CTP1) released!

    PHPPowerPoint logo People following me on Twitter could have already guessed, but here’s something I probably should not have done for my agenda: next to the well known PHPExcel class library, I’ve now also started something similar for PowerPoint: PHPPowerPoint.

    Just like with PHPExcel, PHPPowerPoint can be used to generate PPTX files from a PHP application. This can be done by creating an in-memory presentation that consists of slides and different shapes, which can then be written to disk using a writer (of which there’s currently only one for PowerPoint 2007).

    Simple PHPPowerPoint demo Here’s some sample code:

    /* Create new PHPPowerPoint object */
    $objPHPPowerPoint = new PHPPowerPoint();

    /* Create slide */
    $currentSlide = $objPHPPowerPoint->getActiveSlide();

    /* Create a shape (drawing) */
    $shape = $currentSlide->createDrawingShape();
    $shape->setName('PHPPowerPoint logo');
    $shape->setDescription('PHPPowerPoint logo');
    $shape->setPath('./images/phppowerpoint_logo.gif');
    $shape->setHeight(36);
    $shape->setOffsetX(10);
    $shape->setOffsetY(10);
    $shape->getShadow()->setVisible(true);
    $shape->getShadow()->setDirection(45);
    $shape->getShadow()->setDistance(10);

    /* Create a shape (text) */
    $shape = $currentSlide->createRichTextShape();
    $shape->setHeight(300);
    $shape->setWidth(600);
    $shape->setOffsetX(170);
    $shape->setOffsetY(180);
    $shape->getAlignment()->setHorizontal( PHPPowerPoint_Style_Alignment::HORIZONTAL_CENTER );
    $textRun = $shape->createTextRun('Thank you for using PHPPowerPoint!');
    $textRun->getFont()->setBold(true);
    $textRun->getFont()->setSize(60);
    $textRun->getFont()->setColor( new PHPPowerPoint_Style_Color( 'FFC00000' ) );

    /* Save PowerPoint 2007 file */
    $objWriter = PHPPowerPoint_IOFactory::createWriter($objPHPPowerPoint, 'PowerPoint2007');
    $objWriter->save(str_replace('.php', '.pptx', __FILE__));

    Advanced sample A more advanced sample is also included in the download, where a complete presentation is rendered using PHPPowerPoint.

    Now go grab the fresh sample on CodePlex and be the very first person downloading and experimenting with it. Feel free to post some feature requests or general remarks on CodePlex too.

    I want to thank my employer, RealDolmen, for letting me work on this during regular office hours and also the people at DynamicLogic who convinced me to start this new project.


    Back to the future! Exploring ASP.NET MVC Futures

    Back to the future!For those of you who did not know yet: next to the ASP.NET MVC 1.0 version and its source code, there’s also an interesting assembly available if you can not wait for next versions of the ASP.NET MVC framework: the MVC Futures assembly. In this blog post, I’ll provide you with a quick overview of what is available in this assembly and how you can already benefit from… “the future”.

    kick it on DotNetKicks.com 

    First things first: where to get this thing? You can download the assembly from the CodePlex releases page. Afterwards, reference this assembly in your ASP.NET MVC web application. Also add some things to the Web.config file of your application:

    <?xml version="1.0"?>
    <configuration>
        <!-- ... -->
        <system.web>
            <!-- ... -->

            <pages>
                <controls>
                    <!-- ... -->
                    <add tagPrefix="mvc" namespace="Microsoft.Web.Mvc.Controls" assembly="Microsoft.Web.Mvc"/>
                </controls>
                <namespaces>
                    <!-- ... -->
                    <add namespace="Microsoft.Web.Mvc"/>
                    <add namespace="Microsoft.Web.Mvc.Controls"/>
                </namespaces>
            </pages>

            <!-- ... -->
        </system.web>
        <!-- ... -->
    </configuration>

    You are now ready to go! Buckle up and start your De Lorean DMC-12…

    Donut caching (a.k.a. substitution)

    If you have never heard of the term “donut caching” or “substitution”, now is a good time to read a previous blog post of mine. Afterwards, return here. If you don’t want to click that link: fine! Here’s in short: “With donut caching, most of the page is cached, except for some regions which are able to be substituted with other content.”

    You’ll be needing an OutputCache-enabled action method in a controller:

    [OutputCache(Duration = 10, VaryByParam = "*")]
    public ActionResult DonutCaching()
    {
        ViewData["lastCached"] = DateTime.Now.ToString();

        return View();
    }

    Next: a view. Add the following lines of code to a view:

    <p>
        This page was last cached on: <%=Html.Encode(ViewData["lastCached"])%><br />
        Here's some "donut content" that is uncached: <%=Html.Substitute( c => DateTime.Now.ToString() )%>
    </p>

    There you go: when running this application, you will see one DateTime printed in a cached way (refreshed once a minute), and one DateTime printed on every page load thanks to the substitution HtmlHelper extension. This extension method accepts a HttpContext instance which you can also use to enhance the output.

    Now before you run away and use his in your projects: PLEASE, do not do write lots of code in your View. Instead, put the real code somewhere else so your view does not get cluttered and your code is re-usable. In an ideal world, this donut caching would go hand in hand with our next topic…

    Render action methods inside a view

    You heard me! We will be rendering an action method in a view. Yes, that breaks the model-view-controller design pattern a bit, but it gives you a lot of added value while developing applications! Look at this like “partial controllers”, where you only had partial views in the past. If you have been following all ASP.NET MVC previews before, this feature already existed once but has been moved to the futures assembly.

    Add some action methods to a Controller:

    public ActionResult SomeAction()
    {
        return View();
    }

    public ActionResult CurrentTime()
    {
        ViewData["currentTime"] = DateTime.Now.ToString();

        return View();
    }

    This indeed is not much logic, but here’s the point: the SomeAction action method will render a view. That view will then render the CurrentTime action method, which will also render a (partial) view. Both views are combined and voila: a HTTP response which was generated by 2 action methods that were combined.

    Here’s how you can render an action method from within a view:

    <% Html.RenderAction("CurrentTime"); %>

    There’s also lambdas to perform more complex actions!

    <% Html.RenderAction<HomeController>(c => c.CurrentTime()); %>

    What most people miss: controls

    Lots of people are missing something when first working with the ASP.NET MVC framework: “Where are all the controls? Why don’t all ASP.NET Webforms controls work?” My answer would normally be: “You don’t need them.”, but I now also have an alternative: “Use the futures assembly!”

    Here’s a sample controller action method:

    public ActionResult Controls()
    {
        ViewData["someData"] = new[] {
            new {
                Id = 1,
                Name = "Maarten"
            },
            new {
                Id = 2,
                Name = "Bill"
            }
        };

        return View();
    }

    The view:

    <p>
        TextBox: <mvc:TextBox Name="someTextBox" runat="server" /><br />
        Password: <mvc:Password Name="somePassword" runat="server" />
    </p>
    <p>
        Repeater:
        <ul>
        <mvc:Repeater Name="someData" runat="server">
            <EmptyDataTemplate>
                <li>No data is available.</li>
            </EmptyDataTemplate>
            <ItemTemplate>
                <li><%# Eval("Name") %></li>
            </ItemTemplate>
        </mvc:Repeater>
        </ul>
    </p>

    As you can see: these controls all work quite easy. The "Name property accepts the key in the ViewData dictionary and will render the value from there. In the repeater control, you can even work with “good old” Eval: <%# Eval("Name") %>.

    Extra HtmlHelper extension methods

    Not going in too much detail here: there are lots of new HtmlHelper extension methods. The ones I especially like are those that allow you to create a hyperlink to an action method using lambdas:

    <%=Html.ActionLink<HomeController>(c => c.ShowProducts("Books"), "Show books")%>

    Here’s a list of new HtmlHelper extension methods:

    • ActionLink – with lambdas
    • RouteLink – with lambdas
    • Substitute (see earlier in this post)
    • JavaScriptStringEncode
    • HiddenFor, TextFor, DropDownListFor, … – like Hidden, Text, … but with lambdas
    • Button
    • SubmitButton
    • Image
    • Mailto
    • RadioButtonList

    More model binders

    Another thing I will only cover briefly: there are lots of new ModelBinders included! Model binders actually allow you to easily map input from a HTML form to parameters in an action method. That being said, here are the new kids on the block:

    • FileCollectionModelBinder – useful for HTTP posts that contain uploaded files
    • LinqBinaryModelBinder
    • ByteArrayModelBinder

    When you want to use these, do not forget to register them with ModelBinders.Binders in your Global.asax.

    More ActionFilters and ResultFilters

    Action filters and result filters are used to intercept calls to an action method or view rendering, providing a hook right before and after that occurs. This way, you can still modify some variables in the request or response prior to, for example, executing an action method. Here’s what is new:

    • AcceptAjaxAttribute – The action method is only valid for AJAX requests. It allows you to have different action methods for regular requests and AJAX requests.
    • ContentTypeAttribute – Sets the content type of the HTTP response
    • RequireSslAttribute – Requires SSL for the action method to execute. Allows you to have a different action method for non-SSL and SSL requests.
    • SkipBindingAttribute – Skips executing model binders for an action method.

    Asynchronous controllers

    This is a big one, but it is described perfectly in a Word document that can be found on the MVC Futures assembly release page. In short:

    The AsyncController is an experimental class to allow developers to write asynchronous action methods. The usage scenario for this is for action methods that have to make long-running requests, such as going out over the network or to a database, and don’t want to block the web server from performing useful work while the request is ongoing.

    In general, the pattern is that the web server schedules Thread A to handle some incoming request, and Thread A is responsible for everything up to launching the action method, then Thread A goes back to the available pool to service another request. When the asynchronous operation has completed, the web server retrieves a Thread B (which might be the same as Thread A) from the thread pool to process the remainder of the request, including rendering the response. The diagram below illustrates this point.

    Asynchronous controllers

    Sweet! Should speed up your ASP.NET MVC web application when it has to handle much requests.

    Conclusion

    I hope you now know what the future for ASP.NET MVC holds. It’s not sure all of this will ever make it into a release, but you are able to use all this stuff from the futures assembly. If you are too tired to scroll to the top of this post after reading it, here’s the link to the futures assembly again: MVC Futures assembly

    kick it on DotNetKicks.com


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