views:

46

answers:

1

I have a class that extends the HtmlHelper in MVC and allows me to use the builder pattern to construct special output e.g.

<%=
    Html.FieldBuilder<MyModel>(builder => {
        builder.Field(model => model.PropertyOne);
        builder.Field(model => model.PropertyTwo);
        builder.Field(model => model.PropertyThree);
    })
%>

Which outputs some application specific HTML, lets just say,

<ul>
    <li>PropertyOne: 12</li>
    <li>PropertyTwo: Test</li>
    <li>PropertyThree: true</li>
</ul>

What I would like to do, however, is add a new builder methid for defining some inline HTML without having to store is as a string. E.g. I'd like to do this.

<%
    Html.FieldBuilder<MyModel>(builder => {
        builder.Field(model => model.PropertyOne);
        builder.Field(model => model.PropertyTwo);
        builder.ActionField(model => %>
            Generated: <%=DateTime.Now.ToShortDate()%> (<a href="#">Refresh</a>)
        <%);
    }).Render();
%>

and generate this

<ul>
    <li>PropertyOne: 12</li>
    <li>PropertyTwo: Test</li>
    <li>Generated: 29/12/2008 <a href="#">Refresh</a></li>
</ul>

Essentially an ActionExpression that accepts a block of HTML. However to do this it seems I need to execute the expression but point the execution of the block to my own StringWriter and I am not sure how to do this. Can anyone advise?

+1  A: 

You only need to defer the execution of the action. Here's an example:

public static class HtmlExtensions
{
    public static SomeClass ActionField<TModel>(this HtmlHelper<TModel> htmlHelper, Action<TModel> action)
    {
        return new SomeClass(() => { action(htmlHelper.ViewData.Model); });
    }
}

public class SomeClass
{
    private readonly Action _renderer;
    public SomeClass(Action renderer)
    {
        _renderer = renderer;
    }

    public void Render()
    {
        _renderer();
    }
}

Which could be used like this:

<% Html.ActionField(model => { %>
    Generated: <%=DateTime.Now.ToShortDate()%> (<a href="#">Refresh</a>)
<% }).Render(); %>
Darin Dimitrov
That is exactly what I was after - pretty obvious as well. Thank you.
kouPhax