I am developing a huge form with a lot of elements in it. The purpose of this form is editing one domain entity. Now, I finished developing the whole form and it just shows the bunch of text boxes, text areas, radio buttons and so on, allowing user to change values of entities. When user submits the form, it goes to server and server processes the data.The form is based on Razor's HTML helpers:(... code omitted for shortness ...)<tr data-id=@row.Id class=entity-row><td style=width: 475px>    <span class=num>        @Html.TextBoxFor(x => Model.Entities[i].Address, new { @class = field field-normal, style = text-align: right;width:475px, Id = Address })    </span></td><td>    <span class=num>        @Html.TextBoxFor(x => Model.Entities[i].SupplyDate, {0:dd.MM.yyyy}, new { @class = field field-normal field-date has-datepicker, style = text-align: right;, Id = SupplyDate })    </span></td><td>    <span class=num>        @Html.TextBoxFor(x => Model.Entities[i].Quantity, new { @class = field field-normal field-num, style = text-align: right;, Id = Quantity })    </span></td></tr>(... code omitted for shortness ...)the next request that I got is to make user can just view the data and cannot edit this. So I should make the elements on the form disabled based on some condition. I inject special property to view model indicating ability to edit data:public class MyEntitiesViewModel{    (... code omitted for shortness ...)    public Entity[] Entities { get; set; }    public bool Editable { get; set; }    (... code omitted for shortness ...)}Ok, now I would crawl over each element in the view and set disabled attribute for needed elements like this:@{    object elementAttributes;    if (Model.Editable)    {        elementAttributes = new {@class = field field-normal, style = text-align: right;width:475px, Id = Address};    }    else    {        elementAttributes = new {@class = field field-normal, style = text-align: right;width:475px, Id = Address, disabled = disabled};    }    Html.TextBoxFor(x => Model.Entities[i].Address, elementAttributes);}Or even better I could use IDictionary<string, object> for elementAttributes variable and get code shorter.But I thought about introducing new helpers that accepts bool last argument indicating is element disabled (disableness of element).Here is that I meant:@Html.TextBoxFor(x => Model.Entities[i].Address, new { @class = field field-normal, style = text-align: right;width:475px, Id = Address }, !Model.Editable)The last argument here !Model.Editable indicate should be or should not be the element be disabled.Here is a set of HTML helpers I introduced to project and they are looks like working successfully:    private static IDictionary<string, object> _GetDisabledAttributesDictionary(object attributes)    {        var htmlAttributesDictionary = attributes is IDictionary<string, object> ? (IDictionary<string, object>)attributes : HtmlHelper.AnonymousObjectToHtmlAttributes(attributes);        if (htmlAttributesDictionary.ContainsKey(disabled))        {            htmlAttributesDictionary.Remove(disabled);        }        htmlAttributesDictionary.Add(disabled, disabled);        return htmlAttributesDictionary;    }    private static MvcHtmlString _DisableHtmlElementIfNeeded<TModel, TProperty>(        Expression<Func<TModel, TProperty>> expression,         object value,         object attributes,         bool disabled,         Func<Expression<Func<TModel, TProperty>>, object, object, MvcHtmlString> renderWithObject,         Func<Expression<Func<TModel, TProperty>>, object, IDictionary<string, object>, MvcHtmlString> renderWithDictionary)    {        if (!disabled)            return renderWithObject(expression, value, attributes);        var htmlAttributesDictionary = _GetDisabledAttributesDictionary(attributes);        return renderWithDictionary(expression, value, htmlAttributesDictionary);    }    private static MvcHtmlString _DisableHtmlElementIfNeeded<TModel, TProperty>(        Expression<Func<TModel, TProperty>> expression,         string format,         IDictionary<string, object> attributes,         bool disabled,         Func<Expression<Func<TModel, TProperty>>, string, IDictionary<string, object>, MvcHtmlString> renderWithDictionary)    {        if (!disabled)            return renderWithDictionary(expression, format, attributes);        var htmlAttributesDictionary = _GetDisabledAttributesDictionary(attributes);        return renderWithDictionary(expression, format, htmlAttributesDictionary);    }    private static MvcHtmlString _DisableHtmlElementIfNeeded<TModel, TProperty>(        Expression<Func<TModel, TProperty>> expression,         string format,         object attributes,         bool disabled,         Func<Expression<Func<TModel, TProperty>>, string, object, MvcHtmlString> renderWithObject,         Func<Expression<Func<TModel, TProperty>>, string, IDictionary<string, object>, MvcHtmlString> renderWithDictionary)    {        if (!disabled)            return renderWithObject(expression, format, attributes);        var htmlAttributesDictionary = _GetDisabledAttributesDictionary(attributes);        return renderWithDictionary(expression, format, htmlAttributesDictionary);    }    private static MvcHtmlString _DisableHtmlElementIfNeeded<TModel, TProperty>(        Expression<Func<TModel, TProperty>> expression,         IEnumerable<SelectListItem> selectList,         object attributes,         bool disabled,         Func<Expression<Func<TModel, TProperty>>, IEnumerable<SelectListItem>, object, MvcHtmlString> renderWithObject,         Func<Expression<Func<TModel, TProperty>>, IEnumerable<SelectListItem>, IDictionary<string, object>, MvcHtmlString> renderWithDictionary)    {        if (!disabled)            return renderWithObject(expression, selectList, attributes);        var htmlAttributesDictionary = _GetDisabledAttributesDictionary(attributes);        return renderWithDictionary(expression, selectList, htmlAttributesDictionary);    }    private static MvcHtmlString _DisableHtmlElementIfNeeded<TModel, TProperty>(        Expression<Func<TModel, TProperty>> expression,         object attributes,         bool disabled,         Func<Expression<Func<TModel, TProperty>>, object, MvcHtmlString> renderWithObject,         Func<Expression<Func<TModel, TProperty>>, IDictionary<string, object>, MvcHtmlString> renderWithDictionary)    {        if (!disabled)            return renderWithObject(expression, attributes);        var htmlAttributesDictionary = _GetDisabledAttributesDictionary(attributes);        return renderWithDictionary(expression, htmlAttributesDictionary);    }    private static MvcHtmlString _DisableHtmlElementIfNeeded<TModel, TProperty>(        Expression<Func<TModel, TProperty>> expression,         IDictionary<string, object> attributes,         bool disabled,         Func<Expression<Func<TModel, TProperty>>, IDictionary<string, object>, MvcHtmlString> renderWithDictionary)    {        if (!disabled)            return renderWithDictionary(expression, attributes);        var htmlAttributesDictionary = _GetDisabledAttributesDictionary(attributes);        return renderWithDictionary(expression, htmlAttributesDictionary);    }    public static MvcHtmlString TextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, bool disabled)    {        return _DisableHtmlElementIfNeeded(            expression,            htmlAttributes,            disabled,            helper.TextBoxFor);    }    public static MvcHtmlString TextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, bool disabled)    {        return _DisableHtmlElementIfNeeded(            expression,            htmlAttributes,            disabled,            helper.TextBoxFor,             helper.TextBoxFor);    }    public static MvcHtmlString TextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string format, object htmlAttributes, bool disabled)    {        return _DisableHtmlElementIfNeeded(            expression,            format,            htmlAttributes,            disabled,            helper.TextBoxFor,            helper.TextBoxFor);    }    public static MvcHtmlString TextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string format, IDictionary<string, object> htmlAttributes, bool disabled)    {        return _DisableHtmlElementIfNeeded(            expression,            format,            htmlAttributes,            disabled,            helper.TextBoxFor);    }    public static MvcHtmlString RadioButtonFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, object value, object htmlAttributes, bool disabled)    {        return _DisableHtmlElementIfNeeded(            expression,            value,            htmlAttributes,            disabled,            helper.RadioButtonFor,            helper.RadioButtonFor);    }    public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, object htmlAttributes, bool disabled)    {        return _DisableHtmlElementIfNeeded(            expression,            selectList,            htmlAttributes,            disabled,            helper.DropDownListFor,            helper.DropDownListFor);    }As you could see they are acting like a proxy for genuine helpers just modifying incoming sets of attributes based on condition and passes attributes to base helpers.So, although the code works, I found it very messy and here is points of possible improvements:Repitable behavior like:    if (!disabled)        return renderWithObject(expression, format, attributes);    var htmlAttributesDictionary = _GetDisabledAttributesDictionary(attributes);    return renderWithDictionary(expression, format, htmlAttributesDictionary);The algorithm here is simple: if disabled then render with helper that accepts attributes in form of objectotherwise make sure the attributes have disabled attribute and render with helper that accepts attributes in form of dictionary.Configuration of base helpers in this lines:return _DisableHtmlElementIfNeeded(expression,selectList,htmlAttributes,disabled,helper.DropDownListFor,helper.DropDownListFor);is there any way to map helpers more elegantly? I thought of using attributes or any kind of Map methods in a way mappers configured.So any other recommendations and advices are very welcomed!
A set of Razor HTML helpers for disabling elements
c#;.net;asp.net mvc;razor;helper
Focusing on the helper methods only.  Lets start with the naming of the private static methods to get this out of our way. Method names starting with an underscore is IMO a no go. Based on the NET naming guidelines one shouldn't use any underscores in the names. One exception though is the use of a prefixing underscore for class level variables.It just looks weird if you call call such methods.  private static IDictionary<string, object> _GetDisabledAttributesDictionary(object attributes){    var htmlAttributesDictionary = attributes is IDictionary<string, object> ? (IDictionary<string, object>)attributes : HtmlHelper.AnonymousObjectToHtmlAttributes(attributes);    if (htmlAttributesDictionary.ContainsKey(disabled))    {        htmlAttributesDictionary.Remove(disabled);    }    htmlAttributesDictionary.Add(disabled, disabled);    return htmlAttributesDictionary;}There is no need to use ContainsKey() before you use Remove() because if there is no entry with the passed key the method will just return without throwing an exception.  Because you add the same key later, you could simplify this by just using the setter of the Index property like so  private static IDictionary<string, object> _GetDisabledAttributesDictionary(object attributes){    var htmlAttributesDictionary = attributes is IDictionary<string, object> ? (IDictionary<string, object>)attributes : HtmlHelper.AnonymousObjectToHtmlAttributes(attributes);    htmlAttributesDictionary[disabled] = disabled;    return htmlAttributesDictionary;}If the key disabled isn't in the dictionary it will be added with the value disabled otherwise the value will be overwritten.  This ternary var htmlAttributesDictionary = attributes is IDictionary<string, object> ? (IDictionary<string, object>)attributes : htmlHelper.AnonymousObjectToHtmlAttributes(attributes);is somewhat ugly and less performant. First you are using is and if this evaluates to true you do the cast. A faster way would be to use the soft casting as and use the null-coalescing operator ?? which leads to  private static IDictionary<string, object> _GetDisabledAttributesDictionary(object attributes){    var htmlAttributesDictionary = attributes as IDictionary<string, object> ?? HtmlHelper.AnonymousObjectToHtmlAttributes(attributes);    htmlAttributesDictionary[disabled] = disabled;    return htmlAttributesDictionary;}In all of the remaining private static methods you have this  if (!disabled)    return renderWithObject(expression, value, attributes);which doesn't meet the style used before where you have used braces {} which is recommended. Using braces makes your code less error prone, so do it always.  Whether you decide to use them or not, you should stick to the chosen style. Mixing styles makes it harder to read the code.  