8

The ReadOnly attribute does not seem to be in MVC 4. The Editable(false) attribute does not work the way I would want it to.

Is there something similar that works?

If not then how can I make my own ReadOnly attribute that would work like this:

public class aModel
{
   [ReadOnly(true)] or just [ReadOnly]
   string aProperty {get; set;}
}

so I can put this:

@Html.TextBoxFor(x=> x.aProperty)

instead of this ( which does work ):

@Html.TextBoxFor(x=> x.aProperty , new { @readonly="readonly"})

or this ( which does work but values are not submitted ):

@Html.TextBoxFor(x=> x.aProperty , new { disabled="disabled"})

http://view.jquerymobile.com/1.3.2/dist/demos/widgets/forms/form-disabled.html

something like this maybe? https://stackoverflow.com/a/11702643/1339704

Note:

[Editable(false)] did not work

Community
  • 1
  • 1
Soenhay
  • 3,958
  • 5
  • 34
  • 60

2 Answers2

9

You can create a custom helper like this that will check the property for the presence of a ReadOnly attribute:

public static MvcHtmlString MyTextBoxFor<TModel, TValue>(
    this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)
{
    var metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
    // in .NET 4.5 you can use the new GetCustomAttribute<T>() method to check
    // for a single instance of the attribute, so this could be slightly
    // simplified to:
    // var attr = metaData.ContainerType.GetProperty(metaData.PropertyName)
    //                    .GetCustomAttribute<ReadOnly>();
    // if (attr != null)
    bool isReadOnly = metaData.ContainerType.GetProperty(metaData.PropertyName)
                              .GetCustomAttributes(typeof(ReadOnly), false)
                              .Any();

    if (isReadOnly)
        return helper.TextBoxFor(expression, new { @readonly = "readonly" });
    else
        return helper.TextBoxFor(expression);
}

The attribute is simply:

public class ReadOnly : Attribute
{

}

For an example model:

public class TestModel
{
    [ReadOnly]
    public string PropX { get; set; }
    public string PropY { get; set; }
}

I have verified this works with the follow razor code:

@Html.MyTextBoxFor(m => m.PropX)
@Html.MyTextBoxFor(m => m.PropY)

Which renders as:

<input id="PropX" name="PropX" readonly="readonly" type="text" value="Propx" />
<input id="PropY" name="PropY" type="text" value="PropY" />

If you need disabled instead of readonly you can easily change the helper accordingly.

asymptoticFault
  • 4,491
  • 2
  • 19
  • 24
  • Is there a way to make it work with any Html helper instead of creating a new Html helper? – Soenhay Aug 29 '13 at 16:19
  • There is no way to make it work with all the helpers in the way you are wanting. That is why most of the helpers have the optional `htmlAttributes` argument that will let you specify things like `readonly` as needed. My above solution is how you would have to implement it for the requirements you gave, i.e. using an attribute. Another solution, though I don't believe it would be any cleaner than specifying `@readonly = "readonly"`, would be to create an extension to work on the outputted HTML from the helper, i.e. `@Html.TextBoxFor().Readonly()`. – asymptoticFault Aug 29 '13 at 16:31
  • Ok, I decided to just use htmlAttributes as it is way simpler... but I will accept your answer since it seems like the closest answer to my question. – Soenhay Sep 11 '13 at 15:14
5

You could create your own Html Helper Method

See here: Creating Customer Html Helpers

Actually - check out this answer

 public static MvcHtmlString MyTextBoxFor<TModel, TProperty>(
         this HtmlHelper<TModel> helper, 
         Expression<Func<TModel, TProperty>> expression)
    {
        return helper.TextBoxFor(expression, new {  @readonly="readonly" }) 
    }
Community
  • 1
  • 1
KerSplosh
  • 466
  • 8
  • 26
  • That looks promising... I could just create one called ReadOnlyTextBoxFor or something similar.... I suppose the data annotation is overkill. – Soenhay Aug 29 '13 at 16:01
  • Exactly, and in my opinion doing it this way, you are doing it in the right place. I dont think a data annotation is how you would define what is essentially a presentation attribute – KerSplosh Aug 29 '13 at 16:15
  • Data Annotations can and often do provide information for displaying a property, i.e. the `Display` and `DisplayFormat` data annotations. – asymptoticFault Aug 29 '13 at 16:25