Meet my new HtmlHelper extensions friends, ForEach and If

Posted by Kenny Eliasson | Posted in , , , | Posted on 13:15

How many times have you written code like this in your MVC views?

<%
 int currentIndex = 0;
 foreach(var item in Model.Items) {
%>
    <% if(currentIndex == 0) {%>
       <div class="item first"><%= item.Name %></div>
    <% } else if(currentIndex == Items.Count()-1) { %>
       <div class="item last"><%= currentIndex + 1 %> <%= item.Name %></div>
    <% } else { %>
       <div class="item"><%= item.Name %></div>
    <% } %>
<%
 currentIndex++;
 }
%>

This is pure ugliness :(

What I missed was something like django for variables. They include both a Last and First variable on the loop.

After reading Phil Haacked's blog about "A code based repeater for .NET MVC" I decided to shamelessy take some parts of his code and write my own extension methods.

The first extension method I wrote was the Html.ForEach which gets me a index counter.

public static void ForEach<T>(this HtmlHelper html, IEnumerable<T> items, Action<T, int> render)
{
    if (items == null)
        return;

    int i = 0;
    items.ForEach(item => render(item, i++));
}

And to use it

<% Html.ForEach(Model.Items, (item, index) => { %>
    <div>#<%= index + 1 %> <%= item.Name %>
<% }); %>

Pretty slick and I dont need to have the counter variable in the view code. It uses lambda in way I didn't thought was possible before I read Haacked blog post.

I then decided to see if I could manage to check if I was on the first or last item in the loop.

I came up with this

public static void ForEachExtra<T>(this HtmlHelper html, IEnumerable<T> items, Action<T, ForLoop<T>> render)
{
    if (items == null)
       return;

    var loop = new ForLoop<T>(items);

    int i = 0;
    items.ForEach(item => { render(item, loop.Update(i)); i++; });
}

public class ForLoop<T>
{
    private readonly int _itemCount;

    public ForLoop(IEnumerable<T> items)
    {
        _itemCount = items.Count();
    }

    public int Counter { get; set; }
    public int Counter0 { get; set; }
    public bool First { get; set; }
    public bool Last { get; set; }

    public ForLoop<T> Update(int i)
    {
        Counter = i + 1;
        Counter0 = i;
        First = i == 0;
        Last = i == _itemCount-1;
        return this;
    }
 }


And to use this you will write

<% Html.ForEachExtra(Model.Templates, (template, loop) => {%>
   <% if(loop.First) { %> First! <% }%>">
   <div>#<%= loop.Counter %> - <%= template.Name %></div>
   <% if(loop.Last) { %> Last! <% }%>
<% }); %>


Starting to look impressive here! :) But I still think I can get it better, so onto my other new extension method, If()!

What I want is to have code that looks something like this

<% Html.ForEachExtra(Model.Items, (item, loop) => { %>
   <div class="item <%= Html.If(loop.First).Write("first").ElseIf(loop.Last).Write("last") %>
       #<%=loop.counter%> <%= item.Name %>
   </div>
<% }); %>

That would be awesome so off I went to write it.

public interface IConditionWrite
{
    IElseIfConditionBuilder Write(string output);
}

public interface IElseIfConditionBuilder
{
    IConditionWrite ElseIf(bool condition);
}

public class ConditionBuilder : IConditionWrite, IElseIfConditionBuilder
{
    private readonly IList<FluentHtmlCondition> _conditions;
    private FluentHtmlCondition _lastAddedCondition;

    public ConditionBuilder()
    {
        _conditions = new List<FluentHtmlCondition>();
    }

    public IConditionWrite AddCondition(FluentHtmlCondition condition)
    {
       _lastAddedCondition = condition;
       _conditions.Add(condition);
       return this;
    }
        
    public override string ToString()
    {
        foreach (var condition in _conditions) {
            if (condition.Fulfilled)
                return condition.Output;
        }

        return "";
    }

    public IConditionWrite ElseIf(bool condition)
    {
        AddCondition(new FluentHtmlCondition(condition));
        return this;
    }

    public IElseIfConditionBuilder Write(string output)
    {
        _lastAddedCondition.Output = output;
        return this;
    }
}

public class FluentHtmlCondition
{
    public readonly bool Fulfilled;
    public string Output;

    public FluentHtmlCondition(bool fulfilled)
    {
        Fulfilled = fulfilled;
    }

    public void Write(string output)
    {
        Output = output;
    }
 }

And in my Html-helper extension class i add

public static IConditionWrite If(this HtmlHelper html, bool condition)
{
    return new ConditionBuilder().AddCondition(new FluentHtmlCondition(condition));
}

And there you have it all, hope someone can have some use with it.

How I do data-access

Posted by Kenny Eliasson | Posted in , , , , | Posted on 10:04

Over the years I've tested alot of different techniques for getting data from a database in a .NET application.

From the simple ADO.NET wrapper that executes raw sql or SP's and then returning a DataTable to the more specified "Repository" where each entity in my domain had a corresponding Repository for querying the data.

I then discovered ORM's, especially NHibernate and started using it with the "One repository for each entity" approach. This worked great but when my projects grew bigger and bigger the need to create a new Repository for each new entity was to cumbersome (and often the Repository would have an interface, so for each new entity I created 3 new classes).

I later implemented Linq2NHibernate and made it so that the most basic queries (i.e find by name, ordering etc) was made using it. More advanced queries I still shuffled into a entity-specific repository.

My interface at this time looked at this

public interface INHibernateRepository
{
    ICriteria ExecuteCritera(DetachedCriteria criteria);
    IQuery ExecuteCritera(string hql);
    IList ExecuteMultiCriteria(params DetachedCriteria[] criterias);
    void Delete(int id) where ENTITY : DomainObject;
    int Save(ENTITY entity) where ENTITY : DomainObject;
    IQueryable Query() where ENTITY : DomainObject; //Linq2Nhibernate
    ENTITIY Get(int id) where ENTITIY : DomainObject;
}

Pretty basic stuff for querying and fetching by Primary Key.

If i got a entity specific repository i would extend INHibernateRepository like this

public interface QuestionRepository : INHibernateRepository
{
    Question GetLatestInserted();
    //more question specific implementations
}

I then, of course, had implementing classes of these interfaces.

To use it in a MVC application I used Dependency Injection to wire up my controllers.

public class QuestionController(INHibernateRepository repository, IQuestionRepository questionRepository, IUserRepository userRepository /* etc */)
{
}

Some may say that I shouldn't inject repositories directly to my controller, but even if I broke it out to a domain-service, it would still need 3 dependencies.

So instead of using the approach above I have begun using Domain Queries. I've read abit about them before but I was when i read Implementing Domain Queries i realized how it would benefit me.

I started my refactoring spree by adding two new methods on my repository interface

public interface INHibernateRepository : IRepository
{
    IEnumerable Query(IDomainQuery query);
    T FindOne(IDomainQuery domainQuery);
    /* All other methods */
}

I then one by one extracted the more complicated queries to their own query-class.

During this process I didn't encounter a single problem and I could remove all of my entity specific repositories and use _one_ repository for all database calls.

So when I'm writing a query nowadays, I first and foremost try to use Linq, if that doesn't work I create a new query class instead of creating a whole new repository for a single entity.