I'm using ASP.NET MVC 3. I have an integer field and as a test I am entering character values in the text box which are invalid for ints.
So when I test,
I enter an invalid value and click submit.
MVC passes back the following error message:
The value 'FF,' is not valid for FCode.
So then I erase the FF from the form field and enter HH, then click submit. And then MVC gives me the following messages:
The value 'FF, HH' is not valid for FCode.
Then say I change the form field to BB, I get the following error returned:
The value 'HH, BB' is not valid for FCode.
It is always returning the latest 2 in the error message. How can I fix this to only return the latest 1? Users don't want to see their previous mistakes, they only want to see most recent.
Here is the code from my controller:
if (ModelState.IsValid){
//Do valid stuff here
}
else
{
var query =
from val in ModelState.Values
where val.Errors.Count == 1
select val.Errors;
foreach (var error in query.ToList())
{
errorList.Add(error[0].ErrorMessage);
}
Response.TrySkipIisCustomErrors = true;
Response.StatusCode = 500;
return Json(errorList);
}
I was actually binding to same field in the model twice. That is what was causing this. I was using a TextBoxFor and a HiddenFor on the same field.
So when MVC sent the model errors back to my controller on form submit, it was sending 2.
I changed my TextBoxFor to a TextBox and this solved the problem since it is now only bound to the hidden.
Related
I have a View in MVC called Action, which accepts and ID as parameter. I also have another view called Action, but it is marked as HTTPPOST.
The POST version of Action can fail programatically. When it fails, I want to add a ModelError, and then Redirect to the GET version of Action, whilst I provide the ID .
In short => I want to transfer to a GET view from a POST view, and pass parameters. Something along the lines of
ModelState.AddModelError("", "Could not verify token");
return RedirectToAction("Action", "ExpiredAccounts" new { aid = myId });
Where Action is the View, ExpiredAccounts is the Controller and AID is the Account ID. This of course does not work since you can add a model error to a view, not redirecting
Thanks
You'd better return the same view in this case instead of redirecting:
ModelState.AddModelError("", "Could not verify token");
var model = repository.Get(myId);
return View(model);
The correct flow of the Redirect-After-Post pattern is the following:
GET request -> some form is displayed
POST request -> the form is submitted to the server. Two possible cases here:
Validation succeeds => Redirect.
Validation fails => redisplay the same view so that the user can fix the errors
If you want to violate this best practice you could always send the error message as query string parameter when redirecting:
return RedirectToAction(
"Action",
"ExpiredAccounts"
new { aid = myId, error = "Could not verify token" }
);
and then in side the target action verify whether this parameter has been supplied and add an error to the modelstate:
public ActionResult Action(int myId, string error)
{
if (!string.IsNullOrEmpty(error))
{
ModelState.AddModelError("", error);
}
...
}
Hi I have just started Vaadin 7 and have got the BeanValidator working. But, I have some issues. The code I am using is the following:
BeanItem<RegisterBean> item = new BeanItem<RegisterBean>(new RegisterBean());
final FieldGroup binder = new FieldGroup(item);
final TextField email = new TextField("email");
email.addValidator(new BeanValidator(RegisterBean.class, "email"));
The validates fine using the BeanValidator. With the #NotNull tag I am able to validate for Null values as well. However, I would like to give the user visual clues that the field in the form can't be left blank. For this, I used:
email.setRequired(true);
However, after adding the setRequired the BeanValidation for the form no longer works?
Is this a limitation?
How do I get around it?
You should probably rely on the bean validation itself and use the fieldgroup.
My model looks as follows:
#NotNull(message="Please enter a valid email address.")
#Email(message="Please enter a valid email address.")
#Size(min = 3, max = 255, message="Please enter a valid email address.")
#Column(name="P_EMAIL", nullable=true, length=255)
private String email;
In your view do either buildAndBind
Field<?> email = binder.buildAndBind("email");
Or use the annotation #PropertyId("email") in your field declaration. The rest is magic.
Instead of FieldGroupuse BeanFieldGroup.
A problem will be that validation is made preliminary. So install the validators on click. More to that topic can be found here: http://morevaadin.com/content/bean-validation-and-vaadin-comprehensive-example/
To complete the example above, using a BeanFieldGroup, as it got validators, you can use the setValidationVisible method of an AbstractField to turn off preliminary validation, then to turn on in a blurListener and in the buttons clickListeners.
AbstractTextField cName = binder.buildAndBind("Name","name", AbstractTextField.class);
cName.setNullRepresentation("");
cName.setValidationVisible(false);
cName.addBlurListener(new MyBlurListener(cName)); //<-- turn on setValidationVisible there
myButton.addClickListener(event -> {
try {
cName.setValidationVisible(true);
binder.commit();
} catch (CommitException e){
Notification.show("Sending error");
}
});
I have a page written using .NET MVC. In the model for a Person called PersonModel I have this defined which requires the user to enter some text in the last name field:
<DisplayName("Last Name"), Required()> _
Public Property LastName() As String
Get
Return _LastName
End Get
Set(ByVal value As String)
_LastName = value
End Set
End Property
On the form, there is a checkbox that a user can check to do some other things. Is there a way, using JQuery preferablly, to change that Last Name field to be non-Required? If not using JQuery I am open to other suggestions but since I am doing alot of things when this check box is checked anyways, I was hoping I could add this logic in there. Here is some sample of what I am doing when this box is checked to demonstrate...
function doOwnerBusiness(event) {
if ($(this).is(':checked')) {
$('input[name="People_1__LastName"], label[for="People[1]_LastName"]').hide();
$("#People_1__LastName").hide();
$("#People_1__LastName").val("");
$("#People_1__LastName :input").attr('disabled', true);
$('input[name="People[1]_Suffix"], label[for="People[1]_Suffix"]').hide();
$("#People_1__Suffix").attr('disabled', true);
$('#People_1__Suffix')[0].selectedIndex = 0;
$('#People_1__Suffix').hide();
}
else {
$('input[name="People_1__LastName"], label[for="People[1]_LastName"]').show();
$("#People_1__LastName").show();
$('#People_1__LastName :input').attr('disabled', false);
}
}
Any help with this would be appreciated folks.
Thank you
William
Here is how I am declaring my checkbox and also part of the function where I am trying to check if it is checked or not...
<%=Html.CheckBoxFor(Function(model) model.FirstNameAsBusiness)%>
<%=Html.LabelFor(Function(model) model.FirstNameAsBusiness)%>
Function Nominate(ByVal m As NominationModel, ByVal captchaValid As Boolean) As ActionResult
If Not m.FirstNameAsBusiness.checked AndAlso String.IsNullOrEmpty(m.lastnametext) Then
ModelState.AddModelError("LastName", "Last Name field is required if you don't yada yada...")
Return View()
End If
Short answer: no. You can't bypass the DataAnnotation with a jQuery call.
Technically, the Last Name field isn't required. So, I'd remove the DataAnnotation for Required, and then on the backend, when the user submits the form, verify that a field value exists when the checkbox isn't checked. If the conditional doesn't pass, and an error to ModelState for that field, and redirect to the page. (apologies for the c#):
public ActionResult Index(HomeIndexModel form)
{
if (!form.Checked && string.IsNullOrEmpty(form.LastName))
{
ModelState.AddModelError("LastName", "Last Name field is required if you don't yada yada...");
return View();
}
//conditional requirement passed...
}
If you want to get a little fancier, you can check out this thread, though all of the suggestions here are also server-side:
ASP.NET MVC Conditional validation
I have a page with link http://localhost:8080/Test/Page.faces?id=asdasdasd
The page got 2 text field and one button, after user key in the details and click submit, it works well when you first time click the submit button, the id will return me the exact value, but if the user never enter the value and click submit the validation will be invoked and next click the button again the id return null? How to solve this problem anyone can help?
Yes, when the user clicks on the button, the browser does a new request to the server. That new request doesn't have the ?id=asdasdasd as part of it. The easiest solution I can think of is to store that value into a hidden text field on the page. You can use some javascript to populate the value.
So, if you have a <h:hidden id="idHidden" value="#{mybean.idHidden}"/> on your JSP, maybe some javascript like this:
<script type='text/javascript'>
function gup( name )
{
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null )
return "";
else
return results[1];
}
if(gup('id') != "") {
document.forms[0].idHidden.value = gup('id');
}
</script>
I haven't checked this code for errors, but the idea is the first time the page loads, the value of 'id' is stored in a hidden input field. That field is bound to your managed bean so the value is persisted across page refreshes. Just reference the id value stored on the bean (as idHidden in the example above) instead of the request parameter.
BTW: I stole the GUP function from http://www.netlobo.com/url_query_string_javascript.html
Nick
I have a top-level page called ReceiveItem. Within that page, I have a couple different FORMs - only one of which will be filled out and submitted (depending upon how that item is received). This all works quite well from the UI perspective. Here is the general page structure:
<ReceiveItem.aspx>
<ReceiveNewInventory.ascx>
<ReceiveOrderReturn.ascx>
<ReceiveFromLoan.ascx>
Except, I do not know how to properly display validation errors. Here is my controller for one of those forms:
public ActionResult ReceiveNewInventory(
int id,
int vendorId,
int quantity,
decimal cost) {
var db = new Data();
var item = db.ItemSet.First(i => i.Id == id);
var vendor = db.BusinessSet.First(i => i.Id == vendorId);
ValidateCost(cost);
ValidateQuantity(quantity);
if (ModelState.IsValid) {
item.AddNewInventory(vendor, quantity, cost);
TempData["Message"] = "Added " + quantity +
" inventory items to " + item.FullDisplayName;
return RedirectToAction("Index");
}
else {
TempData["Quantity"] = quantity;
TempData["VendorId"] = vendorId;
TempData["Cost"] = cost;
return RedirectToAction("ReceiveItem", new { id });
}
}
I would like to display the model errors that the two validation functions add using the simple Html.ValidationSummary function; but, those errors seem to get lost because I do the RedirectToAction. (My ReceiveNewInventory controller action does not have a view directly associated with it.)
With the one condition that I still want 1 page with multiple FORMs, what can I change about this design so that my validation messages show up on the ReceiveItem page?
You need to put the ModelState into TempData and extract it in your ReceiveItem action method. Alternatively, change the Redirect to a return View()
hth
Dan
Look at NerdDinner and see how they do it. Very neat and you can display a summary at the top of the page as well as text next to each item if you wish.
let me know if you have trouble and I'll post code.
Why do you redirect to ReceiveItem even if you have errors? When you display the validation message, don't you want the user to have the opportunity to fix their mistakes? If so, why not keep them on the RecevieNewInventory page again and return the view?