Stopping form prepopulation in MVC - asp.net-mvc

In an MVC view with a form on it and given the following code using HTML helpers:
#Html.TextBoxFor(m => m.FirstName, new { id = "firstName", maxlength = "50", #class = "form-input" })
Is there a way to stop this form automatically populating the fields with data? I know it's by design and in most cases is helpful but in this case I want to be able to turn that functionality off.
To clarify - If I have a ViewModel with this property in it:
[Display(Name = "First Name")]
public string FirstName { get; set; }
I understand that the HTMLHelper TextBoxFor will allow me to use the strongly typed
m => m.FirstName
when creating the input.
That's fine. However, if I have the ViewModel populated with data then it also shows this data in the input field, this is by design and I get that.
Now, imagine you wanted the strength of the strongly typed aspect but without the automatic filling of the data.
The only option appears to be:
#Html.TextBox("myTextBox", "value goes here", new { #class = "form-control" })
Which is brittle where the name / id values are concerned. I prefer the strongly typed nature of the TextBoxFor but can't have that without also automatically showing whatever the ViewModel data is.

It sounds like you're talking about the browser behaviour here, so you want to turn off autocomplete. You can use this on a per input basis:
#Html.TextBoxFor(m => m.FirstName, new { ..., autocomplete = "off" })
Or you can do it on the whole form:
#Html.BeginForm(action, controller, FormMethod.Post, new { autocomplete="off" })
EDIT:
Reading your comments it seems you're populating the view model with the values and seeing them when you render the view. In which case, the answer is simple, reset the model before passing it to the view:
return ViewModel(new TModel());

While passing the viewmodel to view in controller you can set those properties to blank value or null for which you want empty textboxes in UI.

Related

ASP.NET/MVC: Automatic "validation-as-you-type"?

