MVC3 Remote Validation not Fired? - asp.net-mvc-3

I created a very simple test project to illustrate the problem.
My model class
public class HomeModel
{
[Required(ErrorMessage="Missing property1.")]
public string Property1
{
get;
set;
}
[Remote("ValidateProperty2", "Home", HttpMethod="Get", AdditionalFields = "Property3", ErrorMessage="Property2 wrong!")]
public string Property2
{
get;
set;
}
public string Property3
{
get;
set;
}
}
My controller
public class HomeController : Controller
{
public ActionResult Index()
{
HomeModel model = new HomeModel();
return View(model);
}
[HttpPost]
public ActionResult Index(HomeModel model)
{
return View(model);
}
public ActionResult ValidateProperty2(string property2, string property3)
{
return Json(true, JsonRequestBehavior.AllowGet);
}
}
And my view
#model RemoteValidationTest.Models.HomeModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
</head>
<body>
#using (Ajax.BeginForm(new AjaxOptions
{
HttpMethod = "POST"
}))
{
#Html.TextBoxFor(x => x.Property1) #Html.ValidationMessageFor(x => x.Property1)<br />
#Html.TextBoxFor(x => x.Property2) #Html.ValidationMessageFor(x => x.Property2)<br />
#Html.TextBoxFor(x => x.Property3) #Html.ValidationMessageFor(x => x.Property3)<br />
<input type="submit" />
}
</body>
</html>
And my web.config
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
Nothing really fancy here. I havea model class with 3 properties. The first one is set be required and second one is remote validation, I believed I have create the action method properly. I set break piont to ValidateProperty2 function, it never gets called.
I also used FireBug, the same thing client side does not even try to call the server side.
What is wrong with the code here?
Edit 1:
I think I get something, the remote validation will only fires when the control (e.g text box) has value in side. The empty control will never trigger the validation. In my case I actually try to implmenet a more complicated logic, I need the validation to fire even when the control text is empty (to check other property's value). Is it even possible?

I have a working version here for mvc3:
http://completedevelopment.blogspot.com/2011/08/remote-ajax-validation-in-mvc3.html
d/l it and you can compare files.

The problem is that the validation don't fire automatically when you press the send button for the first time. Here is how you initiate the validation upon page load so that it fires every time it is needed on submit:
"Required" validation attribute not working in asp.net mvc 3 while others work

Related

How to Implement MVC3 Model URL Validation?

I've successfully implemented client side validation to require input in my textbox. However, I want to evaluate the contents of the textbox to see if it is a well formed URL. Here's what I have thus far:
Index.cshtml:
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery-1.5.1.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.validate.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")"></script>
#model Ticket911.Models.ValidationModel
#{
ViewBag.Title = "Home Page";
}
<h2>#ViewBag.Message</h2>
#using (Ajax.BeginForm("Form", new AjaxOptions() { UpdateTargetId = "FormContainer" , OnSuccess = "$.validator.unobtrusive.parse('form');" }))
{
<p>
Error Message: #Html.ValidationMessageFor(m => m.URL)
</p>
<p>
#Html.LabelFor(m =>m.URL):
#Html.EditorFor(m => m.URL)
</p>
<input type="submit" value="Submit" />
ValidationModel:
public class ValidURLAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
return (value != null);
}
}
public class ValidationModel
{
[Required]
public string URL {get; set;}
}
How do I ensure that the model URL validation occurs? When the Submit button is clicked, what must be done to navigate to the URL entered into the textbox?
Thanks much:)
good way is to implement your attribute for next use in mvc projects. like this:
public class UrlAttribute : RegularExpressionAttribute
{
public UrlAttribute() : base(#"^http(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&%\$#_]*)?$")
{}
}
so on the model:
[Url(ErrorMessage = "URL format is wrong!")]
public string BlogAddress { get; set; }
You can do it wtih DataAnnotations
public class ValidationModel
{
[Required]
[RegularExpression(#"^http(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&%\$#_]*)?$", ErrorMessage = "URL format is wrong")]
public string URL {get; set;}
}
And in your HTTPPost Action method, You can call the ModelState.IsValid property which will check the Validations for you.
[HttpPost]
public ActionResult Save(ValidationModel model)
{
if(ModelState.IsValid)
{
//Save or whatever
}
return View(model);
}

Rectify the input at client side using RemoteValidation

Is there any possibility of rectifying the input at client side using Remote Validation?
For example, the user will enter the date as 010101 which means 01-Jan-2001, can Remote Validation reflect/pass the rectified value (010101 into 01-Jan-2001) at/to client side?
I have a scenario where i have JS to format the input into correct date format. Later on i had to use RemoteValidation. My remote validation receives date in ddmmyy format (RemoteValidation gets called before JS), it first converts it into correct date and then perform validation, and then my JS does not get called at all and so 010101 is not get converted into 01-Jan-2001.
Edit
There are two things i would like to get help for
1- Is there anyway a remote validation function can modify the model/data passed to it for validation and then pass it back to the view so that user can see the modified version of the model/data
[Deleted:2- I have JavaScript for a date field which formats the date when focus is lost. It is working fine. When i used Remote validation along with JS, the script does not get called at all.]
Edit
Model
public class master
{
public string sometext { get; set; }
public child mychild { get; set; }
}
public class child
{
public child()
{
thedate = DateTime.MaxValue;
}
[Remote("ValidateDate", "Test", ErrorMessage = "Invalid Date")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:mm/dd/yyyy}", NullDisplayText = "Enter Date")]
public DateTime? thedate { get; set; }
}
View
#model Models.master
#using Web.Framework
#{
Layout = null;
}
<html>
<head>
<title>Test - My ASP.NET MVC Application</title>
<script src="#Url.Scripts("jquery-1.7.1.min.js")" type="text/javascript"></script>
<script src="#Url.Scripts("jquery-ui-1.8.11.js")" type="text/javascript"></script>
<script src="#Url.Scripts("modernizr-2.0.6-development-only.js")" type="text/javascript"></script>
<script src="#Url.Scripts("AjaxLogin.js")" type="text/javascript"></script>
<script src="#Url.Scripts("jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Scripts("jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="#Url.Scripts("jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script src="#Url.Scripts("MicrosoftAjax.js")" type="text/javascript"></script>
<script src="#Url.Scripts("MicrosoftMvcAjax.js")" type="text/javascript"></script>
<script src="#Url.Scripts("myScripts.js")" type="text/javascript"></script>
</head>
<body>
#using (Html.BeginForm("testSubmit", "Test"))
{
#Html.LabelFor(m => m.sometext)
<br />
#Html.TextBoxFor(m => m.sometext)
<br />
#Html.LabelFor(m => m.mychild.thedate)
<br />
#Html.TextBoxFor(m => m.mychild.thedate, new { onblur = "doDate(this, '');" })
#Html.ValidationMessageFor(m => m.mychild.thedate)
<br />
<input type="submit" value = "Submit me" />
}
</body></html>
Controller
public ActionResult testSubmit(master model)
{
#ViewBag.Message = "OK";
return View("response");
}
public JsonResult ValidateDate(DateTime? thedate)
{
return Json(HttpContext.Request.QueryString["mychild.thedate"].ToString(), JsonRequestBehavior.AllowGet);
}
My remote validator always receives null in thedate, but i can access the value from query string but the value is unformatted i.e. Remote validation gets called before JS which means i have to format the date first in remote function and then validate, once validated then this input is formatted again by JS and both have to be synced.
Now, how can i get the formatted value in Remote function OR pass the formatted value from Remote function to the View ?
Since i didn't get any answer so the answer, so far, is "No".

asp.net mvc add and hide error for input via ModelState

Is it possible to add an error for input via ModelState.AddModelError(inputId) to have error highlight on UI and to have it to have to behave as like client validation, i.e. when user changes smth in the input error class would be removed.
Model:
public class MyViewModel
{
[Required]
public string Foo { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
ModelState.AddModelError("foo", "Foo is required");
return View(new MyViewModel());
}
}
View:
#model MyViewModel
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
#using (Html.BeginForm())
{
#Html.EditorFor(x => x.Foo)
#Html.ValidationMessageFor(x => x.Foo)
<button type="submit">OK</button>
}
Now when the page is rendered, the Foo field will be highlighted red with an error and when the user types something into the field and blurs out, the error will be removed.

Ajaxified link in MVC3/JQuery not working in IE8 (missing header)

Consider the following code (it is based on a default EMPTY MVC3 project created in visual web developer express 2010sp1):
_Layout.cshtml:
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
</head>
<body>
<div id="header">header</div>
<div id="main">#RenderBody()</div>
</body>
</html>
Index method of HomeController:
public ActionResult Index()
{
if (Request.IsAjaxRequest())
{
ViewBag.Message = "partial";
return PartialView();
}
else
{
ViewBag.Message = "full";
return View();
}
}
Index.cshtml:
<script type="text/javascript">
$(function () {
$('#myLink').click(function () {
$.post(this.href, function (result) {
$('#main').html(result);
alert(result);
});
return false;
//$('#main').load(this.href);
//return false;
});
});
</script>
HomeController index. #ViewBag.Message
#Html.ActionLink("Index", "Index", new { controller = "Home" }, new { id = "myLink" } );
The problem is that in IE8 when the myLink link is clicked, it doesn't update the main div with only the partial html from Index.cshtml but the complete html including the layout. Ofcourse it works fine in FF, I mean why shouldn't it right? It seems Request.IsAjaxRequest() always evaluates to false in IE8. I understand that it is a result of a header X-Requested-With not being attached to a request in IE8. I don't have a lot of experience with web development -- is this a common issue and what is the (best) way to solve this?
UPDATE:
Yesterday I got it working normally in IE8, but when I tried it again this morning, the same problem was back. Now I don't think it has anything to do with the settings in IE8 anymore as I restored the settings to the default values. I tried examining the request with the fiddler tool. In order for me to be able to capture the traffic from localhost with fiddler, I added a period to the address: http://localhost.:3157/. So now the error occurs only when I use http://localhost.:3157/ (with period) and it works normally when I use http://localhost:3157/ (without period). I additionally tested the behavior in Chrome, Opera and Safari -- the ajax link works normally in these browsers. Note that I can get it working normally in IE8 when I attach a query parameter to the ajax link like so:
#Html.ActionLink("Index", "Index", new { controller = "Home", param = "param" }, new { id = "myLink" } )
I don't really want to do this. I'm running low on ideas here. I'm probably missing something that is blatantly obvious to a seasoned web developer =] Anybody recognize these symptoms?
You probably want to use the .live() method instead of .click():
$('#myLink').live('click', function () {
...
return false;
});
because you are replacing the DOM in the AJAX callback (the #main) which contains the link so you are killing the event handler you have assigned.
Also you have a typo in the jquery script inclusion in the <head>. You are missing a closing > after type="text/javascript":
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
So here's a complete working example:
_Layout.cshtml:
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
</head>
<body>
<div id="header">header</div>
<div id="main">#RenderBody()</div>
</body>
</html>
HomeController:
public class HomeController : Controller
{
public ActionResult Index()
{
if (Request.IsAjaxRequest())
{
ViewBag.Message = "partial";
return PartialView();
}
else
{
ViewBag.Message = "full";
return View();
}
}
}
Index.cshtml:
<script type="text/javascript">
$(function () {
$('#myLink').click(function () {
$.post(this.href, function (result) {
$('#main').html(result);
});
return false;
});
});
</script>
HomeController index. #ViewBag.Message
#Html.ActionLink("Index", "Index", new { controller = "Home" }, new { id = "myLink" } )
add
jQuery.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
}
});
to make sure the correct header is attached.

Have to double submit when using Remote attribute based validation

We have a field on our model which has a [Remote] attribute. When we store that field on a Hidden form element and then try to submit that form we have to click the submit button twice. Also interesting is that the 2nd time we click it no remote validation is occurring (so says Fiddler).
Thoughts?
Unable to repro. If the hidden field is decorated with the Remote attribute you won't be able to submit the form no matter how many times you click on the submit button if the remote function sends false.
For example:
Model:
public class MyViewModel
{
[HiddenInput(DisplayValue = false)]
[Remote("Check", "Home")]
public string Id { get; set; }
[Required]
public string Name { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel
{
Id = "1"
});
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return View(model);
}
public ActionResult Check(string Id)
{
return Json(Id == "2", JsonRequestBehavior.AllowGet);
}
}
View:
#model AppName.Models.MyViewModel
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
#using (Html.BeginForm())
{
#Html.EditorForModel()
<input type="submit" value="OK" />
}
Because the remote function will always return false this form cannot be submitted. If the remote function returns true a single click would be enough to submit it assuming of course that the other validation passed.

Resources