I am currently using the @Html.EditorFor
HTML helper for the password field. I want to use the @Html.PasswordFor
HTML helper instead.
I copied the current code and replaced @Html.EditorFor
with @Html.PasswordFor
.
This is the code:
@Html.EditorFor(x => x.Password, new { htmlAttributes = new { @class = "form-control k-textbox large", placeholder = "password", @id = "password", @autocomplete = "off" } })
@Html.PasswordFor(x => x.Pwd, new { htmlAttributes = new { @class = "form-control k-textbox large", placeholder = "password", @id = "password", @autocomplete = "off" } })
The parameters are 100% the same, but these produce different style textboxes:
Note that @Html.EditorFor
has validation and a placeholder as well, but @Html.PasswordFor
doesn't; the later also has a different style. The validation spam
element is also not a part of the textbox.
Here is generated HTML code for @Html.EditorFor
:
<input autocomplete="off" class="form-control k-textbox large text-box single-line password k-invalid" data-val="true" data-val-required=" " id="password" name="Password" placeholder="password" type="password" value="" aria-invalid="true">
Here is generated HTML code for @Html.PasswordFor
:
<input data-val="true" data-val-required=" " htmlattributes="{ class = form-control k-textbox large, placeholder = password, id = password, autocomplete = off }" id="Pwd" name="Pwd" type="password" aria-invalid="true" class="k-invalid">
This is how I define those two fields in the model:
[Required(ErrorMessage = " ")]
[DataType(DataType.Password)]
public string Password { get; set; }
[Required(ErrorMessage = " ")]
[DataType(DataType.Password)]
public string Pwd { get; set; }
What am I doing wrong here?
I can't tell you why the decision was made to treat these differently, but while the second parameter for these particular overloads of EditorFor()
and PasswordFor()
both accept an anonymous object, those objects actually represent different concepts.
For EditorFor()
, the second parameter is titled additionalViewData
:
An anonymous object that can contain additional view data that will be merged into the
ViewDataDictionary<TModel>
instance that is created for the template.
For PasswordFor()
, the second parameter is titled htmlAttributes
:
An object that contains the HTML attributes to set for the element.
In other words, you're operating at different levels here. When you set a property called htmlAttributes
on your anonymous object for EditorFor()
(i.e., additionalViewData
), that's being parsed out as HTML attributes on your rendered element:
<input autocomplete="off" class="…" id="password" placeholder="password" … >
But when you set htmlAttributes
on your anonymous object for PasswordFor()
(i.e., htmlAttributes
), that's being seen as an HTML attribute itself, as you can see in your HTML output:
<input htmlattributes="{ class = …, placeholder = password, id = password, autocomplete = off }" … >
As a result, what you should be doing in elevating the htmlAttributes
one level for your PasswordFor()
call:
@Html.PasswordFor(x => x.Pwd, new { @class = "form-control k-textbox large", placeholder = "password", @id = "password", @autocomplete = "off" })
Which should render something like:
<input class="form-control k-textbox large" placeholder="password" id="password" autocomplete="off" … >
And with the CSS classes correctly set, you should also find that the presentation aligned.