ASP.Net Core Razor pages: how does <form class="needs-validation"> actually invoke client-side validation? - asp.net-core

I'm working with a ASP.Net Core 3.1 web application.
If a Razor page has a form with class="needs-validation", then client-side validation is invoked for the fields in that form. Specifically, jquery-validation-unobtrusive gets called when the user clicks "Submit".
Q: How exactly does this occur? What "magic" links the HTML class "needs-validation" to the"validate()" Javascript code? Is there some CSS file somewhere that defines this linkage?
Q: Is "needs-validation" a Bootstrap class? Or is it standard HTML5/CSS3? Where/how is it defined?
These are some of the links I've found, but I still don't understand the linkage between class "needs-validation" invoking the validation code:
https://wakeupandcode.com/validation-in-asp-net-core-3-1/
https://getbootstrap.com/docs/4.0/components/forms/
https://github.com/aspnet/jquery-validation-unobtrusive

By default, asp.net core application use jQuery Unobtrusive Validation and https://jqueryvalidation.org/ plugin to achieve the client side validation. JQuery Unobtrusive Validation parses the data- attributes and passes the logic to jQuery Validation, effectively "copying" the server-side validation logic to the client. You can display validation errors on the client using tag helpers as shown here (without the class="needs-validation"):
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Description" class="control-label"></label>
<input asp-for="Movie.Description" class="form-control" />
<span asp-validation-for="Movie.Description" class="text-danger"></span>
</div>
....
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
The class="needs-validation" is used for custom Bootstrap form validation messages (use HTML5 form validation), then, it will based on this class selector to find elements and validate the data. Check the Bootstrap Validation to learn how it works and how to use it.

Related

How to stay on the same page after a form submission integrated to a Google form

