ASP.Net MVC3 Html.PasswordFor does not populate - asp.net-mvc-3

In my view I have the following element
#Html.PasswordFor(model => model.Password)
This is on a screen that creates/updates user details. When I am trying to update the user this field remains blank. When I change this element to a TextBoxFor it gets the data. How do I get to populate the Password field.

As described above, it is better to avoid doing this for security reason. if you still want to persist the password so that you proceed from where the current validation failed, you can use the HTML helper with html attribute parameter:
Html.PasswordFor(x => x.Password, new { value = Model.Password})

This is as designed. Passwords are not filled to prevent accidental resubmits, and to prevent the page from containing unencrypted passwords. Obviously the password was wrong to begin with if you're posting back the credentials.
In your case, you could create an extension that does input the data, or just use an HTML input of type password.

MVC protects you from doing something like this for a reason. You shouldn't actually be able to do this because the users password should not be stored unencrypted and unhashed. If your goal is to end end up on http://plaintextoffenders.com/ though, you can do something like:
<input type="password" name="Password" id="Password" value="#Model.Password" />

I found this workaound. I needed my password shown in the form:
#model User
#{
#Html.Label(Model.Username, new { #class = "label" })
#Html.TextBoxFor(Model => Model.Username, new { #class = "form-control" })
#Html.Label(Model.Password, new { #class = "label" })
#Html.TextBoxFor(Model => Model.Password, new { #class = "form-control make-pass" })
}
<script type="text/javascript">
$(".make-pass").attr("type", "password");
</script>
This will make your input password-type without losing the value.

As mentioned before, its by design. But that can be wrong. We just got a new user who was confused by the empty password after the page refresh when he just added a password. So a simple fix is to change the label 'Password' to 'New password'. Now its clear why this input box is always empty.

If you're using asp-for attribute you can also do:
<input type="password" placeholder="#(Model.Password != null ? String.Concat(Model.Password.ToCharArray().Select(p=>"*")) : "Password")" asp-for="Password">

Related

How to disable client side validation field wise

suppose my form has 5 fields and first two will be validated at client side and next one will not but next will. i got the guidance like
<div class="editor-field">
#{ Html.EnableClientValidation(false); }
#Html.TextBoxFor(m => m.BatchId, new { #class = "k-textbox" })
#{ Html.EnableClientValidation(true); }
</div>
but it did not work. i wrote Html.EnableClientValidation(true)
and after second field and before 3rd field i wrote Html.EnableClientValidation(false)
and again i wrote Html.EnableClientValidation(true) before 4th field. but i saw all fields are getting validated at client side.
thanks
Try #Html.TexBoxFor(model => model.BatchId, new {#class = "k-textbox", data_val = false})
That should disable validation for field

How to properly disable an Html Helper Textbox or TextBoxFor?

I have a razor display that is being used for entry. In one case, I would like the user to be able to populate the text box, in the other case, I would like to prevent the user from populating it. I am using code like:
#Html.TextBoxFor(model => model.Goop, new { #class = "text-box", maxlength = 2, onfocus = "javascript:this.select();" })
if (Model.Review.ReviewType.Equals("M"))
{
<script type="text/javascript">
$(function () {
$("#Goop").prop("disabled", true);
});
</script>
}
I have tried to do this several ways, jQuery (above), CSS attribs, javascript, ASP.NET... but all have the same issue: When the form is submitted, if the Goop textbox is disabled, the value for Goop in the model is Null. Ideas?
Thanks in advance!
Maybe it's not as cool without jQuery, but when I do this in my apps I do something along the lines of
if (Model.Review.ReviewType.Equals("M"))
{
#Html.DisplayFor(model => model.Goop)
#Html.HiddenFor(model => model.Goop)
}
else
{
#Html.TextBoxFor(model => model.Goop)
}
If a form element is disabled, it does not post a value. That's how it's supposed to work.
To work around this, you will need to do one of several things. You can enable the fields just before posting by intercepting the submit method. You can use a hidden field to store the data in addition to the disabled control. Or you can just assume the values on the controller side.
by the way, it should be .prop("disabled", "disabled"), which renders as disabled="disabled", that's standards compliant.

control name in TextBoxFor in MVC3