EDIT: I got it working now for text fields (see the comments below the question).
However, for some reason, the validation doesn't kick in for my dropdown-list.
In my ViewModel I have this:
[Display(Name = "Country")]
[Required(ErrorMessage = "{0} is definitely required!")]
public int CountryId { get; set; }
In my View I have this:
#Html.LabelFor(m => m.CountryId, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.CountryId, Model.CountryList, "—Select a country --",
new { #class = "form-control" })
<div class="container_voor_error">
#Html.ValidationMessageFor(m => m.CountryId, "", new { #class = "text-danger" })
</div>
</div>
The code in the controller need not be given here I think, since it works fine: it fills the CountryList with the countries, and then later after submit it does the server-side validation and processing, no problem.
So the scenario is this:
I select a country in the dropdown list (say, Belgium);
Then I de-select that choice again, so that it shows “-- Select a country -- “ again;
Now the (lazy) client-side validation should kick in and result in an error message: “Country is definitely required!”;
But that doesn’t happen, no error message is shown.
So... Am I forgetting something, or doing something wrong?
END-OF-EDIT
An easy question for the MVC/ASP.NET experts, I suppose. But as I'm still finding my way in this framework (school courses), this is something I've been wondering about, and that I haven't found an explicit answer to.
It's about client side validation of form input, using annotations in my model (or viewmodel). I get that, as long as one or more of the annotated validation requirements are NOT satisfied, the values of the form fields are NOT sent to the server upon submit. Instead, the same form view is displayed again, this time with the applicable error message shown. That is, of course, assuming that an HTML helper for those error messages (like Html.ValidationMessageFor) is included with the form fields. So far, so good.
However, there's such a thing as "validation-as-you-type". Meaning that the error messages appear (and change) while the user is still typing, as opposed to appearing only on the re-loaded form after the user has hit submit. And this is my question: Is "validation-as-you-type" supposed to be operational automatically? Because that's what seems to be generally implied (though hardly explicitly stated) by internet sources/tutorials.
But my experience has been different: In order to have "validation-as-you-type", I always need to write JavaScript/jQuery event handlers (such as keyUp() and onChange()), in which I explicitly call
$('some-selector').validate().element('some-element');
So my question is: Is it normal that I have to make these explicit calls to method validate() for each to-be-validated form element? Or is there, in ASP.NET/MVC, a way to enable automatic "validation-as-you-type" for all elements (or perhaps a subset of elements) on a view form?
Thanks.
No, ASP.NET MVC does not offer Automatic "validation as you type". To have a "validation as you type" it must be javascript code. ASP.NET Mvc uses jQuery Validation plugin by default, and this plugin does validation on blur event, which is not the same as on keyup events.
All that ASP.NET MVC does, is render some html attributes to the elements, also known as unobtrusive validation. You can check this if you see the page source with validation enabled and then with disabled. Then there is a javscript library that uses the values in those attributes to hook up to proper events.
Lastly, one is also able to use different plugin/library for this, and also one is also able to change how ASP.NET emits validation to the client side.
This is how you validate immediately. This works in ASP.NET Core. This validates immediately, not only after the first blur.
In document.ready (jquery), do this:
function CustomValidationMarco() {
var validator = $("form").data("validator");
if (validator) {
//validator.settings.onkeyup = true; // disable validation on keyup
validator.settings.onkeyup = function (element) {
$(element).valid();
};
//validator.settings.onfocusout = function (element) {
// $(element).valid();
//};
}
}

MVC Show an icon beside a valid field after form post

Been struggling hunting around the web looking for an answer to this one but to no avail. What I want to do is show an icon beside a textbox if the field is valid.
I have a form that posts back data to the controller to be checked against some internal logic, essentially what I want is to post the form run the method to check the data and if it is valid it should show a green tick beside the field. I have validation on the form and it is working as expected if the validation fails, just not on success.
Any help would be much appreciated.
Thanks
As for code not sure it is really relevant but it follows the structure below.
// Controller
private ActionResult DoSomeThing(myModelType model)
{
//... Do checking in here
}
// Model
[Required(ErrorMessage = "Please enter a value.")]
[StringLength(45, ErrorMessage = "Value can only have a maximum of 45 characters.")]
public string SomeValue { get; set; }
// View
#Html.LabelFor(x => x.SomeValue , new { #class="control-label" })
#Html.TextBoxFor(x => x.SomeValue , new { #class="form-control" })
#Html.ValidationMessageFor(x => x.SomeValue )
The way you could achieving "Client-side custom data annotation validation" is using jQuery. Use $('#myelement').change(function () ) syntax for tracking changes on you element on view. Use function () for validation logic and then based on your resault use a green check mark visible beside your element you want to validate.
Also you could some third party one like here.

ModelState.IsValid for the unnecessary field Name

I have a very simple model. I have a location that has 2 fields, Id and Name. I have InventoryItems that has a number of scalar fields with a FK to the location at which it is stored. I have a View for creating an InventoryItem. The view has a drop down for `
<div class="editor-label">
#Html.LabelFor(model => model.Location)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Location.Id, new SelectList(ViewBag.Locations, "Id", "Name"))
</div>
The controller code checks ModelState.IsValid which is returning false because the NAME of the location in the ModelState is empty. I really only need the Id to save the InventoryItem. But I have [required] in the Location Name field because when I go to allowing the addition of Locations, I want that field required.
Can someone tell me the CORRECT way to deal with this in the MVC design pattern?
Well if the name is already set before this point you could just use a #Html.HiddenFor() to hide the name on the page it keeps the value for the HttpPost.
If this isn't the case then I suggest dropping the required requirement on the name in the model itself and use it on a View Model, this way you can have two different levels of validation, just bare in mind you need to make sure that if the field isnt populated at the point where it's needed it will error.
Personally I would use View Models whenever you have changing validation requirements
The best way to go about it is to use ViewModel that have only the fields you need on the UI side and then convert to your actual Model in the controller.
In your case, you could use a LocationLink in your View/Form that only takes an Id like:
public class LocationLink
{
[Required(ErrorMessage = "No id provided")]
public string Id { get; set; }
}
Then in your controller you load the appropriate Location from your data store with the supplied Id and add that to the parent model.
Usually you should have a ViewModel for Display with all the fields (Locationwith Id and Name) and a ViewModel for create/edit forms (LocationLink in that case with only Id).

Confused about Usage of LabelFor() html helper in MVC 2.0

I am working on an MVC 2.0 C# web Applciation. In one of my form, i am using LabelFor() html helper.
I am using the following syntax:
<%=Html.LabelFor(model=>model.Addedon)%>
Here, for this label i would like to associate a initial value that is DateTime.Now
I tried some thing like this:
<%=Html.LabelFor(model=>model.Addedon,new{value=DateTime.Now})%>
But, i am getting an error saying that there is no over load for this helper taking two arguments.Please help
UPDATED:
The form is create form/ add form which makes an insert operation. So, i am building a model and updating that model to the database.
In that model, i have a field called createdby. So, i need to associate this value with the username logged in and doing the insert operation.
So, how to associate this username value with the model field and i need to display as label so that it will be read only field.
Hope this makes clear..
LabelFor is only for, you guessed it, rendering a <label> element.
It also uses the [Display] and [DisplayName] attributes, so you can have a strongly-typed label with custom name.
What you're after is probably this:
<div>
<%= Html.LabelFor(model => model.Addeon) %>
</div>
<div>
<%= Html.DisplayFor(model => model.Addeon) %>
</div>
So the LabelFor will generate the property name description (e.g. 'Addeon'), while the DisplayFor will render the property value. DisplayFor can use the [DisplayFormat] attribute if you need custom formatting. You can set the default property value in the view model's constructor:
public class ViewModel
{
[Display(Name = "My awesome date")]
public DateTime Addeon {get;set;}
public ViewModel()
{
Addeon = DateTime.Now;
}
}
[EDIT]
Actually, your edit would make for a good second question instead of putting it here. Anyway, in your situation I'd create a dedicated view model that would hold the properties you need (e.g. user name) and would be filled in controller. Everything else would be conceptually the same - view would bind to the view model.

Model with List - approaches to add new item to the list from a Razor view

I have a model with various properties but the one of interest is a List of another type of Model.
For example:
public class User
{
public string Name { get; set; }
public string Description { get; set; }
public IEnumerable<UserInterest> Interests { get; set; }
}
I then use an Editor Template within my view to render out a view for each item of the model items.
#Html.EditorFor(x => x.Interests)
The EditorFor template looks something like:
#model Interest
<div>
#Html.HiddenFor(x => x.Id)
#Html.TextBoxFor(x => x.InterestText)
#Html.CheckBoxFor(x => x.Delete)
....
</div>
Something very similar to the accepted answer here: Model Containing List of Models (MVC-3, Razor)
My question is - how would you from the client-side (jQuery) create a new item within the property without going back to the server. I currently have a rough way of doing it whereby I post the data back to my controller which returns the model back with a new blank item within the Interests property.
This seems to be overkill making a HTTP request and not very elegent. I was thinking of using jQuery .Clone() but not entirely sure on what I'd need to do in terms of naming the elements and clearing existing values.
So does anybody have any suggestions. I'm hoping to get more opinions and different approaches.
You can simply create the Textbox and checkbox on the fly and add that to the DOM. When saving it, Use jQuery ajax to post that data ( new record data) to an action method and save it there. Return a status back (Succcess /Falied) from your action method to your client side code ( your callback function of jQuery ajax/post) and check it there. If it is success, Show a success message to the user and append the new item to the existing list.
Sample jSFiddle : http://jsfiddle.net/carwB/2/
If you want to return some complex data ( ex : All new records with its id etc..) along with the status, you may return JSON from your action method.
EDIT : To keep your Model binding works with the newly added dynamic elements, you need to follow the naming convention of the elements.
The trick is to keep the id property value of the html element in this format.
CollectionName_ItemIndex__PropertyName
and name property value in this format
CollectionName[ItemIndex].PropertyName
I created a sample working program and explained it how it works Here based on your requirements.
In such situations I prefer to use client templating. You send data to server with ajax and then receive JsonResult. Look at JsRender this is javascript lib without jQuery dependency.
1.Create two partial view one is for list item and second one is creation
2.First partail view should be inside the div which has id 'divMdeolList'
3.and Creation view will have the code like that
#using (Ajax.BeginForm("SubmitData", new AjaxOptions { UpdateTargetId = "divMdeolList" }))
{
#Html.TextBoxFor(x => x.InterestText)
<p>
<input type="submit" value="Create" />
</p>
}
4. And then create a ActionResult type action on controller that will render the partialview
public ActionResult SubmitData(YourModel model)
{
//Do : save the record
return PartialView("FirstPartailView", model);
}
This will update the View without postback

Resources