In my website i have a contact form, and i've integrated it with a Google form. I've added the google form's execute URL as the action URL so once its submitted the form is being populated with the form data. the way i have done it
But when its being submitted, its redirecting to a google form's response page. What i need is once its submitted, to stay on the same page and give an alert. Im not sure how to do this in vue js. Any suggestion will be appreciated.
the content on the redirected page
{"result":"success","data":"{\"name\":[\"sdvsdv\"],\"company\":[\"dsvdv\"]}"}
Form in vue js view
<form method="POST" id="appointment-form" action="https://script.google.com/macros/s/AKfycbzRHvjfmIZdwKnOm26PeFv64OyyyGAfcr68MxvYw/exec">
<div class="form-group">
<input type="text" placeholder="Your name" name="name" class="form-control" id="name" required>
</div>
<div class="form-group">
<input type="text" placeholder="Company name" name="company" class="form-control" id="company" required>
</div>
<buttontype="submit" class="btn btn-default btn-block form-submit-btn">Submit</button>
</form>
After read your code properly, i found many errors.
How are you saving input values?
To save, you have to use ```v-model directive````
I guess you save the input values in somewhere. To avoid your problem, you can add a method and call it on submit, and inside the method save your input values.

Scaffolded Identity Razor Pages Forms don't submit unless there is a route parameter

This happens on all the Scaffolded Identity Razor Pages that do not include a route parameter in the Form definition, but let's take the ForgotPassword one as an example:
Here is the form as defined on the scaffolded page:
<form method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
When I click the submit button, nothing happens. The browser dev tools confirm nothing happens. The page does not submit to the server. (and yes, I have entered a valid email address; if I don't, then the jquery validation correctly displays the appropriate error messages.)
But I've found that if I change the form definition to include a route parameter, as follows:
<form asp-route-unusedArg="SomeValue" method="post">
then the submit button works fine, and the form is submitted to the server. (Even though the OnPostAsync method defined by the server code does not expect a parameter at all; it is defined as public async Task<IActionResult> OnPostAsync()). The way I figured this out was to compare the form definition with that of the Login form, which was working fine, and had a route parameter for returnUrl.
What is going on here? Why is the form not submitting unless I add a route parameter?

vue.js + Jest : how to test a form post?

Until now I gave been using Avoriaz, but I would like to use Jest now ...
found some tuts... but could not get any hint on testing my contact view component sending POST to an external urk...
<form id="contactForm" action="https://formspree.io/mysite.com" method="POST">
<div class="form-group">
<input type="hidden" name="_next" v-model="next" />
<input type="hidden" name="_language" v-model="language" />
<input type="hidden" name="_subject" value="Contact from my site" />
<input v-model="sendername" ...>
<input v-model="email" ...>
</div>
<div class="form-group">
<div class="uk-margin">
<textarea v-model="message" ...></textarea>
</div>
</div>
<button type="submit" class="btn btn-primary btn-gradient submit">Send</button>
</form>
As the external post URL is only valid for production... I would like mock it and use the _next property as a callback page url...
any useful links to put me on first tracks ?? thanks a lot for feedback
You should prevent submit and post data using axios for example and then mock axios.
<!-- the submit event will no longer reload the page -->
<form v-on:submit.prevent="onSubmit"></form>
It's an easier way to unit-test that.

Customizing WSO2 IS login error messages

I am using WSO2 5.2. I have created a custom UserStoreManager that extends JDBCUserStoreManager and is readonly. Here is a snippet from user-mgt.xml.
<UserStoreManager class="org.arbfile.wso2.user.ReadOnlyJDBCUserStoreManager">
<Property name="TenantManager">org.wso2.carbon.user.core.tenant.JDBCTenantManager</Property>
<Property name="ReadOnly">true</Property>
<Property name="ReadGroups">false</Property>
<Property name="WriteGroups">false</Property>
........
</UserStoreManager>
In terms of user authentication, I'm doing user/passw verification in the doAuthenticate() method of my custom class. I'm also doing other checks like IP filtering and user account locked. I can throw UserStoreException when these other items fail. The problem I'm having is setting the appropriate error message based on certain failure conditions. I found the following link https://docs.wso2.com/display/IS500/Customizing+Authentication+Error+Messages, however the information is too vague. I need to know how to set a "new" custom error message so the authentication endpoint can pass it to the login.jsp where it is rendered. Right now I get the exact same error message no matter what error occurs.
EDIT: Adding html form code for clarity:
<form action="../commonauth" method="post" id="loginForm">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 form-group">
<input id="username" name="username" type="text" class="form-control" tabindex="0" placeholder="Username">
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 form-group">
<input id="password" name="password" type="password" class="form-control" placeholder="Password" autocomplete="off">
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 form-group">
<input type="hidden" name="sessionDataKey" value='e04168f9-95c7-4b87-93af-60e1ecdc6273'/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 form-group">
<div class="form-actions">
<button class="wr-btn green-ltgr col-xs-12 col-md-12 col-lg-12 uppercase font-extra-large" type="submit">Login</button>
</div>
</div>
</form>
I am using SAML and this is the form presented for form based login on the WSO2 server. The form action is "../commonauth". The form submission with username and password appears to be going against a different web app (and not the authenticationendpoint web app). The above code comes from basicauth.jsp.
Few months ago I had exactly same requirement but could not found proper solution. I found that BasicAutheticator every time sending the same error code to login page. As a workaround I changed my flow a little and decided to customize the login app instead of customizing WSO2 error code. I know it is a wrong practice but it solved my problem. Here is how my new architecture works.
I created a library with all logic of pre authentication checks, lets name it validation.jar
Then I added this library as maven dependency to login application which is authenticationendpoint.
Created a new servlet in login app, let's name it PreValidation.java
Modified the basicAuth.jsp and instead of submitting the form to /samlsso, Submitted the form to PreValidation servlet.
In PreValidation servlet, with the help of validation.jar do all validations except authentication ( which should be the task of WSO2).
If any Validation is failed, pass the corresponding error code back to to login.jsp and show the message on screen.
If all validations are done, submit the request to WSO2 and let the flow continue.
Hope this will help you.
Once the error codes are enabled from application-authentication.xml You can edit following JSPs to display error messages.
Login failed BasicAuth:- [IS_HOME]\repository\deployment\server\webapps\authenticationendpoint\basicauth.jsp
Remaining Attempts are over :- [IS_HOME]\repository\deployment\server\webapps\authenticationendpoint\retry.jsp
Please take a look at the URL in Get request. It contains the relevant error code. Hope this helps someone.

Styling Data Validation Errors with Bootstrap

I am working on an ASP.NET MVC 4 Project. I want to style data validation errors on my login page with Bootstrap 3.0. When I debug the page and it gives data validation errors, this codes are disappeared in source of my login form:
<form action="/Account/Login" class="col-md-4 col-md-offset-4 form-horizontal well" method="post"><input name="__RequestVerificationToken" type="hidden" value="Zbg4kEVwyQf87IWj_L4alhiHBIpoWRCJ9mRWXF6syGH4ehg9idjJCqRrQTMGjONnywMGJhMFmGCQWWvBbMdmGFSUPqXpx6XaS4YfpnbFm8U1" /><div class="validation-summary-errors"><ul><li>The user name or password provided is incorrect.</li>
</ul></div> <div class="form-group control-group">
<div class="col-md-6 col-md-offset-3">
<input class="input-validation-error form-control" data-val="true" data-val-required="User name alanı gereklidir." id="UserName" name="UserName" placeholder="Kullanıcı Adı" type="text" value="" />
<span class="field-validation-error" data-valmsg-for="UserName" data-valmsg-replace="true">User name alanı gereklidir.</span>
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-3">
<input class="input-validation-error form-control" data-val="true" data-val-required="Password alanı gereklidir." id="Password" name="Password" placeholder="Şifre" type="password" />
<span class="field-validation-error" data-valmsg-for="Password" data-valmsg-replace="true">Password alanı gereklidir.</span>
</div>
</div>
<div class="form-group">
<div class="col-md-4 col-md-offset-4">
<button class="btn btn-default" type="submit">Giriş Yap</button>
</div>
</div>
</form>
How can I style these errors like "for=inputError" property of label with Bootstrap 3?
As it's shown in Bootstrap's docs, you need to apply class has-error to the div that contains the input and has class form-group:
<div class="form-group has-error">
...
</div>
It's a quite ugly to write a condition for each property you want to check and apply class has-error depending on the results of that condition, though you can do it like so:
<div class="form-group #(Html.ViewData.ModelState.IsValidField(Html.IdFor(x => x.UserName)) ? null : "has-error" )">
This takes care of the server side validation. However, there is also client side validation you need to think about. For that you'd need to write some jQuery that would check for existence of class field-validation-error and apply class has-error depending on the result.
You may do it all your self, though I suggest checking out TwitterBootstrapMVC which does all of that automatically for you. All you'd have to write is:
#Html.Bootstrap().FormGroup().TextBoxFor(m => m.UserName)
Disclaimer: I'm the author of TwitterBootstrapMVC. Using it in Bootstrap 2 is free. For Bootstrap 3 it requires a paid license.