ASP.net MVC Validation Hook - asp.net-mvc

I have the following view in ASP.net MVC 3:
#model Models.CreateProjectViewModel
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.validate.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>
#using( Html.BeginForm() ) {
#Html.TextBoxFor(m => m.ProjectName)
#Html.ValidationMessageFor(m => m.ProjectName)
<p>
<input type="submit" value="Save" />
</p>
}
I am using unobtrusive javascript with jQuery and the Fluent Validation framework.
When I click the Save button and validation fails, is there some event I can hook into to call some custom javascript?
function validationFailed() {
// do something here only if validation failed
}
How would I tie into the validation so that when it failed (and only if it failed) I could call my validationFailed() function.

As jQuery/Validation docs says, you could use invalidHandler to react when an invalid form is submitted.
But since MVC unobtrusive validation instantiates the Validation itself, you have to hook this event later.
Using exactly the same mechanism as the jQuery/Validation does: you could bind your code to the form elements custom event 'invalid-form.validate', witch corresponds to the invalidHandler!
$(document).ready(function() {
$('#myform').bind('invalid-form.validate',function(){
alert('invalid form!');
});
});
to give your form an id use:
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "myform" })) {
}
Update:
An alternative way to get the existing validation object is calling validate() on the form. If a validator for this form was already created, it will be returned:
Edit: after initialization occured, changing .settings.invalidHandler is too late for binding. So the following snippet will not work [anymore] unless you re-init the validator.
$(document).ready(function() {
var existingValdiation = $("#myform").validate();
//the settings property corresponds to the options parameter
existingValdiation.settings.invalidHandler = function (form) {
alert('invalid form!');
};
// not recommended:
// re-init would bind settings.invalidHandler to 'invalid-form.validate'
// existingValdiation.init();
});

You can use the invalidHandler, I believe that is in jquery validation.
invalidHandler Callback
Callback for custom code when an invalid form is submitted. Called
with a event object as the first argument, and the validator as the
second.

Related

MVC - unable to pass value back to controller using hidden field

I'm trying to assign value to the hidden field in java script using the
JavaScript variable and trying to pass it back to the controller. The value every time I go in the post method for my model property DBErrorID is 0.
Razor View:
<body>
#Html.HiddenFor(model => model.DBErrorID, new { id = "DBErrorId" })
<input type="submit" value="Update" class="btn btn-success" onclick="GetValue()" />
</body>
JavaScript:
<script language="javascript" type="text/javascript">
function GetValue() {
$("#DBErrorId").val(totalValues);
// alert(totalValues);
}
<script>
Controller:
[HttpPost]
public ActionResult ErrorStatusView(Models.ErrorStatusModel obj)
{
Models.ErrorStatusModel objreg = new Models.ErrorStatusModel();
objreg.DBErrorID = obj.DBErrorID;
}
Your current server side code is creating an unnecessary new object of ErrorStatusModel as the first line, which will create a new object(objreg variable) with default values(unless you are setting it in a constructor), for an int type property it will be 0. If you are inspecting the values of objreg, that is the reason you see 0 as the property value.
You do not need to create this additional object. The model binder framework will create one for you and map the posted values, when you use ErrorStatusModel your method parameter type. That means your obj property is properly populated by the form data (assuming the DBErrorID property is settable)
[HttpPost]
public ActionResult ErrorStatusView(Models.ErrorStatusModel obj)
{
// obj is populated with form values.
// use obj
// return something.
}
Also, your client side code is trying to set the value of hidden input inside the GetValue method which is called on the onclick event of the submit button. If you are using a normal form submit and your button is inside a form tag, when user clicks on the submit button it will immediately submit the form (with the current value of that input)
If that is the case, you should prevent the default behavior (submitting the form) when the button is clicked, set the value as needded and fire the form submit via JavaScript.
There are multiple ways to do it. Here is one approach- the unobtrusive JavaScript approach- which assumes you have jQuery loaded to your page. Give an Id to the button, which we can use to wireup the click event.
<input type="button" value="Update" class="btn btn-success"
id="btn-save" />
Now in JavaScript, listen to the click event on this button, prevent the normal behavior(submitting the form), update the hidden input value and trigger the form submit.
$(function () {
$('#btn-save').click(function (e) {
e.preventDefault();
$("#DBErrorId").val(34);
$(this).closest("form").submit();
});
})
Also you should not create a new object in server

