Why unobtrusive MVC validations are not working in IE7 and IE8? - asp.net-mvc-3

I have an application in ASP.NET MVC 3 using Razor. I have setup some data annotations on text boxes along with jQuery validation and unobtrusive validation.
The thing is, some fields have custom validation logic using plain old vanilla JavaScript like the following functions.
function Validation() {
var signUp = SignUpValidation();
var book = BookingValidation();
if (signUp && book) {
return true;
}
else
{
ShowErrorMessage();
return false;
}
}
function ShowErrorMessage()
{
$('span#ErrorMessage').html('These fields are required');
}
where SignUpValidation(), BookingValidation() are functions which
returns either true or false on basis of some other validation
logic.
This is my code for submit button.
#using (Html.BeginForm(MVC.Booking.Actions.AtWork(model: null), FormMethod.Post,
new {#onsubmit = "return Validation()" }))
{
#Html.Partial("_BookingView")
}
This approach is working in all browsers except IE-7/8.

I faced the same issue lately .. and worked out the following solution:
instead of giving your additional form validation (apart from the unobtrusive mvc 3 validation) as a separate/second submit handler in form "onsubmit" event, you should "inject" your additional validation function in the main unobtrusive validation process of mvc3.. let it take care of the rest.
Create a custom validation adaptor somewhere in your common javascript code/file:
(function ($) {
if($.validator && $.validator.unobtrusive) {
$.validator.unobtrusive.adapters.addBool("AdditionalFormValidation");
}
} (jQuery));
In your view file, where you have the form, add this code to create a new jquery validator method for the custom validator adaptor that you defined in your common file above:
(function ($) {
if ($.validator) {
$.validator.addMethod("AdditionalFormValidation", function (value, element) {
return Validation();
});
}
} (jQuery));
Here
- "AdditionalFormValidation" is the validator method name same as your custom validation adaptor.
- "Validation" is the name of your javascript function that takes care of your additional validation and returns a boolean result for validation successs or failure.
In your form, remove the "onsubmit" handler that you had supplied, add a invisible dummy text field to your form and apply the custom unobtrusive validation adaptor/rule that you created, as given below:
#using (Html.BeginForm(MVC.Booking.Actions.AtWork(model: null), FormMethod.Post))
{
#Html.Partial(MVC.Booking.Views._BookForAtWork)
<input type="text" style="visibility:hidden; width: 1px; height: 1px;" name="hiddenValidation" id="hiddenValidation" data-val="true" data-val-AdditionalFormValidation />
}
This solution worked like a charm for me. To me appears a cleaner solution as it injects the additional validation in the same unobtrusive validation flow of mvc3 rather than creating a second validation flow. Also it is inline to future improvement for creating custom data annotation (validations) for all the custom client side validation work.

You may try updating both your jQuery.Validate.min.js and jquery.validate.unobtrusive.min.js files to latest version...it could be that these files are old...I had the same issue some time back and fixed it by doing this update.

Related

Return a warning (not an error) via Ajax remote validation

I have an MVC Ajax callback that checks to see if a user input is valid. This callback is invoked via the [Remote] attribute on the associated model property.
I've changed my design, and I've decided that I would really like to warn the user if the value is incorrect, but I don't want the incorrect value to prevent model validation.
A quick search turns up several threads describing very involved solutions to the general problem of wiring up "unobtrusive warnings" similar to the "unobtrusive validation" magic baked into MVC (for example this SO post). I'm not looking for a general solution, and I don't want to spend a lot of time and energy on this, but I'm wondering if some Ajax guru knows of something I can return from the Ajax server routine that would have the effect of causing the unobtrusive validation client-side code to put up the message without triggering the validation error.
FYI, my existing server-side code looks like this:
public async Task<ActionResult> CouponCodeExists(string couponCode, int? planId)
{
if (some_logic) {
return Json("Coupon code is already taken", JsonRequestBehavior.AllowGet);
} else {
return Json(true, JsonRequestBehavior.AllowGet);
}
}
A RemoteAttribute is a validation attribute and triggering it will add a validation error to jQuery.validate.js and prevent the form from submitting. If you just want a warning message, and still allow the form to submit, you can just make your own ajax call in the inputs .change() event.
Assuming you have #Html.TextBoxFor(m => m.couponCode) in the view, add a placeholder for the message - say <div id="couponwarning">Coupon code is already taken</div> and style in as display: none;. Then add the following scripts
var url = '#Url.Action("CouponCodeExists")';
var warning = $('#couponwarning');
$('#couponCode').change(function() {
var code = $(this).val();
var id = .... // the value of your planId input?
$.get(url, { couponCode: code, planId: id }, function(response) {
if (response) {
warning.show();
}
});
});
$('#couponCode').keyup(function() {
warning.hide();
});
and the method can just return true to display the message, or null
if (some_logic) {
return Json(true, JsonRequestBehavior.AllowGet);
} else {
return Json(null, JsonRequestBehavior.AllowGet);
}

Recaptcha is ignored by ajax action

I'm using Primefaces, however I can't use their p:captcha component, because it can't be rendered/updated by Ajax.
So, I'm trying to use reCaptcha's Ajax Api to create it on the form dynamically, by using Recaptcha.create. Here's the code:
Recaptcha.create(/*public_code*/,
'captchadiv', {
tabindex : 1,
theme : "red",
callback : Recaptcha.focus_response_field
});
Captcha has been created, but it doesn't validate actions from ajax buttons, like p:commandButton. What am I doing wrong?
I'm using Primefaces, however I can't use their p:captcha component, because it can't be rendered/updated by Ajax.
False. The p:captcha element has an id attribute so it can be updated using AJAX. It also has a rendered attribute which can be set to true or false, yes even at runtime.
Captcha has been created, but it doesn't validate actions from ajax buttons, like p:commandButton. What am I doing wrong?
I'm guessing the captcha element you're rendering has no integration with JSF/PrimeFaces. ;-)
Why not use the PrimeFaces captcha element like this:
<div id="captchaWrapper">
<p:captcha rendered="captchaBean.rendered"/>
</div>
<p:commandButton value="render" action="#{captchaBean.render}"
update="captchaWrapper"/>
And have a backing bean like this:
public class CaptchaBean
{
//Getter/setter omitted
private boolean rendered;
public void render()
{
rendered = true;
}
}

