Our application (MVC5) has some very complex validation that needs to be done server side (compound capacity checks, workflow validation, and more). The problem we are running into is that once server side validation fails and returns to the same view, the client side never submits values for any fields again (0 for int, empty strings, etc.)
Our general pattern is as follows:
public ActionResult PerformSomeAction()
{
var model = GetActionTemplate();
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult PerformSomeAction([Bind(Include = ActionTemplate.FIELDS)] ItemTemplate template)
{
string errorMessage;
if (ModelState.IsValid)
{
bool isValid = ValidateAndPerformAction(template, out errorMessage)
if(isValid)
return RedirectToAction("Action", "Controller");
}
// Reset non-bound fields from new template
var model = GetActionTemplate();
template.FieldValue = model.FieldValue
return View(template);
}
Our views don't have anything special in them, other than the fact that some of our editors are built with the Telerik Kendo library. However, the symptoms are seen for all controls, not just Kendo based ones.
A basic View layout for editing a field is as follows:
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-9">
#Html.Kendo().TextBoxFor(model => model.Name).HtmlAttributes(new
{
title = ModelMetadata.FromLambdaExpression(model => model.Name, ViewData).Description
})
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
Does anyone have any suggestions on what we are doing wrong?
Note: While it could be argued that this validation could be triggered through AJAX or other service calls, we would prefer to do it with the post implementation that we are using.
Update:
After further research, it appears this has to do with Kendo and not MVC. If I switch my View to be the following:
#Html.EditorFor(model => model.Volume)
Instead of:
#Html.Kendo().NumericTextBoxFor(model => model.Volume).HtmlAttributes(new
{
#class = "",
title = ModelMetadata.FromLambdaExpression(model => model.PreBoilVolume, ViewData).Description
}).Value(Model.Volume)
Everything appears to work fine. So somewhere in that Kendo statement it fails to rebind when returning from the post. It doesn't matter if I set the value again manually, it will never send it back in.
I guess it is time to get rid of some Kendo statements and go back to a more basic UI.
What you "want" to do is a very basic scenario for MVC with failed validation.
The first one that always catches people is with drop down lists. The posted model, does not contain the list of items, so has to be re-populated after failed validation, and then passed back into the view on return.
When I can't solve things like this I start commenting stuff out and work forwards. So in this case strip your model back to one non-ID property and see if it will work. Then you can try and track down the culprit.
It looks like the selectedvalues are not set on the model. Try change these lines of code:
var model = GetActionTemplate();
template.FieldValue = model.FieldValue
return View(template);
to something like this:
var model = GetActionTemplate();
model.Selectedvalues = template.FieldValue ?
return View(model);
Related
I have the following code:
#Html.EditorFor(model => model.AssociatedCard, new { htmlAttributes = new { #class = "form-control", #id="addCardBox", #onkeydown="test()"} })
Notice the #onkeydown="test()" attribute. This works fine, on keydown, a JS function is called.
But I want to send the key that was pressed, to the server, and save it to the database.
How can I send this key to the server, so that I can handle it in the C# code?
In asp.net, we can do something like this (which will allow me to bind to the TextBox):
<asp:TextBox id="txt" Runat="Server"></asp:TextBox>
At server side, I can then reach my textbox with the id=txt. Can I do something similar, without having to use ajax/JQuery?
Provided EditorFor is producing a textbox you can do the following as it will capture the input.
You appear to be on the right track given that you've created a strongly typed view, you just need to wrap your inputs in a form to post them to the server.
#using (Html.BeginForm("PostAction", "Home"))
{
//Put your foreach loop in here
}
Then in your controller
public class HomeController : Controller
{
[HttpPost]
public ActionResult PostAction(ViewModelType model)
{
//model.AssociatedCard should contain your value
}
}
I have one MVC project,containing user registration form which have 25-30 fields to fill. After filling form if user forgot to fill mandatory field then it will shows validation error. But remaining all fields loss their data.
I mentioned in controller like
if (!ModelState.IsValid)
{
ModelToDBclass obj = new ModelToDBclass();
objModel.Id = Convert.ToInt32(obj.GetMaxPaperId());
objModel.countryNameDB = obj.GetcountryName();
return View(objModel);
}
and finally it returns the blank view. but at runtime when it comes to
return View(objModel); , the model shows the data with every field, but when it comes to view it unable to show record in text boxes and dropdown. I used textbox like,
<div class="col-sm-2"><input type="text" class="form-control" name="ConsumerFName" id="txtConsumerFirstName" placeholder="First Name" />
#Html.ValidationMessageFor(m => m.ConsumerFName)</div>
so, please help me how can i display filled record after validation error
You should always use Html Helper
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" }, placeholder = "First Name", autofocus = "autofocus" })
Then only when the Model state is not valid, it will show the returned object values at the respective fields. Don't normal html tags.
Hope this helps
I want to display error messages dynamically i.e, when the cursor moves out of the field but not when the form is submitted.
My requirement is like this:-
I have to design a registration form with some fields like name,address,phone number,email,password etc.
i designed it & saved the data successfully in DB but what i exactly required in the sense i have to display error messages dynamically without using "ajax" as i have already stated ...
My code is like this:-
View:-
<div class="venfor_line5" popText><label>#Resources.Resources.VendorReg_phoneNumber<img src="~/images/star.png" /> </label>
#Html.TextBoxFor(model => Model.MobileNumber, new { #class = "input" })
#Html.ValidationMessageFor(model => model.MobileNumber)</div>
<div class="venfor_line1" popText = #Resources.Resources.VendorReg_emailHintStr>
<label>#Resources.Resources.VendorReg_email<img src="~/images/star.png" /> </label>
#Html.TextBoxFor(model => Model.Email, new { #class = "input" })
#Html.ValidationMessageFor(model => model.Email)</div>
I have gone through many references but not found exactly what i am looking for.Any help would be greatly appreciated. can anyone guide me in resolving this issue.
You could use jQuery's focusOut() method to perform validation. Something like:
$('#elementId').focusOut(function(){
//do validation here
});
If you are using unobtrusive jQuery validation you could eagerly enable it so that it is automatically triggered onblur without requiring the user to submit the form:
$(document).ready(function () {
var settngs = $.data($('form')[0], 'validator').settings;
settngs.onfocusout = function (element) { $(element).valid(); };
});
I am building my first MVC site using MVC 4 in C# and Entity Framework 4.1. I have a model that displays a list of items with standard "add", "edit", "details", and "delete" options.
The database that's linked to the model has a column for "Username" and my application currently displays a text box for the user to enter their username via the following code from the Create.cshtml file.
<div class="editor-field">
#Html.EditorFor(model => model.UserName)
#Html.ValidationMessageFor(model => model.UserName)
</div>
I'm trying to alter this so that their User.Identity.Name (e.g. DOMAIN\user) value will either auto-populate in the text box, or even better, just be stored without showing the user that it's happening.
Is there a relatively painless way to accomplish this?
EDIT: My Controller code for the "create" section currently looks like this:
public ActionResult Create(Occurrence occurrence)
{
if (ModelState.IsValid)
{
db.Occurrences.Add(occurrence);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.EmployeeID = new SelectList(db.Employees, "EmployeeID", "EmployeeName", occurrence.EmployeeID);
return View(occurrence);
}
You can set the username in the controller
public ActionResult Create()
{
string username = Environment.UserName // or however you get it
User user = new User{UserName = username};
return View(user);
}
another option is to handle it in the view
#Html.ValidationMessageFor(model => model.UserName, new{#Value = Environment.UserName})
I'm using ASP .NET MVC 3 with Data Annotations and the jQuery validate plugin.
Is there a way to mark that a certain field (or certain data annotation) should only be validated server-side?
I have a phone number field with a masking plugin on it, and the regular expression validator goes crazy on the user's end. The regex is only a fail-safe (in case someone decides to hack the javascript validation), so I don't need it to run on the client side. But I'd still like the other validation to run client side.
I'm not sure if this solution works on MVC3. It surely works on MVC4:
You can simply disable client side validation in the Razor view prior to render the field and re-enable client side validation after the field has been rendered.
Example:
<div class="editor-field">
#{ Html.EnableClientValidation(false); }
#Html.TextBoxFor(m => m.BatchId, new { #class = "k-textbox" })
#{ Html.EnableClientValidation(true); }
</div>
Here we disable client side validation for the BatchId field.
Also I have developed a little helper for this:
public static class YnnovaHtmlHelper
{
public static ClientSideValidationDisabler BeginDisableClientSideValidation(this HtmlHelper html)
{
return new ClientSideValidationDisabler(html);
}
}
public class ClientSideValidationDisabler : IDisposable
{
private HtmlHelper _html;
public ClientSideValidationDisabler(HtmlHelper html)
{
_html = html;
_html.EnableClientValidation(false);
}
public void Dispose()
{
_html.EnableClientValidation(true);
_html = null;
}
}
You will use it as follow:
<div class="editor-field">
#using (Html.BeginDisableClientSideValidation()) {
#Html.TextBoxFor(m => m.BatchId, new { #class = "k-textbox" })
}
</div>
If anyone has better solutions please let me know!
Hope this help.
You can switch off client-side unobtrusive validation for a single field by adding a data-val='false' attribute:
#Html.TextBoxFor(m => m.BatchId, new { data_val = "false" })
This will override the data-val='true' attribute that MVC adds due to any System.ComponentModel.DataAnnotations attributes. The HTML element will still be decorated with other validation attributes (e.g. data-val-required) but they won't have any effect.
(Note the underscore in data_val above. MVC automatically converts underscores to hyphens in anonymous type properties, so data_val becomes data-val when rendering the HTML)
MVC5 use jquery.validate
http://jqueryvalidation.org/rules/
If you want to remove validations in MVC5 client-Side you need to do the following:
Remove all validations on 'myinput'
$("#myinput").rules("remove");
Specific validations
$("#myinput").rules("remove", "min max" );
Listing the validations can help
$("#myinput").rules();
Then you will need to correct your Code Behind to validate manually your model or differently because ModelState.IsValid will be false. Using ModelState.Clear() and TryValidateModel can then be handy.
Edit:
Disabling the control also remove the validations.
$("#myinput").attr('disabled', disabledValue);
Assuming you use default unobtrusive validation, You could use some javascript to remove rules on client side. Take a look at Plugins/Validation/rules
To achieve this goal in the given scenario, we need to make two tweaks.
Client Side
To disable client side validation, we need to disable it by force.
#Html.EditorFor(model => model.Password, new { htmlAttributes = new { #data_val = "false" , #class = "form-control"} })
Notice the #data_val= “false”. It will disable the validation on this field.
Server Side (In Action)
When the model is validated on the post action, ModelState.IsValid will always return false because password is not provided. Here we have to provide the current password to the model and Re-validate the model.
var userObj = db.Users_Info.Where(a => a.Id == users_Info.Id).FirstOrDefault();
if (String.IsNullOrEmpty(users_Info.Password))
{
users_Info.Password = userObj.Password;
}
ModelState.Clear();
TryValidateModel(users_Info);
Let me explain, first we retrieve current information saved in the database which we are using later to assign to current model if password is not provided. The last two lines actually reset the ModelState to return updated result on ModelState.IsValid.
I ran into trouble with data_val="true". I had a sequence of radio buttons tied to a single property in my model. The data validation only worked when I applied data_val="true" to the first #Html.RadioButtonFor call.
In debugging this, I discovered you can also disable or alter individual rules on the client side by using data_rule_??. The rules can be found in the jquery validation documentation.
for example;
#Html.RadioButtonFor(m => m.Answer, "Yes", new { data_rule_Required = "false" });
#Html.TextBoxFor(m => m.Answer, new { data_rule_minlength = "10" }
If you want to remove validations in MVC5 client-Side you need to do the following:
$("#Email").rules("remove", {
"required",
"minlength",
"email"
}
});