Posting form to different MVC post action depending on the clicked submit button

I am using ASP.Net MVC 4. I have multiple buttons on a view.. At present I am calling the same action method; and I am distinguishing the clicked button using a name attribute.
#using (Html.BeginForm("Submit", "SearchDisplay", new { id = Model == null ? Guid.NewGuid().ToString() : Model.SavedSearch }, FormMethod.Post))
{
<div class="leftSideDiv">
<input type="submit" id="btnExport" class="exporttoexcelButton"
name="Command" value="Export to Excel" />
</div>
<div class="pageWrapperForSearchSubmit">
<input type="submit" class="submitButton"
value="Submit" id="btnSubmitChange" />
</div>
}
//ACTION
[HttpPost]
public ActionResult Submit(SearchCostPage searchModel, string Command)
{
SessionHelper.ProjectCase = searchModel.ProjectCaseNumber;
if (string.Equals(Command, Constants.SearchPage.ExportToExcel))
{
}
}
QUESTIONS
Is there a way to direct to different POST action methods on different button clicks (without custom routing)?
If there is no way without custom routing, how can we do it with custom routing?
References:
Jimmy Bogard - Cleaning up POSTs in ASP.NET MVC
You can choose the url where the form must be posted (and thus, the invoked action) in different ways, depending on the browser support:
for newer browsers that support HTML5, you can use formaction attribute of a submit button
for older browsers that don't support this, you need to use some JavaScript that changes the form's action attribute, when the button is clicked, and before submitting
In this way you don't need to do anything special on the server side.
Of course, you can use Url extensions methods in your Razor to specify the form action.
For browsers supporting HMTL5: simply define your submit buttons like this:
<input type='submit' value='...' formaction='#Url.Action(...)' />
For older browsers I recommend using an unobtrusive script like this (include it in your "master layout"):
$(document).on('click', '[type="submit"][data-form-action]', function (event) {
var $this = $(this);
var formAction = $this.attr('data-form-action');
$this.closest('form').attr('action', formAction);
});
NOTE: This script will handle the click for any element in the page that has type=submit and data-form-action attributes. When this happens, it takes the value of data-form-action attribute and set the containing form's action to the value of this attribute. As it's a delegated event, it will work even for HTML loaded using AJAX, without taking extra steps.
Then you simply have to add a data-form-action attribute with the desired action URL to your button, like this:
<input type='submit' data-form-action='#Url.Action(...)' value='...'/>
Note that clicking the button changes the form's action, and, right after that, the browser posts the form to the desired action.
As you can see, this requires no custom routing, you can use the standard Url extension methods, and you have nothing special to do in modern browsers.
BEST ANSWER 1:
ActionNameSelectorAttribute mentioned in
How do you handle multiple submit buttons in ASP.NET MVC Framework?
ASP.Net MVC 4 Form with 2 submit buttons/actions
http://weblogs.asp.net/scottgu/archive/2007/12/09/asp-net-mvc-framework-part-4-handling-form-edit-and-post-scenarios.aspx
ANSWER 2
Reference: dotnet-tricks - Handling multiple submit buttons on the same form - MVC Razor
Second Approach
Adding a new Form for handling Cancel button click. Now, on Cancel button click we will post the second form and will redirect to the home page.
Third Approach: Client Script
<button name="ClientCancel" type="button"
onclick=" document.location.href = $('#cancelUrl').attr('href');">Cancel (Client Side)
</button>
<a id="cancelUrl" href="#Html.AttributeEncode(Url.Action("Index", "Home"))"
style="display:none;"></a>
This sounds to me like what you have is one command with 2 outputs, I would opt for making the change in both client and server for this.
At the client, use JS to build up the URL you want to post to (use JQuery for simplicity) i.e.
<script type="text/javascript">
$(function() {
// this code detects a button click and sets an `option` attribute
// in the form to be the `name` attribute of whichever button was clicked
$('form input[type=submit]').click(function() {
var $form = $('form');
form.removeAttr('option');
form.attr('option', $(this).attr('name'));
});
// this code updates the URL before the form is submitted
$("form").submit(function(e) {
var option = $(this).attr("option");
if (option) {
e.preventDefault();
var currentUrl = $(this).attr("action");
$(this).attr('action', currentUrl + "/" + option).submit();
}
});
});
</script>
...
<input type="submit" ... />
<input type="submit" name="excel" ... />
Now at the server side we can add a new route to handle the excel request
routes.MapRoute(
name: "ExcelExport",
url: "SearchDisplay/Submit/excel",
defaults: new
{
controller = "SearchDisplay",
action = "SubmitExcel",
});
You can setup 2 distinct actions
public ActionResult SubmitExcel(SearchCostPage model)
{
...
}
public ActionResult Submit(SearchCostPage model)
{
...
}
Or you can use the ActionName attribute as an alias
public ActionResult Submit(SearchCostPage model)
{
...
}
[ActionName("SubmitExcel")]
public ActionResult Submit(SearchCostPage model)
{
...
}
you can use ajax calls to call different methods without a postback
$.ajax({
type: "POST",
url: "#(Url.Action("Action", "Controller"))",
data: {id: 'id', id1: 'id1' },
contentType: "application/json; charset=utf-8",
cache: false,
async: true,
success: function (result) {
//do something
}
});