Lost: Getting a fully rendered view via Ajax in ASP.NET MVC3 / jQuery

All,
I am very new to MVC3 / jQuery combo and have been reading tutorials. While I kind of get the concept, razor syntax etc. I'm still a bit confused on how to implement a basic concept that I'm trying to.
I have a textarea and when someone enters some text into it and hits enter, I want to trigger a ajax call to the server with the content of the text area, and get back a fully formed HTML blurb that I can put in a div. Now as I understand in MVC3 this would be a view, so in a sense I'm rendering a view on the server and sending it back so I can put it in HTML.
Is this possible? Any examples that I can look up to see how this done? I know how to capture keystrokes, get the value etc., it's this partial rendering of a fully formed HTML via ajax that I'm struggling to understand.
Thanks,
You can do with jQuery. This is how it works. you listen for the keydown event of the text area and when there is a keydown, check what key it is.if it is enter key, then make a jQuery ajax post call to a server page (action method in your controller with the data).Save the data there to your tables and return the markup of what you want and return that. in your script load it to your relevant div.
HTML
//Load jQuery library in your page
<textarea id="txtComment" > </textarea>
<div id="divComment"></div>
Javascript
$(function(){
$("#txtComment").keydown(function (event) {
if (event.keyCode == 10 || event.keyCode == 13) {
var comment=$("#txtComment").val();
comment=encodeURIComponent(comment);
$.post("yourcontroller/actionmethod?data="+comment,function(response){
$("#divComment").html(response);
});
}
});
});
and your controller action method
public ActionResult actionmethod(string data)
{
//Do some sanitization on the data before saving.
// Call your method to save the data to your tables.
CommentViewModel objCommentVM=new CommentViewModel();
objCommentVM.Comment=data;
return View("PartialCommentView",objCommentVM);
}
You should have a ViewMolde class called "CommentViewModel" like this
public class CommentViewModel
{
public string Comment{ set; get; }
}
and you should have a View called PartialCommentView which is strongly typed to CommentViewModel
#model FlashRack.ViewModel.RackViewModel
#{
Layout = null;
}
<div>
#Model.Comment
</div>
If you are simply returning a string, instead of returning a View, you can simply return the string using Return Content("your string here") method as well. But i prefer returning the ViewModel via View because it is more scalable and clean approach to me.
Your action method will return the markup you have in your PartialCommentView with the data.
Keep in mind that you have to take care of the special characters and escaping them properly.

Conditional validation in MVC3

