Question

I've been working a lot with asp.net web forms and one think that I like about the is the consistency with the generated markup e.g. if you create a composite control for a TextField you can control the generated markup in a single class like and don't break the SRP:

<form:textfield id="firstName" runat="server" required="true" label="First Name" />

I you're your going to generate the markup by hand it might look like this:

<label for="firstName" id="lbl_firstName">Name <span class="required">*</span></label>
<input id="firstName" name="firstName" type="text" value="" />

The problem is when would like to change something for example add a wrapping div or move the span. In worst case you have to edit thousands of views.

That's why I really like the MVC Contrib FluentHtml.

<%= this.TextBox(x => x.Message.PostedBy).Class("required").Label("Name") %>

My question is what do you think is the best way to add a wrapping div for the code line above? I think hand writing is not an option because of the arguments above? Perhaps extending the TextBox : MvcContrib.FluentHtml.Elements.TextInput?

Was it helpful?

Solution

have you checked InputBuilder in MvcContrib project? it is used in Codecampserver as well. have a look and i think u will like it.

OTHER TIPS

Honestly, I don't think the example case you've given applies to real world. A textbox is a textbox. If you need one, you render one.
If you need a more "complex" control like a textbox wrapped in a div tag, then you can have a partial view for that.

For example, Model :

public class CustomControlModel {
    public string Name { get; set; }
    public string Value { get; set; }
    public string Class { get; set; }
    public bool WrapInDivTag { get; set; }
    //you get the idea
}

Custom Control :

<%@ Control Inherits="System.Web.Mvc.ViewUserControl<CustomControlModel>" %>
<%if (Model.WrapInDivTag) {%> <div> <% } %>
    <%=Html.TextBox(Model.Name, Model.Value, new { @class = Model.Class })%>
<%if (Model.WrapInDivTag) {%> </div> <% } %>

And when rendering :

<%Html.RenderPartial("CustomControl", 
    new CustomControlModel { Name = "name", WrapInDivTag = true }); %>

That's a very simple example but I hope it explains why I suggested partial views. Don't forget that you can expose another property to get which tag to render etc.

InputBuilders are one option. With FluentHtml you could create a custom element, something like this:

public class TextBoxInContainer : TextInput<TextBox>
{
    public TextBoxInContainer (string name) : base(HtmlInputType.Text, name) { }

    public TextBoxInContainer (string name, MemberExpression forMember, IEnumerable<IBehaviorMarker> behaviors) : base(HtmlInputType.Text, name, forMember, behaviors) { }

    protected override ToString()
    {
         divBuilder = new TagBuilder(HtmlTag.Div);
         divBuilder.InnerHtml = ToString();
         return divBuilder.ToString(TagRenderMode.SelfClosing);
    }
}

To use this from your view you would extend IViewModelContainer something like this:

public static MyTextBox TextBoxInContainer <T>(this IViewModelContainer<T> view, Expression<Func<T, object>> expression) where T : class
{
    return new TextBoxInContainer (expression.GetNameFor(view), expression.GetMemberExpression(), view.Behaviors)
        .Value(expression.GetValueFrom(view.ViewModel));
}

Then if you want to change your container to a span sitewide, you change the ToString method of TextBoxInContainer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top