Client validation doesn't fire after server error - c#

I have form which validate inputed email on uniqueness.
<form id="emailValidationForm">
#Html.ValidationSummary(true, String.Empty, new {#class = "text-danger text-center"})
<div class="form-group text-center">
<div class="input-group margin-bottom-5 margin-top-10">
<span class="input-group-addon"><i class="fa fa-user"></i></span>
#Html.TextBoxFor(m => m.Email, new {#class="form-control", #placeholder="Enter your Email",#data_toggle="tooltip"})
#*<input type="text" name="Email" placeholder="Enter your Email" class="form-control" data-toggle="tooltip">*#
</div>
#Html.ValidationMessageFor(m => m.Email, null, new { #class = "text-danger text-center" })
</div>
<div class="text-right">
<button type="submit" class="btn-u btn-u-wide btn-u-orange" title="Validate email">Join</button>
</div>
</form>
Email is part of next Model :
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
So, when i type nothing in text-box i will get error. When i type email that is already registered, i will get also error from function which checks uniqueness.
[AllowAnonymous]
public JsonResult EmailValidation(string email)
{
if (ModelState.IsValid)
{
var user = _service.FindByEmail(email);
if (user == null)
{
return Json(new {result = true, message = "Email is validated"}, JsonRequestBehavior.AllowGet);
}
ModelState.AddModelError(string.Empty, "Email already exists");
return Json(new
{
result = false,
message =
RenderRazorViewToString("~/Views/Account/_RegisterPartialView.cshtml",
new RegisterViewModel {Email = email})
}, JsonRequestBehavior.AllowGet);
}
return Json(new {result = false, message = "Input Email"}, JsonRequestBehavior.AllowGet);
}
But then client validation doesn't works, i can input nothing in email text-box and it will go on.
How can i fix it?
I use jquery 1.10.2 and jquery.validate for validation. Work on MVC5. Use Bootstrap3 for styling.
Also i have set custom defaults:
$.validator.setDefaults({
highlight: function (element) {
$(element).closest(".input-group").addClass("has-error");
},
unhighlight: function (element) {
$(element).closest(".input-group").removeClass("has-error");
}
});
That script is in partialView (i try to replace it in js-module that is used on partialView, but this doesn't works. So i left script it in partialView)

You need to add the remote annotation to the Email-field:
[Remote("EmailValidation","<ControllerName>", ErrorMessage="{0} already has an account, please enter a different email address.")]
public string Email { get; set; }
Also it appears to me like you are mixing two concepts here. The validation-check should be a simple JSON-result like this:
public JsonResult EmailValidation(string email)
{
var user = _service.FindByEmail(email);
return user == null
? Json(true, JsonRequestBehavior.AllowGet)
: Json(false, JsonRequestBehavior.AllowGet);
}

Related

Browser error in unobtrusive for asp.net MVC

I am trying to use unobtrusive Jquery to validate in client side but something is wrong.
the error like the attached image :
this is my code:
*In BundleConfig.cs
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*", "~/Scripts/jquery.unobtrusive*"));
*in the master page :
<script src="~/Scripts/jquery.validate.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js" type="text/javascript"></script>
*In view model class :
public class EmployeeViewModel
{
public int? EmployeeId { get; set; }
[MaxLength(length: 10, ErrorMessage = "First name can't be more than 10 charechers")]
[Required(AllowEmptyStrings = false, ErrorMessage = ("First name is required!"))]
public string FirstName { get; set; }
[MaxLength(length: 10, ErrorMessage = "First name can't be more than 10 charechers")]
[Required(AllowEmptyStrings = false, ErrorMessage = ("Last Nmae is required!"))]
public string LastName { get; set; }
[MaxLength(length: 20)]
public string FullName { get; set; }
[Range(500, 1500, ErrorMessage = "Salare must be between 500 DK and 1500 DK")]
[Required(AllowEmptyStrings = false, ErrorMessage = ("Salary is required!"))]
public double Salary { get; set; }
[EmailAddress(ErrorMessage = "Invalid Email")]
[Required(AllowEmptyStrings =false,ErrorMessage =("Email is required!"))]
public string Email { get; set; }
public bool IsMarriage { get; set; } = false;
public string Gender { get; set; }
public string DepartmentName { get; set; }
[Required(AllowEmptyStrings = false,ErrorMessage ="Birth day is required")]
//[DataType(DataType.Date)]
public DateTime? BirthDate { get; set; }
public TimeSpan? StartWorkingTime { get; set; }
public TimeSpan? EndWorkingTime { get; set; }
public int? DepartmentId { get; set; }
}
*In view :
#using (Html.BeginForm("Save","Employee",FormMethod.Post))
{
<div class="form-group ">
<div class="row">
<div class="col-md-2 col-form-label">
#Html.LabelFor(e => e.FirstName, "First Name")
</div>
<div class="col-md-10">
#Html.TextBoxFor(e => Model.FirstName, new { #class = "form-control" })
#Html.ValidationMessageFor(e => e.FirstName, "", new { #class = "text-danger text-left" })
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-2">
#Html.LabelFor(e => e.LastName, "Last Name")
</div>
<div class="col-md-10">
#Html.TextBoxFor(e => Model.LastName, new { #class = "form-control" })
#Html.ValidationMessageFor(e => e.LastName, "", new { #class = "text-danger text-left" })
</div>
</div>
</div>
}
**the problem that the client validation not working, but the server side working good
I think there could be a problem with your MaxLength attribute syntax. It shoud be
[MaxLength(10, ErrorMessage = "First name can't be more than 10 charechers.")]
But for client validation, instead of using MaxLength attribute, you should try to replace it by StringLength attribute.
[StringLength(10, ErrorMessage = "First name can't be more than 10
charechers.")] [Required(AllowEmptyStrings = false, ErrorMessage =
("First name is required!"))]
public string FirstName { get; set; }
I understand this is an year old question however might help someone who might come here looking for answer.
First of all, questioner has not posted the code completely, so it is difficult to arrive at a conclusion why exactly we get error(what is undefined). I do not see the jquery client side validation rules which define the rules and messages for form inputs.
Apart from what he has done, he will need to have client side validation rules as follows:
This example is for a simple registration form which consists are Email, Password and Confirm Password as text input.The code is as follows:
$('#registerFormId').validate({
errorClass: 'help-block animation-slideDown',
// You can change the animation class for a different entrance animation - check
animations page
errorElement: 'div',
errorPlacement: function (error, e) {
e.parents('.form-group > div').append(error);
},
highlight: function (e) {
$(e).closest('.form-group').removeClass('has-success has-error').addClass('has-error');
$(e).closest('.help-block').remove();
},
success: function (e) {
e.closest('.form-group').removeClass('has-success has-error');
e.closest('.help-block').remove();
},
rules: {
'Email': {
required: true,
email: true
},
'Password': {
required: true,
minlength: 6
},
'ConfirmPassword': {
required: true,
equalTo: '#Password'
}
},
messages: {
'Email': 'Please enter valid email address',
'Password': {
required: 'Please provide a password',
minlength: 'Your password must be at least 6 characters long'
},
'ConfirmPassword': {
required: 'Please provide a password',
minlength: 'Your password must be at least 6 characters long',
equalTo: 'Please enter the same password as above'
}
}
});
Please make sure the names of your text inputs should be same as the properties that you want to validate.
Apart from this make sure Client side validation unobtrusive is enabled in web.config as follows:
Here is an excellent blog post which explains how to implement client and server side validation using jquery unobstrusive validation.
https://www.c-sharpcorner.com/article/asp-net-mvc5-jquery-form-validator/#:~:text=Server%20side%20form%20validation%2C%20as,with%20ASP.NET%20MVC5%20platform.
Asma Shaikh
Note : Above blog post is NOT written by me

Invalid column name 'Length' webmatrix

im new in asp.net mvc. i watch a tutorial and he is using webmatrix. i tried to add column named "IDViewer" in table "UserProfile" in my database created by webmatrix. but then, when i tried to insert some value it returns me an error of "Invalid column name 'Length'." but i did not declare column name "Length" in my code. please check my codes and the images. thank you
Images Link Here. please take a look
The error
My database, i added column named IDViewer
public class Register
{
[Required(ErrorMessage = "Please provide password", AllowEmptyStrings = false)]
public string Username { get; set; }
[Required(ErrorMessage = "Please provide password", AllowEmptyStrings = false)]
[DataType(System.ComponentModel.DataAnnotations.DataType.Password)]
[StringLength(50, MinimumLength = 8, ErrorMessage = "Password must be 8 char long.")]
public string Password { get; set; }
public string IDViewer { get; set; }
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary("", new { #style = "color: red" })
<label>Username</label>
#Html.TextBoxFor(m => m.Username, new { #class = "form-control" })
<label>Password</label>
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
<label>Student ID</label>
#Html.TextBoxFor(m => m.IDViewer, new { #class = "form-control" })
#Html.DropDownList("role",roles,"Select Account Type")
<button class="btn btn-primary">Register</button>
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Register(Register registerdata, string role)
{
if(ModelState.IsValid)
{
try
{
WebSecurity.CreateUserAndAccount(registerdata.Username, registerdata.Password, registerdata.IDViewer);
Roles.AddUserToRole(registerdata.Username,role);
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException)
{
ModelState.AddModelError("", "Sorry the username already exists");
return View(registerdata);
}
}
ModelState.AddModelError("","Data invalid");
return View(registerdata);
}
From the documentation, the 3rd parameter is a dictionary
propertyValues
Type: System.Object
(Optional) A dictionary that contains additional user attributes. The default is null.
so your method needs to be
WebSecurity.CreateUserAndAccount(registerdata.Username,
registerdata.Password, new { IDViewer = registerdata.IDViewer });

changing a role with html select box asp.net mvc4

I am using the ASP.NET web application template and trying to allow a user to pick a role when registering.
Here is what I got at the moment.
Does it
View
<fieldset class="col-lg-5 .col-md-5">
<legend>Registration Form</legend>
<p>
#Html.LabelFor(m => m.UserName)
#Html.TextBoxFor(m => m.UserName, new { #class = "form-control" })
</p>
<p>
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
</p>
<p>
#Html.LabelFor(m => m.ConfirmPassword)
#Html.PasswordFor(m => m.ConfirmPassword, new { #class = "form-control" })
</p>
<p>
#Html.DropDownListFor(model => model.Type, Model.TypeList)
</p>
<input type="submit" value="Register" class="btn btn-default" />
</fieldset>
Model
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
public string Type { get; set; }
public IEnumerable<SelectListItem> TypeList
{
get
{
return new List<SelectListItem>
{
new SelectListItem { Text = "athlete", Value = "athlete"},
new SelectListItem { Text = "coach", Value = "coach"},
};
}
}
}
Controller
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
Roles.AddUserToRole(model.UserName, model.Type);
WebSecurity.Login(model.UserName, model.Password);
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
I am feel like I am close but I can't quiet get it and i am getting this error
Compiler Error Message: Models.RegisterModel>' does not contain a definition for 'DropDownListFor' and the best extension method overload 'System.Web.Mvc.Html.SelectExtensions.DropDownListFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>, System.Collections.Generic.IEnumerable)' has some invalid arguments
Did you initialize your model in HttpGet Register method? Like below...
[AllowAnonymous]
public ActionResult Register()
{
var model = new RegisterModel();
return View(model);
}
I create an empty template MVC4 app, added your code, got object reference not set error as default Register model does not pass model object to view which you are trying to access (i.e. loading TypeInt in DropDownListFor()).
I then initialized model in Get method as shown above. All works fine, i was able to pick a role on register view.
Check if this helps.
take a look your last comma should be removed:
new SelectListItem { Text = "athlete", Value = "athlete"},
new SelectListItem { Text = "coach", Value = "coach"}

ASP.NET MVC Razor Model state not valid on RegisterModel

I'm having two issues with editing my applications RegisterModel.
A) The fields UserName and Email are rendered as password fields?
B) The modelstate is always invalid (and my model is empty)
I think they are both caused because I have a "HomeModel" which contains "LoginModel" and "RegisterModel" property and it passes the entire HomeModel instead of the corresponding property. How can I make it pass the correct one?
I have the following form:
#using (Ajax.BeginForm("Register", "Account", new AjaxOptions { UpdateTargetId = "RegisterAjaxResponse" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="form-row">
<div id="RegisterAjaxResponse"></div>
</div>
<div class="form-row">
#Html.LabelFor(m => m.RegisterModel.UserName)
#Html.PasswordFor(m => m.RegisterModel.UserName)
#Html.ValidationMessageFor(m => m.RegisterModel.UserName)
</div>
<div class="form-row">
#Html.LabelFor(m => m.RegisterModel.Password)
#Html.PasswordFor(m => m.RegisterModel.Password)
#Html.ValidationMessageFor(m => m.RegisterModel.Password)
</div>
<div class="form-row">
#Html.LabelFor(m => m.RegisterModel.ConfirmPassword)
#Html.PasswordFor(m => m.RegisterModel.ConfirmPassword)
#Html.ValidationMessageFor(m => m.RegisterModel.ConfirmPassword)
</div>
<div class="form-row">
#Html.LabelFor(m => m.RegisterModel.Email)
#Html.PasswordFor(m => m.RegisterModel.Email)
#Html.ValidationMessageFor(m => m.RegisterModel.Email)
</div>
<div class="form-row">
<input type="submit" value='Register' />
</div>
}
The model:
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
[DataType(DataType.Text)]
public string UserName { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "EmailAddress")]
public string Email { get; set; }
}
But the UserName and Email field are rendered as an password field.
http://i.imgur.com/GCamint.png
-Can't page images yet, sorry.
And my modelstate is always invalid.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
string returnValue = "";
if (ModelState.IsValid)
{
//Some code that is never executed
}
return Content(returnValue, "text/html");
}
Problem A: you're rendering the textfields for email and username using #Html.PasswordFor(), this will render password fields, try using #Html.TextboxFor()
And for problem B, it depends if you're targetting MVC3 or 4 and which version of .NET.
Later versions of .NET use the compare annotation as
[Compare(CompareField = Password, ErrorMessage = "Passwords do not
match")]
a) Because you have in razor view for them
#Html.PasswordFor(m => m.RegisterModel.UserName)
need to be
#Html.TextboxFor(m => m.RegisterModel.Email)

How does the MVC3 Controller retrieve HTTPPOST params?

I'm not quite understanding how this works.
Passing parameters from my entity objects works fine. But when I create new fields, only the first one is retrieved.
Model User Class:
public class User {
[Key]
public long Uid { get; set; }
[Required]
[StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 4)]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email:")]
public string Email { get; set; }
[Required]
[StringLength(20, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 4)]
[Display(Name = "User Name:")]
public string Username { get; set; }
public string Password { get; set; }
public byte Role { get; set; }
public DateTime Created { get; set; }
}
CSHTML:
#using (Html.BeginForm( null,
null,
FormMethod.Post,
new { id = "regform" })
) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Register</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Username)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Username)
#Html.ValidationMessageFor(model => model.Username)
</div>
<div class="editor-label">
Password:
</div>
<div class="editor-field">
#Html.Password("pwd")
</div>
<div class="editor-label">
Confirm Password:
</div>
<div class="editor-field">
#Html.Password("confirm")
</div>
<p>
<input type="submit" value="Register" />
</p>
</fieldset>
}
Controller:
[HttpPost]
public ActionResult Register(User user, string pwd, string confirm) {
user.Username = confirm;
user.Created = DateTime.Now;
user.Role = 255;
user.Password = EncryptPassword.Password(pwd);
if (ModelState.IsValid && pwd == confirm) {
db.Users.Add(user);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(user);
}
Where I'm getting confused, is pwd picks up fine. confirm on the other hand remains null. My initial thought that it was calling by order and confirm in the model was simply conPwd. When that didn't work, I changed it's name to confirm. It still is not working and I can't find anything that explains how multiple parameters are passed to the controller.
Edit:
Updated my code. Believe it or not, this alone has taken me most of the day to write because I've been trying to understand what I'm doing. There is just so much to take in when you're learning Entities, LINQ, MVC, ASP.NET and Razor all at the same time. Basic C# is the only part I came in to this knowing. :)
You need a strongly typed view for your RegisterModel then use a Html.BeginForm to post the data to the controller.
Model
// This is the Model that you will use to register users
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
View (CSHTML)
// This is your strongly typed view that will use
// model binding to bind the properties of RegisterModel
// to the View.
#model Trainer.Models.RegisterModel
// You can find these scripts in default projects in Visual Studio, if you are
// not using VS, then you can still find them online
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
// This is where your form starts
// The "Account" parameter states what controller to post the form to
#using (Html.BeginForm((string)ViewBag.FormAction, "Account")) {
#Html.ValidationSummary(true, "Account creation was unsuccessful. Please correct the errors and try again.")
<fieldset>
<legend>Registration Form</legend>
<ol>
<li>
#Html.LabelFor(m => m.UserName)
#Html.TextBoxFor(m => m.UserName)
#Html.ValidationMessageFor(m => m.UserName)
</li>
<li>
#Html.LabelFor(m => m.Email)
#Html.TextBoxFor(m => m.Email)
#Html.ValidationMessageFor(m => m.Email)
</li>
<li>
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password)
#Html.ValidationMessageFor(m => m.Password)
</li>
<li>
#Html.LabelFor(m => m.ConfirmPassword)
#Html.PasswordFor(m => m.ConfirmPassword)
#Html.ValidationMessageFor(m => m.ConfirmPassword)
</li>
</ol>
<!-- The value property being set to register tells the form
what method of the controller to post to -->
<input type="submit" value="Register" />
</fieldset>
}
Controller
// The AccountController has methods that only authorized
// users should be able to access. However, we can override
// this with another attribute for methods that anyone
// can access
[Authorize]
public class AccountController : Controller
{
// This will allow the View to be rendered
[AllowAnonymous]
public ActionResult Register()
{
return ContextDependentView();
}
// This is one of the methods that anyone can access
// Your Html.BeginForm will post to this method and
// process what you posted.
[AllowAnonymous]
[HttpPost]
public ActionResult Register(RegisterModel model)
{
// If all of the information in the model is valid
if (ModelState.IsValid)
{
// Attempt to register the user
MembershipCreateStatus createStatus;
Membership.CreateUser(model.UserName, model.Password, model.Email, passwordQuestion: null, passwordAnswer: null, isApproved: true, providerUserKey: null, status: out createStatus);
// If the out parameter createStatus gives us a successful code
// Log the user in
if (createStatus == MembershipCreateStatus.Success)
{
FormsAuthentication.SetAuthCookie(model.UserName, createPersistentCookie: false);
return RedirectToAction("Index", "Home");
}
else // If the out parameter fails
{
ModelState.AddModelError("", ErrorCodeToString(createStatus));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
}

Categories