MVC 4 razor Data Annotations ReadOnly
Solution 1
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.
Solution 2
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" })
}
Soenhay
Updated on July 09, 2022Comments
-
Soenhay almost 2 years
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
-
Soenhay over 10 yearsThat looks promising... I could just create one called ReadOnlyTextBoxFor or something similar.... I suppose the data annotation is overkill.
-
KerSplosh over 10 yearsExactly, 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
-
Soenhay over 10 yearsIs there a way to make it work with any Html helper instead of creating a new Html helper?
-
asymptoticFault over 10 yearsData Annotations can and often do provide information for displaying a property, i.e. the
Display
andDisplayFormat
data annotations. -
asymptoticFault over 10 yearsThere 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 likereadonly
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()
. -
Soenhay over 10 yearsOk, 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.