Tim Scott's Blog

May 18, 2009

Use MvcContrib.FluentHtml With Spark View Engine

Filed under: FluentHtml, MS MVC, Spark View Engine — Tim Scott @ 11:04 pm

Introduction

MvcContrib.FluentHtml is a library of extensible HTML helpers for MS MVC.  It works out of the box with the WebForms view engine. As it turns out, it’s not very hard to use with other view engines.  Read on to see how to use FluentHtml with the Spark view engine.

View Class

First, you need to add a class to your project, something like this:

public abstract class SparkModelViewPage<T> : SparkView<T>, IViewModelContainer<T> where T : class
{
    private readonly List<IBehaviorMarker> behaviors = new List<IBehaviorMarker>();

    protected SparkModelViewPage()
    {
        behaviors.Add(new ValidationBehavior(() => ViewData.ModelState));
        //add any other desired behaviors here
    }

    public string HtmlNamePrefix { get; set; }

    public T ViewModel
    {
        get { return Model; }
    }

    public IEnumerable<IBehaviorMarker> Behaviors
    {
        get { return behaviors; }
    }
}

NOTE: I updated this class since the original post. I removed constructors overrides that pass in behaviors ad htlmPrefix. You don’t need these unless you expect to further derive this class.

Configuration

Then apply a little configuration – either in the config file or in code. Refer to the Spark config documentation for details.

var settings = new SparkSettings()
    .SetPageBaseType("SparkModelViewPage")
    .AddAssembly("MvcContrib.FluentHtml")
    .AddNamespace("MvcContrib.FluentHtml")
    ...yadda yadda;
ViewEngines.Engines.Add(new SparkViewFactory(settings));

PageBaseType tells the Spark view engine to use your new class as the base class for all views.  The other two settings tell the Spark view engine to use FluentHtml in views.

Usage

That’s it.  Then you can use FluentHtml in your views like so:

<viewdata model="MyApp.Models.Person"/>  

<%=this.TextBox(x => x.FirstName).Label("First Name") %>
<%=this.TextBox(x => x.LastName).Label("Last Name") %>

Conclusion

I should add one caveat. I have tested only the most naive scenarios, and I have not used Spark for any production work at all. Please comment on any issues you encounter in using FluentHtml with Spark.

7 Comments »

  1. Very interesting, I’ll have to poke around with this. It could be of some good use. Thanks for the post.

    Comment by Donn Felker — May 19, 2009 @ 2:22 am

  2. Thanks for FluentHtml, it’s great. This is off the topic of Spark, but I was writing some FluentHtml behaviors to work with MS DataAnnotations, and I found I needed to be able to support buddy/metadata classes defined with the MetadataTypeAttribute. Here’s the code I came up with – feel free to use this if you like.

    /// <summary>
    /// This is a re-implementation of MvcContrib.FluentHtml.Behaviors.MemberBehaviorHelper{T}
    /// that is aware of MetadataTypeAttribute from DataAnnotations.
    /// </summary>
    internal static class AnnotationsHelper
    {
    // Methods
    public static T GetAttribute<T>(IMemberElement element) where T : Attribute
    {
    return GetAttribute<T>(element.ForMember);
    }

    public static T GetAttribute<T>(MemberExpression expression) where T : Attribute
    {
    if (expression == null)
    return default(T);

    var metadataAttrib = expression.Member.DeclaringType
    .GetCustomAttributes(typeof(MetadataTypeAttribute), true)
    .Cast<MetadataTypeAttribute>().FirstOrDefault();

    if (metadataAttrib == null)
    {
    return expression.Member.GetCustomAttributes(typeof(T), true)
    .Cast<T>().FirstOrDefault();
    }

    return (from prop in TypeDescriptor.GetProperties(metadataAttrib.MetadataClassType).Cast<PropertyDescriptor>()
    where prop.Name == expression.Member.Name
    select prop.Attributes.OfType<T>().FirstOrDefault()).FirstOrDefault();
    }

    public static MethodInfo GetMethod(IMemberElement element, string methodName)
    {
    return element.ForMember == null ? null : element.GetType().GetMethod(methodName);
    }

    public static void InvokeMethod(MethodInfo method, IMemberElement element, params object[] parameters)
    {
    method.Invoke(element, parameters);
    }
    }

    Comment by Joel — October 16, 2009 @ 8:51 pm

  3. Do you have a recommendation on what to do if the spark page doesn’t have a model, it’s just html? A couple possibilities are to declare the model as object or create an empty viewmodel.

    Comment by Marshal — December 7, 2009 @ 5:07 pm

  4. […] equally as easy to use FluentHtml from within Spark. I followed this great post by Tim Scott which details exactly what you need to do. I copied the SparkViewModelPage<T> base class from […]

    Pingback by James Broome » Blog Archive » Turbo-charge your MVC views with Spark and FluentHtml — December 15, 2009 @ 9:38 am

  5. Marshal, I ran into that. I created a non-generic implementation of SparkModelViewPage and used the following for the ViewModel property:

    public object ViewModel
    {
    get { return null; }
    }

    Comment by aroder — January 15, 2010 @ 10:43 pm

    • Marshal and aroder,

      You can just inherit the non-generic implementation from the generic one, like this:

      public abstract class SparkModelViewPage : SparkModelViewPage { }

      Comment by Daniel Liuzzi — January 26, 2010 @ 4:36 am

      • WordPress swallowed the brackets, here it goes again:

        public abstract class SparkModelViewPage : SparkModelViewPage[ViewPage] { }

        (replace square brackets with angle brackets)

        Comment by Daniel Liuzzi — January 26, 2010 @ 4:39 am


RSS feed for comments on this post. TrackBack URI

Leave a reply to aroder Cancel reply

Create a free website or blog at WordPress.com.