Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom html helper with LINQ expression in MVC 3

I'm building a custom HTML helper with an expression to draw a tag cloud where the data that goes into the tag cloud comes from the expression. I'll let the code do the talking here:

View Model

public class ViewModel
{
    public IList<MyType> MyTypes { get; set; }
    public IList<MyOtherType> MyOtherTypes { get; set; }
}

View

<div>
    @Html.TagCloudFor(m => m.MyTypes)
</div>

<div>
    @Html.TagCloudFor(m => m.MyOtherTypes)
</div>

Helper

public static MvcHtmlString TagCloudFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression) where TProperty : IList<MyType> where TProperty : IList<MyOtherType>
{
    // So my actual question here is: how do I get my IList<TProperty> collection 
    // so I can iterate through and build my HTML control
}

I've had a quick look around and have done the usual Google searches, but I can't quite seem to find that specific answer. I assume it's somewhere in the region of expression.Compile().Invoke() but I'm not sure what the correct parameters to pass are.

I should also mention that MyType and MyOtherType have a similar property of Id but there's no inheritance here, they are completely separate objects hence I'm constraining my TProperty as IList<MyType> and IList<MyOtherType>. Am I heading down the wrong path here, I feel like this should be obvious, but my brain isn't playing.

like image 860
Paul Aldred-Bann Avatar asked Aug 23 '12 12:08

Paul Aldred-Bann


2 Answers

The following should do it:

public static MvcHtmlString TagCloudFor<TModel , TProperty>( this HtmlHelper<TModel> helper , Expression<Func<TModel , TProperty>> expression )
        where TProperty : IList<MyType>, IList<MyOtherType> {

        //grab model from view
        TModel model = (TModel)helper.ViewContext.ViewData.ModelMetadata.Model;
        //invoke model property via expression
        TProperty collection = expression.Compile().Invoke(model);

        //iterate through collection after casting as IEnumerable to remove ambiguousity
        foreach( var item in (System.Collections.IEnumerable)collection ) {
            //do whatever you want
        }

    }
like image 75
Pierluc SS Avatar answered Nov 18 '22 15:11

Pierluc SS


How about....

public static MvcHtmlString TagCloudFor<TModel , TItemType>( this HtmlHelper<TModel> helper , Expression<Func<TModel , IEnumerable<TItemType>>> expression ) 
// optional --- Where TItemType : MyCommonInterface
 { 

        TModel model = (TModel)helper.ViewContext.ViewData.ModelMetadata.Model; 
        //invoke model property via expression 
        IEnumerable<TItemType> collection = expression.Compile().Invoke(model); 

        foreach( var item in collection ) { 
            //do whatever you want 
        } 

    } 
like image 1
Bob Vale Avatar answered Nov 18 '22 14:11

Bob Vale