How do I use a Button(Non Submit) Click Event to call a method on my Controller?

I feel ridiculous asking this question but here goes, I am trying to make a very simple ASP.NET MVC 5 app. My first of it's kind. I want to have a button that when clicked does something but doesn't change the user's view or at most returns a "Email has been submitted" message.
My problem is I can't figure out how to wire a button to an "event" or "action" that doesn't change the view(i.e. using #Html.ActionLink()) or is a Submit button. Every example I find is also of a Submit button.
Thanks for any help.
EDIT
This is still not working for me. I'll post my code below. My effort is based on what was said here and on the linked post. Also, FYI, I can make it work with `#Html.ActionLink("link text", "actionname") but that appears as a link and I am trying to use a "Button".
Index.cshtml
#{
ViewBag.Title = "Home Page";
}
<div class="hero-unit">
<h3>Marketing & Communications Project Request Form</h3>
<p>User: <strong>#Context.User.Identity.Name</strong></p>
</div>
<div class="row">
<div class="span4">
#Html.ActionLink("Send Email", "SendEmail") #*this line works*#
<input id="SendEmail" class="btn" type="button" value="SendEmail" /> #*this line does not
</div>
</div>
<script type="text\javascript">
$(function(){
var url = '#Url.Action("SendEmail", "HomeController")';
$("input#SendEmail").on('click', function() {
$.ajax({
url: url
})
});
});
</script>
HomeController
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
public ActionResult SendEmail()
{
//Code to create and send email here
return View("Index");
}
}
OK, say you have the following button, written in HTML:
<input type="button" id="MyButton" value="Click Me />
You can use jQuery to hook up to the click event:
$(function(){
$("input#MyButton").on('click', function(){
// Do what you want.
});
});
If you use a HTML helper, such as HTML.TextBoxFor(), as long as you know the id of the input that is generated, you can use the same jQuery code to hook up the click event.
EDIT:
You can place that jQuery code either in the view e.g.
<script type="text/javascript">
$(function(){
$("input#MyButton").on('click', function(){
// Do what you want.
});
});
</script>
Usually you find script code placed near the bottom of the view, but you can place it anywhere you like really.
Or you could place that jQuery in a separate JavaScript (*.js) file. Just make sure you add the following to the <head> section in _Layout.cshtml:
<script type='text/javascript' src='#Url.Content("~Scripts/YourFile.js")' ></script>
_Layout.cshtml is a master layout file that is used across your project (assuming you have picked one of the usual ASP.NET MVC project templates in Visual Studio).
EDIT:
Regards the jQuery reference, in _Layout.cshtml you can add this, if jQuery is not already referenced:
<script type='text/javascript' src='#Url.Content("~Scripts/jquery.version.js")' ></script>
Just replace the filename for the correct one you have. Now, things get interesting if your MVC app uses bundling. That's a bit out of my knowledge bank, so might be better to look at other SO questions that talk about CSS/JavaScript bundling in MVC apps.
You could simply achieve with this below sample code using jQuery ajax(post) call
<a id="btn-send-mail">SendEmail</a>
JS
$(document).ready(function(){
$('#btn-send-mail').click(function(e){
e.preventDefault();
var emailData={};
emailData.toMail='sample#testmail.com';
$.post('/Mail/Send/',{data:emailData}, function(result){
if(result.status==true){
alert('Email submitted successfully');
}});//end of post
});//end of click
});//end of ready
Controller code
public class MailController
{
[HttpPost]
public JsonResult Send(Email obj)
{
//Code for sending email
return Json(new {status=true});
}
}
If you don't want to use normal jquery call you can take advantage of Razor #Ajax.ActionLink.
You just set up the link like a normal Html.ActionLink and then create a controller action that sends your email, since this call is asynchronous it wont refresh the page.
#Ajax.ActionLink("Send Email", // <-- Text to display
"SendEmail", // <-- Action Method Name
new AjaxOptions
{
UpdateTargetId="", // <-- Used if you want to update up, DOM element ID to update
HttpMethod = "GET" // <-- HTTP method
})
I would recomend doing the jquery way but here is an example using Ajax.ActionLink

