Code Sprouts

Wholesome Bits Of Tech

Quick Tip: Injecting Script From C#

clock May 18, 2009 08:07 by author ColinW

I’ve developed quite a few extensions working with the ASP.Net MVC framework ( don’t worry, I’ll roll them out as I clean them up and make the more useful for mass-consumption ).  I almost always need to inject some javascript into the page in these extensions, and I’ve found literal strings ( using @ before a string ) to be quite handy for development.

For example, imagine a script block similar to the following:

<script type="text/javascript">
    $('#divToShow').show();
    $('#divToHide').hide();
</script>

Without using string literals, you’ll need to do something like the following:

"<script type=\"text/javascript\">" + Environment.NewLine +
" $('#divToShow).show();" + Environment.NewLine +
" $('#divToHide).hide();" + Environment.NewLine +
"</script>"

Using string literals:
 
@"<script type=""text/javascript"">
$('#divToShow').hide();
$('#divToHide').show();
</script>"

Much cleaner!
 
It may look subtle, but using string literals throughout the development of my extensions has made things much easier to enhance, refine, and (gasp!) debug.
 
What do you think?
 
- Colin


Sorting By String In LINQ

clock May 15, 2009 08:44 by author ColinW

When implementing a sorting feature in most UI’s, the sorting expression is typically string based.  When you’re using LINQ this becomes a problem due to the sorting methods requiring a lambda function with a typed field name.

While working on a project recently, a colleague and I came up with a pretty elegant solution that uses reflection to turn the fieldname in string form into an acceptable lambda expression. 

The code is pretty compact, so I’ve included it below and added comments to what’s going on:

public static class SortingExtensions
{
    public static IQueryable<T> OrderByFieldName<T>
        (this IQueryable<T> query, string fieldName, bool isSortAscending)
    {
        // Find the field we're sorting on and get it's type
        Type fieldType = typeof(T).GetProperty(fieldName).PropertyType;

        // Find the generic sort method. Note the binding flags 
        // since our particular sort method is marked as private & static
        MethodInfo sortItMethod = typeof(SortingExtensions)
            .GetMethod("SortIt", BindingFlags.Static | BindingFlags.NonPublic);

        // The method returned is an open generic, 
        // so let's close it with the types we need for this operation
        sortItMethod = sortItMethod.MakeGenericMethod(typeof(T), fieldType);

        // Now that we have our closed generic type, 
        // we can invoke it with the specified parameters 
        query = (IQueryable<T>)sortItMethod
            .Invoke(null, new object[] { query, fieldName, isSortAscending });

        return query;
    }

    private static IQueryable<T> SortIt<T, K>
        (IQueryable<T> query, string sortFieldName, bool isSortAscending)
    {
        // The orderby works by examining the lambda passed and looking that the body
        // for the property name and variable type.
        // In order to supply a lambda, we'll need to build one.

        // The parameter will be the left-hand side of the lambda expression
        ParameterExpression param = Expression.Parameter(typeof(T), "x");

        // The body will be the right-hand side of the lambda expression
        MemberExpression body = Expression.Property(param, sortFieldName);

        // We'll build our lambda expression, 
        // first passing in the body and then the parameter
        var sortExpression = Expression.Lambda<Func<T, K>>(body, param);

        // All that's left to do is calling the correct extension method for ordering
        if (isSortAscending)
            return query.OrderBy<T, K>(sortExpression);
        else
            return query.OrderByDescending<T, K>(sortExpression);
    }
}

The code works in all the situations we’ve tested it in ( LINQ to objects, LINQ to SQL ), and considering reflection is used in the operation, we’re rather proud of it.  A possible performance enhancement left out of this solution would be to cache the MethodInfo for the open generic type to avoid having to reflect every time to find the method, but the overhead is rather minimal in this situation.

Side Note:

After we developed our solution, we ran across a post from Scott Guthrie, that enlightened us to the existence of the Dynamic LINQ Library, which adds string-based support similar to what we’ve done here, however this code is more narrow focused for sorting operations, and is a bit different than the Dynamic LINQ Library.

- Colin



ASP.Net MVC Repeater Extension

clock May 8, 2009 05:58 by author ColinW

Download the code!

When working in the View of an MVC project, you’ll frequently need to iterate through a list of items.  If all you need to do is output the exact same markup for every item, a foreach will serve you well.  However, it’s extremely common that you’ll need to generate some sort of alternating sequence for those items, and the foreach quickly turns rather unwieldy ( normally turning into a simpler for loop and having quite a few conditional statements and temporary variables ).

Since I frequently run into the situation that I need to generate alternating ‘templates’ for collections of data, I’ve created a simple Repeater extension to handle the task.

The Repeater Extension

The Repeater is a relatively simple extension, however it does contain the following functionality:

  • Works with any enumerable class
  • Accepts a string or action to generate markup
  • Supports adding custom markup for the beginning & ending of an ‘item’, allowing you to use the same template for both all items.

Syntax:

<div style="width: 100px;">
    <% this.Html.Repeater((IEnumerable<string>)this.ViewData["ItemData"])
       .BeginTemplate("<div style='border: solid 1px blue;'>")
       .BeginAlternatingTemplate("<div style='border: solid 1px red;'>")
       .Template(item =>
       {
    %>
        <div style="margin: 2px; padding: 4px; border: dashed 1px black;">
            <%= item%>
        </div>
    <% 
        })
       .AlternatingTemplate(item =>
       {
    %>
        <div style="text-align: right;">
            <%= item %>              
        </div>
    <%
       })
       .EndTemplate("</div><br />")
       .Render();
    %>
</div>

Output from the above example:

image

While there’s support for a custom alternating template, I’ve found that any style changes you want to make between regular/alternating items can be done through BeginTemplate / BeginAlternatingTemplate.

Using The Repeater In Your Own Project

Download the code first.

The Repeater is contained in the MvcExtensions project.  You’ll need to either add the project to your solution or pull out the dll it generates and add then add a reference to the project or dll:

image

Add a namespace entry to your root web.config namespaces element:

<add namespace="MvcExtensions.Repeater"/>

After the reference has been added and the namespace is inserted into the web.config, you should see it show up in auto-complete when writing script code in the view ( might take a bit for autocomplete to recognize the extension):

image

And you’re ready to go!

If you have any questions or comments, feel free to leave a comment or send me an email!

- Colin