Cancel button does not get called when ModelState is not valid - c#

I had these two buttons:
<button id="submit" name="button" value="register" class="btn btn-primary">Submit</button>
<button id="cancel" name="button" value="cancel" class="btn btn-secondary">Cancel</button>
In a page that has some text fields with some validation on them for example
#Html.TextBoxFor(m => m.EmailRequest, new { #class = "form-control", type = "email" })
#Html.ValidationMessageFor(m => m.EmailRequest)
And then to know if cancel button was cliked to redirect them to some other page, in controller I had it like this:
[HttpPost]
public ActionResult ForgotPassword(string button, ForgotPasswordViewModel fpModel)
{
// cancel button, go back to LoginPage
if (!string.IsNullOrEmpty(button) && button == "cancel")
{
return RedirectToAction("Login");
}
else
{
// blah
}
}
It works if they fill out good valid values in the text boxes and then they click on cancel BUT it does not even get called when there are validation errors on the text boxes and then click cancel. So it won't redirect them either.
So what should i do ?

It sounds as if you are trying to POST the form back to the server in both scenarios (cancel or submit).
It doesn't make much sense to POST a form back to a server if there are validation issues. If you do this, you then rely on server side validation checking and make sure you re route to Login. You should always have server side, but it is obviously best to not just rely on it and to have both server side and client side validation.
An alternative solution would be to replace the cancel button with a link.
E.g.
#Html.ActionLink("Cancel", "Login")
This is also quicker in terms of performance, because it will simply redirect the user to the login page. Instead of posting back to the server and then re routing.

Related

Trying to click a menu option and take me to a new view

Working in a MVC project using C# .Net.
I have a top menu where I have links to different views.
I'm trying to get my button click to take me to one of my views;
<input type="button" value="About Me" onclick="location.href='<%= #Url.Action("About Me", "AboutMePage") %>'"/>
But I'm hit with this error:
A potentially dangerous Request.Path value was detected from the client (<).
Not sure where I'm going wrong?
Cheers.
Try to add a Controller to Post your action.
<input type="submit" value="About Me"/>
After your controller
[HttpPost]
public ActionResult Index()
{
return RedirectToAction("About Me", "AboutMePage");
}

Does submit button passes its value to action method, on form submit?

Update:
What are the control/fields whose value would be submitted when the form is post back?
In an ASP.NET MVC Form, if user double clicks on the submit button, the form would be submitted two times. In order to solve this problem I implemented the solution explained here.
This is my solution, where I disable the submit button on form submit so it cannot be clicked again:
function preventFromBeingDoubleSubmitted() {
$('form').each(function () {
$(this).submit(function (e) {
if ($("form").valid()) {
// if form is valid, then disable the submit button so it cannot be double clicked (double submitted)
$(this).find(':submit').attr('disabled', 'disabled');
}
});
});
}
$(document).ready(function () {
preventFromBeingDoubleSubmitted();
});
This works fine, but I am getting a very strange behavior with ASP.NET Built in, Identity code. My login page, allows user to login with Facebook or Google (each of those buttons are submit buttons):
This is the code which generates the above login form (this is the built-in identity template):
#{
var loginProviders = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes();
if (loginProviders.Count() > 0)
{
using (Html.BeginForm("ExternalLogin", "Account", new { ReturnUrl = Model.ReturnUrl }))
{
#Html.AntiForgeryToken()
<div class="form-group">
#foreach (AuthenticationDescription p in loginProviders.OrderBy(o => o.Caption))
{
if (string.Equals(p.AuthenticationType, "google", StringComparison.InvariantCultureIgnoreCase))
{
<button type="submit" class="external-login-btn btn-google" id="#p.AuthenticationType" name="provider" value="#p.AuthenticationType" title="Log in using your #p.Caption account">Log in with #p.AuthenticationType</button>
}
if (string.Equals(p.AuthenticationType, "facebook", StringComparison.InvariantCultureIgnoreCase))
{
<button type="submit" class="external-login-btn btn-facebook" id="#p.AuthenticationType" name="provider" value="#p.AuthenticationType" title="Log in using your #p.Caption account">Log in with #p.AuthenticationType</button>
}
}
</div>
}
}
}
The above code, should hit the following Controller Action (built-in identity template):
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
}
After, adding the .js code to prevent double submission, the external login no longer works. The problem is, when user clicks on Log in with Facebook button, the provider name is no longer passed in to ExternalLogin Action.
If I remove preventFromBeingDoubleSubmitted() function, provider name would be passed in ExternalLogin Action method and everything works fine.
What I don't understand is, how is provider passed in to action method at the first place? And why disabling the button prevents provider from being passed in?
I will first answer this question:
What I don't understand is, how is provider passed in to action method at the first place?
You have a button with name="provider" value="#p.AuthenticationType" this code is passing the provider name to your action method.
Next:
And why disabling the button prevents provider from being passed in?
When the form is submitted, the value of disabled fields is not passed to the server. This is the default behaviour.
Now to solve it, we can hide the button instead of disabling it. So in your preventFromBeingDoubleSubmitted() you can change $(this).find(':submit').attr('disabled', 'disabled'); to $(this).find(':submit').hide();
Hope this helps.
Update
To answer a new question about which fields are included in the form data.
<input>
<button>
<option>
An HTML form is a section of a document containing normal content, markup, special elements called controls (checkboxes, radio buttons, menus, etc.), and labels on those controls. Users generally "complete" a form by modifying its controls (entering text, selecting menu items, etc.), before submitting the form to an agent for processing (e.g., to a Web server, to a mail server, etc.)
Users interact with forms through named controls.
A control's "control name" is given by its name attribute. The scope of the name attribute for a control within a FORM element is the FORM element.
HTML defines the following control types:
buttons
checkboxes
radio buttons
menus: Menus offer users options from which to choose. The SELECT element creates a menu, in combination with the OPTGROUP and OPTION elements.
input controls (number, text, etc.)
hidden controls
object controls: Authors may insert generic objects in forms such that associated values are submitted along with other controls. Authors create object controls with the OBJECT element.
Because buttons are controls so the button's value will be posted to the server (if the buttons have name and value like your example). So it is about html specification. NOT asp.net mvc, not Microsoft's specification
You can refer these links for more details
https://www.w3.org/TR/html4/interact/forms.html#h-17.2.1
https://www.w3.org/TR/html5/sec-forms.html#submittable-element