Is it possible to control the name attribute of say a text boxt when using TextBoxFor?
this code in the view
#Html.TextBoxFor(m => m.SearchParams.someParam)
produce this
<input id="SearchParams_someParam" name="SearchParams.someParam" type="text" value="">
but I do not want my input name to be "SearchParams.someParam" and I wanted that to be something like
<input id="SearchParams_someParam" name="MyPreferedName" type="text" value="">
where the MyPreferedName comes from from some attributes the .SearchParams.someParam in the corresponding model.
Is this possible? I know #Html.TextBox does it but I do not want to hardcode the name in the view.
#Html.TextBoxFor(model => model.attr, new { Name = "txt1" })
Just Use "Name" instead of "name"
It seems as though the TextBoxFor method will not allow you to use the #name key as an htmlAttribute. This makes a little bit of sense because if it did allow you to override the HTML name attribute, the value would not get binded to your model properly in a form POST.
Instead of using...
#Html.TextBoxFor(x => Model.MyProperty, new { #name = "desired_name" }); // does not work
I ended up having to use...
#Html.TextBox("desired_name", Model.MyProperty); // works
I am not exactly sure why the first option does not work but hopefully this helps get around it.
Use TextBox instead of TextBoxFor
#Html.TextBox("MyPreferedName", Model.SearchParams.someParam)
TextBoxFor doesn't allow the name attribute to be set. This workaround:
#Html.EditorFor(m => m.UserName, null, "user_name")
outputs:
<input class="text-box single-line" id="user_name" name="user_name" type="text" value="" />
Don't this work?
#Html.TextBoxFor(m => m.SearchParams.someParam, new { id="my_id" }) although for your specific case it's be more like:
#Html.TextBoxFor(m => m.SearchParams.someParam, new { name = "MyPreferedName" })
Here you'll find the different overloads for the constructor of the InputExtensions.TextBoxFor in MVC3

How to get model's field name in custom editor template