Display MVC3 Unobtrusive ValidationSummary errors in a jQuery UI Dialog

I'm looking to display MVC3's unobtrusive ValidationSummary errors in a jQuery UI Dialog. Specifically, I want to be able to have a "live" $('.validation-summary-errors').dialog(...);-like experience. That is to say, whenever MVC3 client-side validation would show (for the first time) or update (on repeat offenses) the .validation-summary-errors element, I want the results to appear in a jQuery UI Dialog.
I currently have something along the lines of
#Using Html.BeginForm("Action", "Controller", FormMethod.Post, New With {.id = "MyForm"})
#Html.ValidationSummary()
...
$('#MyForm').submit(function () {
if (!$(this).valid()) {
$('.validation-summary-errors').dialog(...);
return false;
}
});
but this doesn't feel right to me.
It feels like I should be able to hook into the validation framework and be notified that validation completed, and there was an error summary that is now shown or updated with the errors. Then using that event, dialog() the now-shown/updated .validation-summary-errors element. Is there such a thing? Or are there any other suggestions?
So this is how I ended up doing it. I didn't find much documentation, but did enough JS digging to get to this point. Not sure how I feel about it. I do know that I no longer need to hook the form's submit event and "double-up" on the validation calls, so that's good. It just seems that this solution feels "cryptic" (at least in my inexperienced eyes), and I would have expected (and am still looking for) a solution that feels more baked-in.
$(function () {
// If there is an error element already (server side error), show it.
showValidationSummaryDialog();
// When the form validates, and there is an error element, show it
$('#MyForm').bind('invalid-form.validate', function (error, element) {
showValidationSummaryDialog();
}
}
function showValidationSummaryDialog() {
$('.validation-summary-errors').dialog({
title: 'Unable to Save',
close: function () {
$(this).dialog('destroy')
.prependTo($('#MyForm')); // jQuery moves the source element out of the DOM.
// We need to put it back in its place afterwards for validation to maintain its contents.
// TODO: Is there a better way?
}
});
}
If some one want to display both ValidationSummary & ValidationSummaryDialog then try this.
as per #ckittel.
#using (Html.BeginForm())
{
#Html.ValidationSummary()
<div id="ValidationSummary" style="display:none" class="validation-summary-errors">
</div>
}
<script type="text/javascript">
function showValidationSummaryDialog() {
$('#ValidationSummary').html($('.validation-summary-errors').html());
$('#ValidationSummary').dialog({
title: 'Error',
modal: true
});
}
$(document).ready(function () {
$('form').bind('invalid-form.validate', function (error, element) {
showValidationSummaryDialog();
});
});
</script>

ASP.NET Mvc 2 How do you launch client side validation from inside javascript?

Is there a function for ASP.NET MVC 2 built in data annotation javascript validation that performs the functionality of Jquery.Validate's isValid()?
I'd like to check if my fields are valid prior to using jquery ajax to send data to the server? Any suggestions?
Thank You.
i used the :
http://geekswithblogs.net/stun/archive/2010/02/27/asp.net-mvc-client-side-validation-summary-with-jquery-validation-plugin.aspx
and it worked great for me,
especially you don't need to change the original Mvc Validation way(I mean the validation field), you just make it client side
As basilmir and Dom Ribaut implies you should get this automatically if you EnableClientValidation(). However if you want to manually call client side MVC validation you can use:
if (!Sys.Mvc.FormContext.getValidationForForm($("#myform").get(0)).validate('submit').length) {
// is valid
}
You can replace $("#myform").get(0) with the DOM element for your form.
Seems that there is nothing special in MicrosoftMvcJQueryValidation.js except for registration of rules for jquery.validate.js plugin.
This worked for me:
<script type="text/javascript">
function validateForm(formId)
{
var valid = $("#" + formId).validate().form();
return valid;
}
</script>
Scott Guh describe simple js validation step by step in this post: http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx (look for step3).
It is not JQuery but wouldn't that fit your needs?
--
Dom
Have a look at xval. It lets you define your validation rules either using data annotation attributes or castle validation attributes (I think nhibernate validation has also been added recently). Validation is then converted to client validation rules and you can validate a form using ajax so no postback to the server.
From the project page: xVal is a validation framework for ASP.NET MVC applications. It makes it easy to link up your choice of server-side validation mechanism with your choice of client-side validation library, neatly fitting both into ASP.NET MVC architecture and conventions.
If you are only after validation mechanisms for asp.net mvc then have a look at this and this
Jquery will be your best friend
check this http://bassistance.de/jquery-plugins/jquery-plugin-validation/
document link:http://docs.jquery.com/Plugins/Validation
You can enable client-side validation via <% Html.EnableClientValidation(); %>
It will automatically generate all the javascript code you need to the server-side validation to work on the client-side. Remember to still check on the server-side, since the client can bypass javascript and send bad data. Do not use client-side validation only.
<% Html.EnableClientValidation(); %>
<%= Html.ValidationSummary() %>
<% using (Html.BeginForm()) {%>
<%=Html.EditorForModel() %>
<p>
<input type="submit" value="Save" />
</p>
<% } %>
here is a simple program will guide how to do client side validation of Form in JavaScript.
Name : <asp:TextBox ID="txtName" />
Email : <asp:TextBox ID="txtEmail" />
Web URL : <asp:TextBox ID="txtWebUrl" />
Zip : <asp:TextBox ID="txtZip" />
<asp:Button ID="btnSubmit" OnClientClick=" return validate()" runat="server" Text="Submit" />
Now on the source code of this form in script tag write the following code:
<script language="javascript" type="text/javascript">
function validate()
{
if (document.getElementById("<%=txtName.ClientID%>").value=="")
{
alert("Name Feild can not be blank");
document.getElementById("<%=txtName.ClientID%>").focus();
return false;
}
if(document.getElementById("<%=txtEmail.ClientID %>").value=="")
{
alert("Email id can not be blank");
document.getElementById("<%=txtEmail.ClientID %>").focus();
return false;
}
var emailPat = /^(\".*\"|[A-Za-z]\w*)#(\[\d{1,3}(\.\d{1,3}){3}]|[A-Za-z]\w*(\.[A-Za-z]\w*)+)$/;
var emailid=document.getElementById("<%=txtEmail.ClientID %>").value;
var matchArray = emailid.match(emailPat);
if (matchArray == null)
{
alert("Your email address seems incorrect. Please try again.");
document.getElementById("<%=txtEmail.ClientID %>").focus();
return false;
}
if(document.getElementById("<%=txtWebURL.ClientID %>").value=="")
{
alert("Web URL can not be blank");
document.getElementById("<%=txtWebURL.ClientID %>").value="http://"
document.getElementById("<%=txtWebURL.ClientID %>").focus();
return false;
}
var Url="^[A-Za-z]+://[A-Za-z0-9-_]+\\.[A-Za-z0-9-_%&\?\/.=]+$"
var tempURL=document.getElementById("<%=txtWebURL.ClientID%>").value;
var matchURL=tempURL.match(Url);
if(matchURL==null)
{
alert("Web URL does not look valid");
document.getElementById("<%=txtWebURL.ClientID %>").focus();
return false;
}
if (document.getElementById("<%=txtZIP.ClientID%>").value=="")
{
alert("Zip Code is not valid");
document.getElementById("<%=txtZIP.ClientID%>").focus();
return false;
}
var digits="0123456789";
var temp;
for (var i=0;i<document.getElementById("<%=txtZIP.ClientID %>").value.length;i++)
{
temp=document.getElementById("<%=txtZIP.ClientID%>").value.substring(i,i+1);
if (digits.indexOf(temp)==-1)
{
alert("Please enter correct zip code");
document.getElementById("<%=txtZIP.ClientID%>").focus();
return false;
}
}
return true;
}
</script>
And in code behind file just write the below code.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
btnSubmit.Attributes.Add("onclick", "return validate()")
End Sub
Now you will get a form with proper validation.
I hope this is going to help you

Resources