Disable validation on OnPostDelete in razorpages

I have a razorpage containing two button for submits(Post). One is submitting new entries entered on the page, and the other is deleting already added entries. The new entries and existing entries are all in the same form and both use the same model.
I use page handlers to control which method is executed.
My problem is that when I click the delete button on existing entries I get client side validation for the inputfields from the model used when creating new entries.
Is there a way to disable client side validation for the field used when creating new entries in my delete button? or is it possible to send only the button in the POST request to avoid validation?
<button asp-route-id="#line.Id" asp-page-handler="DeleteRow" accesskey="" type="submit" class="btn btn-default pull-left">
<span class="glyphicon glyphicon-trash"></span>
</button>
Here is a photo of the scenario. the first line is used to create new entries is SQL., second line is fetched from SQL. clicking the delete button(POST) on second row causes client side validation on first row and prevents submit/POST).
The validation is correct when submitting the form for a new entry, but need to prevent the validation when deleting an existing entry.
I found the answer, In the jquery.validate.js there was exceptions added to avoid validation.
// allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
if ( $( this ).attr( "formnovalidate" ) !== undefined ) {
validator.cancelSubmit = true;
}
<button asp-route-id="#line.Id" formnovalidate asp-page-handler="DeleteRow" accesskey="" type="submit" class="btn btn-default pull-left">
<span class="glyphicon glyphicon-trash"></span>
</button>

How do I do some custom unobtrusive validation in mvc in code?

Trying to get my head around unobtrusive validation. I created a simple page like this:
#using (Html.BeginForm())
{
<text>Validation for name should fail unless this box contains the word christmas</text>
#Html.TextBoxFor(c => c.IsChristmas, new { id = "IsChristmas" }) <br />
#Html.TextBoxFor(c => c.Name)
#Html.ValidationMessageFor(c => c.Name)
<br />
<input type="submit" value="Submit" />
}
The model just has two strings, [Required] Name and IsChristmas.
This works fine, if you press submit when the text box is empty, you get the Name is required validation error appearing.
What I want to do now is make a validation error appear when they try to submit, if the first textbox doesn't contain the word 'Christmas'. This is just to learn how I can create my own custom validation types. I don't want to use data attributes, I want to do it entirely in javascript. I'd like to hook into the existing unobtrusive stuff if possible.
Any ideas?
I figured I could write a function first:
function isChristmas()
{
return $('#isChristmas').val() == 'christmas';
}
Then perhaps I can register it somehow so it is called on submit? Either directly into the validation code, by registering some kind of handler, or write my own handler (a submit button click event) that calls isChristmas() and if it's false, calls a method to display the validation error.
I am not sure how flexible the unobtrusive stuff is. I guess another desirable thing would be that if the page is submitted with the validation being bypassed, I can check server-side as well and have it go back to the view and somehow display the error that way too.

Issue related to Submit HTTPPOST ActionMethod in MVC

I have asp.net MVC Web application.
i have an input button:
<input type="submit" name="Report" value="To File" id="rptToFile" />
i have another input textbox :
<input type="text" id="txtMemItem1" name="" />
when user hits enter in TextBox i have written code to open a new popup:
but problem is: by hitting enter, it calls HTTPPOST Action Method in Controller.. i dont want to submit it on EnterPress key, but want to open popup..
how can i solve my problem ???
THanks
That is default behavior of the HTML forms Whenever focused on form control and you pressed enter form gets posted to the server.
Alternative solution to this behavior can be write a javascript onkeypress event and check if keyCode is 13 (enter) then return false and open a popup else return true.
HTML
<input type="text" onKeyPress="keyPressed(event)" .../>
Javascript
function keyPressed(event)
{
var code = (e.keyCode ? e.keyCode : e.which);
if(code == 13)
{
//open a popup here.
return false;
}
return true;
}
Alternatively if you don't need to post the form ever then you can use something like below too.
<form onsubmit="return false" ></form>

Categories

Resources