In MVC3, there are a way to add or stop validation in a field depending on the value of a drop-drown list with JQuery? I have been trying with Fluent Validation, but with no luck.
Are you using unobtrusive validation? Is so, look at the html and you will see that there are some html5 attributes on your input, something like this:
<input name="product" id="product" data-val="true" data-val-required="Product is required" />
I suppose you could use jQuery to remove the data-val attribute and then the jQuery Validator will skip this item.
$("#product").data("val", false);
Well, that's my guess, try it yourself.
you should use jQuery AddClass Rules
Create jQuery Class
$.validator.addClassRules({
Req: {
required: true
}
});
Validate the Filed by checking the selected value
$("#Selector").blur(function () {
var Val= $("#Selector").val();
if (Val == "Compare to the String") {
$("#Selector").addClass("Req");
}
else {
$("#Selector").removeClass("Req");
}
});

jQuery unobtrusive validation to validate part of a form

We have a ASP.NET MVC 3 application that uses unobtrusive jQuery validation. The page allows to add children objects to the model in the same go. The <form> contains a grid for the children, and some input fields for adding new children.
Simplified example with Issue as the Model and Subtasks as the children:
Issue.cshtml -> Defines the form and includes fields for the issue as well as its subtasks.
#model Issue
#using (Html.BeginForm("Create", "Issues", FormMethod.Post, new { id = "mainForm" })
{
#Html.TextBoxFor(model => model.Summary)
#Html.Partial("SubtaskFields", new Subtask())
#Html.Partial("SubtasksGrid", model.Subtasks)
}
SubtaskFields.cshtml:
#model Subtask
#Html.TextBoxFor(model => model.Summary)
<button id="add">Add</button>
SubtasksGrid.cshtml:
#model IEnumerable<Subtask>
<table>
#foreach (var subtask in Model)
{
<tr>
<td>
#subtask.Name
<input type="hidden" name="Subtasks[#subtask.Index].Name" value="#subtask.Name"/>
</td>
</tr>
}
</table>
The point is, when submitting the form, only the properties of the issue (Issue.Name, e.g.), plus the hidden fields for the children (Subtask.Name, e.g.) should be validated and submitted.
We have some javascript code that hooks on the "add" button, and adds a new subtask based on the values in the SubtaskFields.cshtml partial view. That script validates the input fields first. In order for this to work, we use the TextBoxFor etc. html helpers for the SubtaskFields.cshtml, too, rendering a dummy/default Subtask object (new Subtask()). Our javascript the uses $("#mainForm").validate().element(...) to validate the SubtaskFields before adding a new subtask.
The big problem with this approach is that the jQuery unobtrusive validation framework automatically hooks on the submit button and validates all fields within the form before submitting the form. I.e., even the subtask fields are validated. This does not make any sense. Say that the subtask name is mandatory (which means the user can only click on "add" if he has filled in a subtask name). But if the user does not click on "add", the values in the Subtask Fields don't have any meaning and can in particular be left blank. In this case, in our current setting, jQuery validation fails because a mandatory field was left blank.
How can this be solved?
This is what we've come up with:
Add an attribute to all subtask fields (which should not be validated when submitting the form), e.g. "data-val-ignore".
Set the ignore setting on the form's validator to "[data-val-ignore]"
For the add button, in order to validate the subtask fields (which are normally ignored), iterate over them, and for each field, remove the attribute, re-parse to genereate the rules, execute validation, add the attribute, parse one more time.
Ad 2:
$(document).ready(function () {
$.data($('form')[0], 'validator').settings.ignore = "[data-val-ignore]";
});
Ad 3:
$(allSubtaskFields).each(function() {
$(this).removeAttr("data-val-ignore");
$.validator.unobtrusive.parseElement(this, false);
if (!$("mainForm").validate().element($(this))) { result = false; }
$(this).attr("data-val-ignore", "true");
$.validator.unobtrusive.parseElement(this, false);
});
I would suggest moving #Html.Partial("SubtasksGrid", model.Subtasks) outside of your form, and either having it in a single separate form, or have the partial generate a form for each grid row.
This will address your validation problems with your main form, and should also permit you to simplify validation of each row in SubTasksGrid.
To validate part of the form, wrap the section or the controls you want to validate into a div with an #id or .class and do the following:
var validator = $("#myForm").validate();
var isValid = true;
$("myDivToBeValidated").find("*[data-val]").each(function (indx, elem) {
if (!validator.element(elem)) {
isValid = false;
}
});
//this part of form is valid however there might be some other invalid parts
if (isValid)
//do your action, like go to next step in a wizard or any other action
goToNextStep();
I hope it is clear, if not please leave a comment. For more info about jQuery validation plugin and element() function, check this
Looks like you are working against the MVC egine here.
I would use Editor templates and Display templates, EditorFor template for the stuff you wanna validate and post, and Display template for the stuff you dont wanna post and validate.. If you have a TextBoxFor in the display template make sure its binding property has no Required attribute, and if its a value type make it nullable.

Resources