Learning Razor–Writing an Inline Recursive HTML Helper

by rhernandez 10. November 2010 08:54

I have been using Spark (http://www.sparkviewengine.com) as my default view engine for the past 5 or 6 months and I love everything about it.  I like its elegance, simplicity and I depend on some of its features to be efficient in doing most of my daily tasks.   That being said, there is a new kid on the block and his name is Razor.  Razor, will be an out of the box alternative for the ASP.NET WebForm’s view engine for ASP.NET MVC3 (Read Scott Guthrie’s blog on the topic here).   I don’t intend to write a full blown tutorial on Razor,  but as I learn the basics for this alternative view engine, I will try to write some “Learning Razor” posts that relate my experience in learning this new technology.

 

Writing an Inline Recursive Html Helper

The Spark view engine provides you with the ability to define inline macros that allow for recursive calls (Read Louis DeJardin blog on the topic here, and additional documentation here).  These macros are extremely useful for rendering a hierarchical structure such as the one in the following snippet.

 

<ul>
  <li>Fuller, Andrew
    <ul>
      <li>Davolio, Nancy</li>
      <li>Leverling, Janet</li>
      <li>Peacock, Margaret</li>
      <li>Buchanan, Steven
        <ul>
          <li>Suyama, Michael</li>
          <li>King, Robert</li>
          <li>Dodsworth, Anne</li>
        </ul>
      </li>
      <li>Callahan, Laura</li>
    </ul>
  </li>
</ul>

 

Now, the Razor view engine allows you to easily build a hierarchical structure by the use of inline HTML helpers that can be called recursively.  The following is a basic snippet of a “Hello World” inline HTML helper, and a call to trigger its functionality.

 

@HelloWorld("Roberto!")

@helper HelloWorld(string name) {
    <h1>Hello World! @name</h1>
}

 

Finally, if we wanted to output the html from the first snippet using Razor we could write the following inline HTML helper.

 

@model IEnumerable<OrganizationNodeViewModel>
@using MVC3.Playground.ViewModels;
@{
    View.Title = "OrganizationTree";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>OrganizationTree</h2>

@OrgTree(Model, null);

@helper OrgTree(IEnumerable<OrganizationNodeViewModel> nodes, int? parentId) {
    if (nodes.Any(n => n.ParentId == parentId)) { 
    <ul>
        @foreach (var node in nodes.Where(n => n.ParentId == parentId)) {
            <li>
                @node.DisplayName
                @OrgTree(nodes, node.Id)
            </li>
        }
    </ul>
    }
}

MVC Model Validation–Refactor (Part Deux)

by rhernandez 9. November 2010 10:36

This post enhances the functionality of the code in the Blog titled “MVC2 Validation and Testing” at the following link. 
http://blog.overridethis.com/blog/post/2010/04/22/MVC2-Model-Validation-and-Testing-Scenarios.aspx

 

A comment was made on one of my previous blogs requesting additional functionality for the extension method I wrote in April for testing controller action’s that rely on MVC2 Model Validation.  The request was simple, to be able to test class level validation attributes such as the ones found on the ChangePasswordModel in the default MVC2 project template.   Well, as requested!

 

public static class ControllerExtensions {

    public static ActionResult CallWithModelValidation<TController, TResult, TModel>(
            this TController controller, 
            Func<TController, TResult> action, 
            TModel model)
        where TController : Controller
        where TResult : ActionResult
        where TModel : class {

        var provider = new DataAnnotationsModelValidatorProvider();

        var metadata = new List<ModelMetadata>();
        metadata.Add(GetMetadataForClass(model));
        metadata.AddRange(GetMetadataForProperties(model));

        foreach (ModelMetadata modelMetadata in metadata) {
            ApplyValidatorsFromMetadata(model, provider, modelMetadata, controller);
        }        
        
        return action(controller);
    }

    private static ModelMetadata GetMetadataForClass<TModel>(TModel model) 
        where TModel : class {

        return ModelMetadataProviders
            .Current
            .GetMetadataForType(() => model, typeof (TModel));
    }

    private static IEnumerable<ModelMetadata> GetMetadataForProperties<TModel>(TModel model)
       where TModel : class {
        return ModelMetadataProviders
            .Current
            .GetMetadataForProperties(model, typeof(TModel));
    }

    private static void ApplyValidatorsFromMetadata<TModel, TController>(TModel model, 
        DataAnnotationsModelValidatorProvider provider, 
        ModelMetadata modelMetadata, 
        TController controller)
            where TController : Controller
            where TModel : class {
        
        IEnumerable<ModelValidator> validators = provider
            .GetValidators(modelMetadata, new ControllerContext());
            
        foreach (ModelValidator validator in validators) {
            IEnumerable<ModelValidationResult> results = validator.Validate(model);
            foreach (ModelValidationResult result in results)
                controller.ModelState.AddModelError(
                    modelMetadata.PropertyName ?? "Model", 
                    result.Message);
        }
    }
}

MVC Extensibility–CMAP Code Camp

by rhernandez 7. November 2010 01:27

downloadThe following is the download link for the demo code and slides for my presentation on MVC Extensibility done at the Central Maryland Association of .NET Professionals Code Camp (CMAP Code Camp).  Thanks to all who attended my presentation, it was extremely fun plowing through a ton of code all across the stack of the ASP.NET MVC Framework request execution lifecycle.

 

Download Demo Code & Slides

 

Also, big thanks to Christopher Steen and Randy Hayes for hosting and allowing me to participate as a speaker in such a wonderful event.

Code and Slides on “Intro to NHibernate 3.0 Alpha”

by rhernandez 9. October 2010 12:00

As promised, and in record time, the code and slides for my presentation on NHibernate 3.0 Alpha are now available for download.  As usual, I would like to express my thanks to Justin Etheredge and Kevin Hazzard for hosting and allowing me to present at Richmond Code Camp 2010.2 (http://www.richmondcodecamp.org).

 

The following are links to the materials used in the presentation.

 

Download Slides & Demo Code

 

Happy coding in .NET!!!

image      Richmond Code Camp

Microsoft C# MVP 2010 – Thank You!

by rhernandez 2. October 2010 01:34

I got an email yesterday congratulating and welcoming me as a Microsoft C# MVP for 2010.  I tweeted about it but had a hard time coming up with words (140 chars) that expressed my gratitude towards the Virginia, Maryland, and DC developer community. This award would not have happened without their support. 

 

I moved to the region in late 2007 and I was saddened to leave behind a lot of the communities that I  had helped to build in Puerto Rico and the Dominican Republic. But, I was excited and impressed with the large number of developer communities that thrive in the region and the quality and professionalism of the leaders that run these communities.  As a developer and active participant of many of these developer communities I encourage you to exploit these invaluable resources of knowledge and growth.

 

A special thanks to,

Washington, DC -  District Of Columbia Developer’s Community (DCDNUG)

Maryland – Central Maryland Association of .NET Professionals (CMAP)

Maryland – Rockville .NET User’s Group (ROCKNUG)

Virginia – Capital Area .NET User’s Group (CAPAREA)

Virginia – ALT.NET DC Chapter (ALTNETDC)

Virginia – Richmond Code Camp (RichCC)

The Author



Roberto Hernández

 

Currently a Managing Consultant for Excella in Arlington, VA. I have been architecting and building software solutions using Microsoft technology for the past 14 years. I was awarded as a Microsoft MVP in C# in 2007,2008 and 2010. I am originally from the Dominican Republic, and the proud father of two beautiful daughters that make my life special. You can track me down on twitter (@hernandezrobert) and on this blog http://overridethis.com.


 

Stack Overflow profile for Roberto Hernandez at Stack Overflow, Q&A for professional and enthusiast programmers

INETA Community Speakers Program

Recent Posts