131

How do I create a readonly textbox in ASP.NET MVC3 with the Razor view engine?

Is there an HTMLHelper method available to do that?

Something like the following?

@Html.ReadOnlyTextBoxFor(m => m.userCode)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shyju
  • 214,206
  • 104
  • 411
  • 497

7 Answers7

266
@Html.TextBoxFor(m => m.userCode, new { @readonly="readonly" })

You are welcome to make an HTML Helper for this, but this is simply just an HTML attribute like any other. Would you make an HTML Helper for a text box that has other attributes?

  • 1
    @Shyju Sorry, I was missing the `@` prefix of the `readonly` property. See my edit. –  Jan 06 '12 at 17:36
  • 7
    In the future, if you get any kind of errors adding properties to the dynamic object argument you can prefix them with the `@`. You'll usually only see it with keywords that match HTML attributes (like readonly, class, etc.) – Brad Christie Jan 06 '12 at 17:40
  • 10
    @BradChristie: No; you only need an `@` to use attributes that match **C#** keywords. – SLaks Jan 06 '12 at 17:55
  • @SLaks: Isn't that what I said? ;-) – Brad Christie Jan 06 '12 at 19:11
  • 1
    @BradChristie: I misread your comment ("keywords" was ambiguous) – SLaks Jan 06 '12 at 19:13
  • 1
    If you have multiple html attributes you can do something like: `@Html.TextBoxFor(m => m.userCode, new { @readonly="readonly", @class="form-control" })` – benscabbia Jan 28 '17 at 17:20
36

UPDATE: Now it's very simple to add HTML attributes to the default editor templates. It neans instead of doing this:

@Html.TextBoxFor(m => m.userCode, new { @readonly="readonly" })

you simply can do this:

@Html.EditorFor(m => m.userCode, new { htmlAttributes = new { @readonly="readonly" } })

Benefits: You haven't to call .TextBoxFor, etc. for templates. Just call .EditorFor.


While @Shark's solution works correctly, and it is simple and useful, my solution (that I use always) is this one: Create an editor-template that can handles readonly attribute:

  1. Create a folder named EditorTemplates in ~/Views/Shared/
  2. Create a razor PartialView named String.cshtml
  3. Fill the String.cshtml with this code:

    @if(ViewData.ModelMetadata.IsReadOnly) {
        @Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue,
            new { @class = "text-box single-line readonly", @readonly = "readonly", disabled = "disabled" })
    } else {
        @Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue,
            new { @class = "text-box single-line" })
    }
    
  4. In model class, put the [ReadOnly(true)] attribute on properties which you want to be readonly.

For example,

public class Model {
    // [your-annotations-here]
    public string EditablePropertyExample { get; set; }

    // [your-annotations-here]
    [ReadOnly(true)]
    public string ReadOnlyPropertyExample { get; set; }
}

Now you can use Razor's default syntax simply:

@Html.EditorFor(m => m.EditablePropertyExample)
@Html.EditorFor(m => m.ReadOnlyPropertyExample)

The first one renders a normal text-box like this:

<input class="text-box single-line" id="field-id" name="field-name" />

And the second will render to;

<input readonly="readonly" disabled="disabled" class="text-box single-line readonly" id="field-id" name="field-name" />

You can use this solution for any type of data (DateTime, DateTimeOffset, DataType.Text, DataType.MultilineText and so on). Just create an editor-template.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
amiry jd
  • 27,021
  • 30
  • 116
  • 215
  • 2
    +1 because you used "ViewData.ModelMetadata.IsReadOnly". I was expecting MVC would take into account these stuff in version 4. – cleftheris Oct 24 '12 at 11:00
  • @cleftheris well we are in version 5 now, and MVC still didn't take them ;) – amiry jd Jul 23 '14 at 19:59
  • 2
    @Javad_Amiry - great answer - I've implemented it and it seemed to work great until I clicked Save on a Scaffolded Edit page. Then it turns out Properties with [ReadOnly(true)] will result in NULL being sent to the database instead of the real Property value - Have you come across this? – Percy Mar 25 '15 at 20:11
5

The solution with TextBoxFor is OK, but if you don't want to see the field like EditBox stylish (it might be a little confusing for the user) involve changes as follows:

  1. Razor code before changes

    <div class="editor-field">
         @Html.EditorFor(model => model.Text)
         @Html.ValidationMessageFor(model => model.Text)
    </div>
    
  2. After changes

    <!-- New div display-field (after div editor-label) -->
    <div class="display-field">
        @Html.DisplayFor(model => model.Text)
    </div>
    
    <div class="editor-field">
        <!-- change to HiddenFor in existing div editor-field -->
        @Html.HiddenFor(model => model.Text)
        @Html.ValidationMessageFor(model => model.Text)
    </div>
    

Generally, this solution prevents field from editing, but shows value of it. There is no need for code-behind modifications.

Bronek
  • 10,722
  • 2
  • 45
  • 46
  • 1
    I think that having the CSS for the classes editor-field and display-field here might be really helpful. – DOK Oct 30 '14 at 18:36
  • What do you mean by *"this solution disables filed against editing,"* (it seems incomprehensible)? Please respond by [editing your answer](https://stackoverflow.com/posts/13587678/edit), not here in comments (as appropriate). – Peter Mortensen Sep 16 '19 at 19:38
4

With credits to the previous answer by @Bronek and @Shimmy:

This is like I have done the same thing in ASP.NET Core:

<input asp-for="DisabledField" disabled="disabled" />
<input asp-for="DisabledField" class="hidden" />

The first input is readonly and the second one passes the value to the controller and is hidden. I hope it will be useful for someone working with ASP.NET Core.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0
 @Html.TextBox("Receivers", Model, new { @class = "form-control", style = "width: 300px", @readonly = "readonly" })
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hossein Dahr
  • 75
  • 11
0
@Html.TextBoxFor(model => model.IsActive, new { readonly= "readonly" })

This is just fine for text box. However, if you try to do same for the checkbox then try using this if you are using it:

@Html.CheckBoxFor(model => model.IsActive, new { onclick = "return false" })

But don't use disable, because disable always sends the default value false to the server - either it was in the checked or unchecked state. And the readonly does not work for checkbox and radio button. readonly only works for text fields.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ananda G
  • 2,389
  • 23
  • 39
0

You can use the below code for creating a TextBox as read-only.

Method 1

 @Html.TextBoxFor(model => model.Fields[i].TheField, new { @readonly = true })

Method 2

@Html.TextBoxFor(model => model.Fields[i].TheField, new { htmlAttributes = new {disabled = "disabled"}})
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131