Helper to write HtmlHelpers

4

I'm trying to write an HtmlHelper and seeing some basic examples I found one with the class TagBuilder already help :

namespace MyNamespace 
{  
    public static class MyHeleprs
    { 
        public static MvcHtmlString Image(this HtmlHelper htmlHelper, 
        string source, string alternativeText)
        {
            //declare the html helper 
            var builder = new TagBuilder("image"); 
            //hook the properties and add any required logic
            builder.MergeAttribute("src", source);
            builder.MergeAttribute("alt", alternativeText);
            //create the helper with a self closing capability
            return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing));
        } 
    } 
}

I just want to create a bigger facilitator, in order to manipulate a value that will be displayed, some classes css etc. So I would not want to rewrite a helper that already exists as TextBoxFor or EditorFor .

Based on this will, I thought about reusing these helpers and adding my manipulations.

I was thinking of doing the following:

public static MvcHtmlString FieldFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression,
    string cssClass = "",
    bool placeHolder = false,
    bool autoFocus = false,
    object htmlAttributes = null)
{
    var builder = new TagBuilder(
        htmlHelper.TextBoxFor(expression, htmlAttributes).ToString());

    // value attribute
    ...
    builder.Attributes["type"] = "text";
    builder.Attributes["value"] = value;           

    // autofocus
    if (autoFocus)
        builder.Attributes.Add("autofocus", "autofocus");

    // css
    builder.AddCssClass(cssClass);

    // placeholder
    ...
    return new MvcHtmlString(builder.ToString(TagRenderMode.SelfClosing));
}

Anyway, highlighting what I thought:

var builder = new TagBuilder(htmlHelper.TextBoxFor(expression, htmlAttributes).ToString());

But TagBuilder does not work like this.

Manipulating something already ready helps by not having to rewrite things that the framework already does, how to generate the Id and Name of the element among others.

How can I resolve this? What would be a more practical way?

    
asked by anonymous 02.07.2014 / 22:55

1 answer

5

Example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace System.Web.Mvc
{
    public static class Methods
    {
        public static String ControllerName(this HtmlHelper HtmlHelper)
        {
            return HtmlHelper.ViewContext.RequestContext.RouteData.Values["controller"].ToString();
        }
        public static String ControllerName(this AjaxHelper AjaxHelper)
        {
            return AjaxHelper.ViewContext.RequestContext.RouteData.Values["controller"].ToString();
        }
        public static String ActionName(this HtmlHelper HtmlHelper)
        {
            return HtmlHelper.ViewContext.RequestContext.RouteData.Values["action"].ToString();
        }
        public static String ActionName(this AjaxHelper AjaxHelper)
        {
            return AjaxHelper.ViewContext.RequestContext.RouteData.Values["action"].ToString();
        }
        public static IHtmlString FieldFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            string cssClass = "",
            string placeHolder = "",
            bool autoFocus = false,
            object htmlAttributes = null)
        {
            IDictionary<string, object> htmlAttributesList = new Dictionary<string, object>();
            if (htmlAttributes != null)
            {
                foreach (PropertyInfo prop in htmlAttributes.GetType().GetProperties())
                {
                    htmlAttributesList.Add(prop.Name, prop.GetValue(htmlAttributes));
                }
            }            
            if (!String.IsNullOrEmpty(cssClass))
            {
                htmlAttributesList.Add("css", cssClass);
            }
            if (!String.IsNullOrEmpty(placeHolder))
            {
                htmlAttributesList.Add("placeholder", placeHolder);
            }
            if (autoFocus)
            {
                htmlAttributesList.Add("autofocus", "autofocus");
            }            
            return new MvcHtmlString(htmlHelper.TextBoxFor(expression, htmlAttributesList).ToHtmlString());
        }      
    }
}

Note: There are some more methods that I usually use to mount something standard, but, your question would be the way to do it, without TagBuilder .

How to use:

@Html.FieldFor(a => a.Nome);
@Html.FieldFor(a => a.Nome, htmlAttributes: new { id="Nome" })
@Html.FieldFor(a => a.Nome, cssClass: "", placeHolder: "", autoFocus: false, htmlAttributes: null)
@Html.FieldFor(a => a.Nome, "form-control", "Digite o seu nome", true, null)
    
02.07.2014 / 23:52