I'm building my first custom editor template for a text area control. My code so far is -
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<%= Html.TextAreaFor( Model => Model , 2, 30,
new { #class = "html", #placeholder = ViewData.ModelMetadata.Watermark }) %>
It's not much so far, but it does work. But we need to add a character counter field to show remaining number of characters that the user can type in. I know how to do all the JavaScript to make this work.
So to keep naming system same, I'm going to add a control named ".charCounter" to display number of remaining characters left. My problem is that I cannot figure out the correct syntax to be able to retrieve the field name for the model.
The final version will look something like (JavaScript omitted) -
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<%= Html.TextAreaFor( Model => Model , 2, 30,
new { #class = "html", #placeholder = ViewData.ModelMetadata.Watermark }) %>
<span class="xxx">Remaining characters -
<input readonly type="text" name="<fieldName>.charCounter" />
</span>
You could use ViewData.TemplateInfo.HtmlFieldPrefix, like this:
<input
readonly="readonly"
type="text"
name="<%= ViewData.TemplateInfo.HtmlFieldPrefix %>.charCounter"
/>
I ran into an issue where the PropertyName wasn't returning the Model prefix eg Contact.FirstName. I was able to have it return the HTML field Id using this:
#ViewData.TemplateInfo.GetFullHtmlFieldId("")
Returns:
Contact_FirstName
Respectively you can return the field name using:
#ViewData.TemplateInfo.GetFullHtmlFieldName("")
Returns:
Contact.FirstName
ViewData.ModelMetadata.PropertyName works nicely in MVC3.
In razor:
<input readonly="readonly" type="text" name="#ViewData.ModelMetadata.PropertyName">
Getting just the model name/Id (e.g BirthDate):
ViewData.ModelMetadata.PropertyName;
Getting the model name with prefixes for complex objects (e.g Identity.Person.BirthDate):
#Html.NameFor(m => Model);
or
ViewData.TemplateInfo.HtmlFieldPrefix;
Getting the model Id with prefixes for complex objects (e.g Identity_Person_BirthDate):
#Html.IdFor(m => Model)
or
#Html.IdForModel()

ASP.NET MVC 3 - Validation Question

Good evening everyone I have a question regarding validation of drop-down list values. I have a view that is bound to a view model type called ReservationData.
This object contains a property CustomerVehicles of type List<VehicleData>. VehicleData has two int properties VehicleMakeId and VehicleModelId.
On my view I am trying to loop over the number of items in the CustomerVehicles collection and displaying two dropdowns for each, a vehicle make dropdown and a vehicle model dropdown using DropDownListFor.
When I try to submit and validate I do not see any validation errors displayed on the screen.
Just in case you are wondering I have added a ValidationMessageFor for each dropdown as well. I am not sure if this is an issue with the structure of my view model and its complexity and how the controls need to be named or how the ids need to be set. Any help would be greatly appreciated.
Here is the code for the looping over the collection:
#for (var i = 0; i < Model.CustomerVehicles.Count(); i++)
{
var vehicleNumber = i + 1;
<div class="vehicle-selection-wrapper">
<div class="content-container">
<h3>
Vehicle #vehicleNumber</h3>
<img class="vehicle-image" alt="manufacturer image" src="#Url.Content("~/Content/images/default-vehicle.gif")" /><br />
#Html.LabelFor(m => m.CustomerVehicles[i].VehicleMakeId)
#Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleMakeId
, new SelectList(Model.VehicleMakes, "Id", "Name")
, #UIDisplay.Dropdown_DefaultOption, new { #class = "long-field" })<br />
#Html.ValidationMessageFor(m => m.CustomerVehicles[i].VehicleMakeId)<br />
#Html.LabelFor(m => m.CustomerVehicles[i].VehicleModelId)
#Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleModelId
, new SelectList(new List<CWR.Domain.VehicleModel>(), "Id", "Name")
, #UIDisplay.Dropdown_DefaultOption, new { #class = "long-field" })
#Html.ValidationMessageFor(m => m.CustomerVehicles[i].VehicleModelId)
</div>
</div>
}
Ok so I also noticed that in the generated HTML the selects that are generated are missing the HTML5 data-val attributes that are associated to elements to handle validation. Here is the generated HTML
<select class="long-field" id="CustomerVehicles_0__VehicleMakeId" name="CustomerVehicles[0].VehicleMakeId"><option value="">-- Select --</option>
</select><br />
<span class="field-validation-valid" data-valmsg- for="CustomerVehicles[0].VehicleMakeId" data-valmsg-replace="true"></span><br />
<label for="CustomerVehicles_0__VehicleModelId">Model</label>
<select class="long-field" id="CustomerVehicles_0__VehicleModelId" name="CustomerVehicles[0].VehicleModelId"><option value="">-- Select --</option>
</select>
<span class="field-validation-valid" data-valmsg-for="CustomerVehicles[0].VehicleModelId" data-valmsg-replace="true"></span>
Additionally in my VehicleData class the VehicleMakeId and VehicleModelId properties are decorated with a Required attribute.
UPDATE:
Ok so I was testing and noticed that if I keep my code identical except I swap the Html.DropdownListFor calls with Html.TextboxFor calls then the validation works. What could be causing this? Could it be a framework bug with the unobtrusive validation?
UPDATE: Contains Fix
So after posting this same question on the ASP.NET Forums, I was able to get a solution. In the post you will be able to see that there is a bug in the unobtrusive validation framework and how it handles validation of dropdownlists. The user counsellorben does a good job in explaining the problem as well as a solution (including sample code) that will assist others in avoiding this issue in the future, or at least until Microsoft builds in a fix in to the framework.
Thank you everyone for your assistance.
I too have come across this obviously massive oversight regarding client side validation with dropdownlists in MVC 3 and the best solution I can offer is to put the missing HMTL attributes in yourself.
In your view model create a property like this.
public Dictionary<string, object> CustomerVechicleAttributes
{
get
{
Dictionary<string, object> d = new Dictionary<string, object>();
d.Add("data-val", "true");
d.Add("data-val-required", "Please select a Vechicle.");
return d;
}
}
Then in your code, enter
#Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleMakeId
, new SelectList(Model.VehicleMakes, "Id", "Name")
, #UIDisplay.Dropdown_DefaultOption,
**Model.CustomerVechicleAttributes** })
Just add the Model.CustomerVechicleAttributes as htmlAttributes to your dropdownlist.
This will inject the necessary attributes that are missing. You will of course need to add any other attributes you may need like your class attribute.
Hope this helps.
This is the simpliest way I found to do it, just adding data-val-*-* attributes in HtmlAttributes of DropDownListFor, inside the view. The following method works with RemoteValidation too, if you do not need remote validation, simply remove the elements containing data-val-remote-*:
#Html.DropDownListFor(m => m.yourlistID, (IEnumerable<SelectListItem>)ViewBag.YourListID, String.Empty,
new Dictionary<string, object>() { { "data-val", "true" },
{ "data-val-remote-url", "/Validation/yourremoteval" },
{ "data-val-remote-type", "POST" }, { "data-val-remote-additionalfield", "youradditionalfieldtovalidate" } })
I hope it may help. Best Regards!
you should try to add data annotations on your view model properties first so you could see the validation messages.
you might find what you need here
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx
or create custom ones if needed.
what exactly do you need to validate?
I had exactly the same problem with the field getting correctly validated in TextBoxFor but not in DropDownListFor.
#Html.DropDownListFor(m => m.PaymentTO.CreditCardType, Model.CreditCardTypeList, "Select Card Type", new { style = "width:150px;" })
Since I had another DropDownListFor working on the same page, I knew that it wasn’t a generic DropDownListFor problem. I also have a complex model and parent object PaymentTO wasn’t initialized. When I set viewTO.PaymentTO = new PaymentTO(); in the Controller, the validation for the DropDownListFor started to work. So there is probably a problem with DropDownListFor, but the fix can be as simple as initializing the object in the controller.

Resources