Merge validation summary in single line(All required validation in single line,All invalid field validation in single line etc) - asp.net-mvc

I am creating one ASP.NET MVC Application using JQuery,KnockOutJs etc.
I have one model for SignUp and use client side validation only.
public class SignUp
{
[Required(ErrorMessageResourceType = typeof(Messages), ErrorMessageResourceName = MessagesConst.UserNameIsRequired, AllowEmptyStrings = false)]
[StringLength(30, ErrorMessageResourceName = MessagesConst.UserNameLength, ErrorMessageResourceType = typeof(Messages))]
[RegularExpression(#"^[a-zA-Z ]*$", ErrorMessageResourceType = typeof(Messages), ErrorMessageResourceName = MessagesConst.OnlyAlphabetsAndSpaceAreAllowed)]
public string UserName { get; set; }
[RegularExpression(#"^\s*[_A-Za-z0-9-]+(\.[_A-Za-z0-9-]+)*#[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,4})[ ]*$", ErrorMessageResourceType = typeof(Messages), ErrorMessageResourceName = MessagesConst.InvalidEmail)]
[Required(ErrorMessageResourceType = typeof(Messages), ErrorMessageResourceName = MessagesConst.EmailIsRequired, AllowEmptyStrings = false)]
[StringLength(256, ErrorMessageResourceName = MessagesConst.EmailLength, ErrorMessageResourceType = typeof(Messages))]
public string Email { get; set; }
[DataType(DataType.Password)]
[StringLength(50, ErrorMessageResourceName = MessagesConst.PasswordRange, ErrorMessageResourceType = typeof(Messages),MinimumLength = 6)]
[Required(ErrorMessageResourceType = typeof(Messages), ErrorMessageResourceName = MessagesConst.PasswordRequired, AllowEmptyStrings = false)]
public string Password { get; set; }
[DataType(DataType.Password)]
[Compare("Password", ErrorMessageResourceName = MessagesConst.InvalidConfirmPassword, ErrorMessageResourceType = typeof(Messages))]
public string ConfirmPassword { get; set; }
public bool IsNewsLetter { get; set; }
public bool RememberMe { get; set; }
}
I m showing validation summary on view.
#using (Html.BeginForm("Registration", "Home", FormMethod.Post, new { id = "frmRegistration" }))
{
<div class="msg">
#Html.ValidationSummary(false)
</div>
<h1 class="title">#UserResource.lblSignUp</h1>
<div class="content_box signup">
<div class="sign_up">
<div class="left">
<div class="logo">
<a href="/" title="Home">
</a>
</div>
<div class="feat_text">
<h1>#LayoutResources.tglnCF</h1>
<p class="subtitle">#LayoutResources.tglnSubTitleCF</p>
</div>
<div class="bottom_box">
<strong>#UserResource.lblAlreadyAccountOnSocialnetwork</strong><br>
<span class="sing_in_direct">#UserResource.lblSignIn directly from here.</span>
</div>
</div>
<div class="right">
#*Remove Placeholders for validation issue.*#
<div class="control-group">
<label class="blue">#UserResource.lblUserName</label>
<div class="controls">
#Html.TextBoxFor(m => m.UserName, new { #data_bind = "value:UserName, valueUpdate:['afterkeydown','propertychange','input']", placeholder = Placeholders.UserName, want_live_validation = true })
<span class="help-inline">
<span class="sprite"></span>
</span>
#*#Html.ValidationMessageFor(m => m.UserName)*#
</div>
</div>
<div class="control-group">
<label class="blue">#UserResource.lblEmail</label>
<div class="controls">
#Html.TextBoxFor(m => m.Email, new { #data_bind = "value:Email, valueUpdate:['afterkeydown','propertychange','input']", placeholder = Placeholders.Email, want_live_validation = true })
<span class="help-inline">
<span class="sprite"></span>
</span>
#*#Html.ValidationMessageFor(m => m.Email)*#
</div>
</div>
<div class="control-group">
<label class="blue">#UserResource.lblPassword</label>
<div class="controls">
#Html.PasswordFor(x => x.Password, new { #data_bind = "value:Password, valueUpdate:['afterkeydown','propertychange','input']", title = ToolTipResources.ttPassword, placeholder = Placeholders.Password, #class = "tooltip", want_live_validation = true })
<span class="help-inline">
<span class="sprite"></span>
</span>
#*#Html.ValidationMessageFor(m => m.Password)*#
<div class="m-t5">
<div data-bind="css:PasswordStrengthClass()"></div>
<span id='result' data-bind="text:PasswordStrengthMessage()"></span>
</div>
</div>
</div>
<div class="control-group">
<label class="blue">#UserResource.lblConfirmPassword</label>
<div class="controls">
#Html.PasswordFor(m => m.ConfirmPassword, new { #data_bind = "value:ConfirmPassword, valueUpdate:['afterkeydown','propertychange','input']", placeholder = Placeholders.ConfirmPassword, want_live_validation = true })
<span class="help-inline">
<span class="sprite"></span>
</span>
#*#Html.ValidationMessageFor(m => m.ConfirmPassword)*#
</div>
</div>
<label class="checkbox blue" for="checkbox1">
#Html.CheckBoxFor(m => m.IsNewsLetter, new { name = "check1", id = "checkTermAndPolicy" })
#UserResource.lblDiscoverNewProjectWithWeeklyNewsLetter
</label>
<p class="terms_text">
#UserResource.lblBySignInYouAgreeToOur #UserResource.lblTermsOfUse #UserResource.lblAnd #UserResource.lblPrivacyPolicy.
</p>
<div>
<p class="errorMassage"></p>
</div>
<input type="submit" value="SIGN UP">
</div>
<div class="clear"></div>
</div>
</div>
}
currently summary appear like
but i want to customize that summary like all validation that fire for required field will show like(User Name,Email,Password Required.)
or all validation that fire for invalid field will show like(invalid email address User Name,Email.)

You could try #Html.ValidationSummary().ToString().Replace("\r\n", "").Replace("\n", "").Replace("\r", "")
I'm not sure how validationsummary spits out its linebreaks, however, so you can probably find out and cut that down.

Related

How to make your button on a form using asp.net-mvc work?

I have a button, it does not seem to create new users to my database. What it does it only inherits user validaton to my Login method and need some guidance to this please and thanks. Below is the logic what i am trying to do. What i want to do my create button must be able to create new users if not exist to the database.
Controller:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateModel objSubmit)
{
ViewBag.Msg = "Details submitted successfully";
return View(objSubmit);
}
// This is for login, and its hits this method each time.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(Login login)
{
if (ModelState.IsValid)
{
bool success = WebSecurity.Login(login.username, login.password, false);
var UserID = GetUserID_By_UserName(login.username);
var LoginType = GetRoleBy_UserID(Convert.ToString(UserID));
if (success == true)
{
if (string.IsNullOrEmpty(Convert.ToString(LoginType)))
{
ModelState.AddModelError("Error", "Rights to User are not Provide Contact to Admin");
return View(login);
}
else
{
Session["Name"] = login.username;
Session["UserID"] = UserID;
Session["LoginType"] = LoginType;
if (Roles.IsUserInRole(login.username, "Admin"))
{
return RedirectToAction("AdminDashboard", "Dashboard");
}
else
{
return RedirectToAction("UserDashboard", "Dashboard");
}
}
}
else
{
ModelState.AddModelError("Error", "Please enter valid Username and Password");
return View(login);
}
}
else
{
ModelState.AddModelError("Error", "Please enter Username and Password");
return View(login);
}
}
Model:
namespace eNtsaPortalWebsiteProject.Models
{
public class CreateModel
{
[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; }
[Required]
public string username { get; set; }
}
}
// View for login
<div data-="mainContent">
<section class="container">
<div class="logo col-sm-12 text-center col-md-12"> <img alt="" src="~/Images/eNtsa.png" /></div>
<div class="clearfix"></div>
<div class="container">
<div class="row">
<div id="MyWizard" class="formArea LRmargin">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div id="divMessage" class="text-center col-md-12 col-md-offset-12 alert-success">
#Html.ValidationSummary()
</div>
<div class="col-md-12 col-md-offset-10 col-xs-12">
<div class="loginPage panel-info">
<div class="form-group"><span class=""><i class="glyphicon glyphicon-user">Username:</i></span>
#Html.TextBoxFor(model => model.username, new { #class = "form-control text-center", autocomplete = "off" })
#Html.ValidationMessageFor(model => model.username)
</div>
<div class="form-group">
<span class=""><i class="glyphicon glyphicon-lock">Password:</i></span>
#Html.PasswordFor(model => model.password, new { #class = "form-control text-center", autocomplete = "off" })
#Html.ValidationMessageFor(model => model.password)
</div>
</div>
<div class="form-group">
<input id="BtnLogin" type="submit" class="btn btn-success btn-pressure" name="BtnLogin" value="Login" />
<input type ="Submit" class="btn btn-info btn-pressure" name="BtnCreate" value="Create" />
</div>
</div>
}
<div class="clear"></div>
</div>
</div>
</div>
</section>
</div>
View for creating user:
<div class="mainContent">
<section class="container">
<div class="logo col-sm-12 text-center col-md-10">
<img alt="" src="~/Images/eNtsa.png"/>
</div>
<div class="container">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div id="divMessage" class="text-center col-md-12 col-md-offset-12 alert-success">
#Html.ValidationSummary()
</div>
<div class="col-md-12 col-md-offset-10 col-xs-12">
<div class="glyphicon-registration-mark">
<div class="form-group"><span class=""><i class="glyphicon glyphicon-user">Username:</i></span>
#Html.TextBoxFor(model=>model.username, new {#class ="form-control text-center", automplete="off" })
#Html.ValidationMessageFor(model=>model.username)
</div>
<div class="form-group">
<span class=""><i class="glyphicon glyphicon-lock">Password:</i></span>
#Html.PasswordFor(model=>model.password, new {#class = "form-control text-center", autocomplete="off" })
#Html.ValidationMessageFor(model=>model.password)
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-success btn-pressure" name="BtnSubmit" value="Submit"/>
</div>
</div>
}
</div>
</section>
</div>
The button is working - that isn't the problem that you're having.
You can have multiple buttons to submit the form but they will return to the same place, either:
a) the controller/action specified in the "action" property of the form
b) if no action is specified then the default location - in your case there isn't one directly specified so it is posting back to the default location.
(see: How to link HTML5 form action to Controller ActionResult method in ASP.NET MVC 4)
The easiest way to accomplish what you're trying to do would be refactor your controller and branch the logic depending on what the value is of the submit button.
(see: MVC razor form with multiple different submit buttons?
and How to handle two submit buttons on MVC view)
This will require some refactoring of the code that you have written, but it is the most straightforward way of achieving what you're trying to do.
In very basic terms it would look something like this:
Model:
namespace eNtsaPortalWebsiteProject.Models
{
public class LoginCreateModel
{
[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; }
[Required]
public string username { get; set; }
public string btnSubmit { get; set; } // both buttons will have the same name on your form, with different values ("Create" or "Login")
}
}
Controller:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginCreateModel objSubmit)
{
if (objSubmit.btnSubmit == "Create")
{
// Handle creation logic here
}
if (objSubmit.btnSubmit == "Login")
{
// Handle login logic here
}
return View(objSubmit);
}

How can I send email to dedicated email address based on dropdown selection in MVC view

I wanted to send an email in contact us form and redirect the email to certain email address based on drop-down selection i.e. if general selected i wanted the email to go general#xxxx.com or info selected from the drop-down the email should go to info#xxxx.com, I have already created the form But not sure how to go about doing this using MVC actionResult and #Razor views
my view
#model ETWServices.Models.ContactUs
#{
var culture = System.Threading.Thread.CurrentThread.CurrentUICulture.Name.ToLowerInvariant();
}
<div class="cards">
<div class="card">
<div id="contact-form" class="clearfix">
#Html.ValidationSummary(true)
#using (Html.BeginForm())
{
<h1>
#Resources.ResContact.Title
</h1>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Subject)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Subject)
#Html.ValidationMessageFor(model => model.Subject)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Message)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.Message)
#Html.ValidationMessageFor(model => model.Message)
</div>
<p>
<div class="submit">
<input type="submit" value="#Resources.ResContact.Send" id="btnSubmit" />
</div>
</p>
}
</div>
</div>
</div>
Contact us controller
[HttpPost]
public ActionResult Contact(ContactUs contUs)
{
if (ModelState.IsValid)
{
try
{
MailMessage mailMsg = new MailMessage();
mailMsg.From = new MailAddress(contUs.Email);
mailMsg.To.Add("xxxxx#gmail.com");
mailMsg.Subject = contUs.Subject;
mailMsg.Body = contUs.Message;
SmtpClient smtp = new SmtpClient();
smtp.Host = "smtp.gmail.com";
smtp.Port = 587;
smtp.Credentials = new System.Net.NetworkCredential("xxxx#gmail.com", "gmailpassword");
smtp.EnableSsl = true;
smtp.Send(mailMsg);
ModelState.Clear();
}
catch (Exception ex)
{
ModelState.Clear();
ViewBag.Message = " Sorry we are facing Problem here ";
}
}
return View();
}
Contact us Model
public class ContactUs
{
[Display(Name = nameof(Resources.ResContact.Name), ResourceType = typeof(Resources.ResContact))]
[Required(ErrorMessageResourceType =typeof(Resources.ResContact),
ErrorMessageResourceName = nameof(Resources.ResContact.NameReq))]
[StringLength(20, MinimumLength = 5,ErrorMessageResourceType =typeof(Resources.ResContact),
ErrorMessageResourceName = "NameShort")]
public string Name { get; set; }
[Display(Name = "Email", ResourceType =typeof(Resources.ResContact))]
[Required(ErrorMessageResourceType = typeof(Resources.ResContact),
ErrorMessageResourceName = "Emailrequired")]
[RegularExpression(".+#.+\\..+", ErrorMessageResourceType = typeof(Resources.ResContact),
ErrorMessageResourceName = "EmailWrong")]
public string Email { get; set; }
[Required(ErrorMessageResourceType =typeof(Resources.ResContact),
ErrorMessageResourceName ="subjectRequired")]
[Display(Name = "Subject", ResourceType = typeof(Resources.ResContact))]
public string Subject { get; set; }
[Required(ErrorMessageResourceType = typeof(Resources.ResContact),
ErrorMessageResourceName = "msgRequired")]
[Display(Name = "Message", ResourceType = typeof(Resources.ResContact))]
public string Message { get; set; }
}
The simple solution, is add a SELECT element to your form, add a new property to your view model, which is matching with the SELECT element name attribute value.
<SELECT name="toAddress">
<option value="info">Info</option>
<option value="general">General</option>
</SELECT>
Now add one property to your view model with same name
public class ContactUs
{
public string ToAddress { set;get;}
// your existing properties goes here
}
Now when user submits the form, your method parameters ToAddress property will have the selected value (info or general),. You can use it further to build your full email address.
[HttpPost]
public ActionResult Contact(ContactUs contUs)
{
var toSelection = contUs.ToAddress;
//use this as needed
}
Here we hard coded the SELECT element with 2 options. But there are other ways to render the dropdown, like using the DropDownListFor helper method.

SelectListItem properties in view model are not passed back from view to controller

I have this View Model:
public class UserViewModel
{
public string ID { get; set; }
[Required]
[Display(Name = "Nombre")]
public string Nombre { get; set; }
[Required]
[Display(Name = "Login")]
public string Login { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Contraseña")]
public string Password { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "E-mail")]
public string Email { get; set; }
[DataType(DataType.PhoneNumber)]
[Display(Name = "Teléfono")]
public string PhoneNumber { get; set; }
[Display(Name = "Ciudad")]
public System.Web.Mvc.SelectListItem City { get; set; }
[Display(Name = "Empresas")]
public IEnumerable<System.Web.Mvc.SelectListItem> Empresas { get; set; }
[Required]
[Display(Name = "Perfil")]
public string Role { get; set; }
[Display(Name = "Está Vigente")]
public bool Vigente { get; set; }
}
the problem I am having is that when I select something in City and Empresas in the form (they are both SELECT fields), they are not passed to controller in UserViewModel parameter:
public JsonResult EditUser(UserViewModel model)
{
.....
}
Only other properties are passed.
What is the right way to manage this?
EDIT:
this is part of the view:
#using (Html.BeginForm("EditUser", "Account", new { area = "Security" }, FormMethod.Post, new { #class = "form-horizontal form-label-left", role = "form", novalidate = "novalidate", id = "frmUsuario" }))
{
var id = Model == null ? String.Empty : Model.ID;
<div class="errores col-md-12 col-sm-12 col-xs-12" style="display: none">
<div class='validation-summary-errors alert alert-danger alert-white rounded' data-valmsg-summary="true">
<div class="icon">
<i class="fa fa-times-circle"></i>
</div>
<p>Debe completar los campos marcados en forma correcta.</p>
</div>
</div>
#Html.AntiForgeryToken();
<input type="hidden" value="#id" id="id" name="id" />
<div class="item col-md-12 col-sm-12 col-xs-12 form-group has-feedback">
#Html.TextBoxFor(m => m.Nombre, new { #class = "form-control has-feedback-left", placeholder = "Nombre", required = "required" })
<span class="fa fa-user form-control-feedback left" aria-hidden="true"></span>
</div>
<div class="item col-md-6 col-sm-6 col-xs-12 form-group has-feedback">
#Html.TextBoxFor(m => m.Login, new { #class = "form-control has-feedback-left", placeholder = "Login", required = "required" })
<span class="fa fa-sign-in form-control-feedback left" aria-hidden="true"></span>
</div>
<div class="item col-md-6 col-sm-6 col-xs-12 form-group has-feedback">
#{
//var requerido = String.IsNullOrEmpty(userId) ? "required" : String.Empty;
var requerido = Model == null || String.IsNullOrEmpty(Model.ID);
object htmlAttributes = null;
if (requerido)
{
htmlAttributes = new { #class = "form-control has-feedback-left", placeholder = "Contraseña", required = "required" };
}
else
{
htmlAttributes = new { #class = "form-control has-feedback-left", placeholder = "Contraseña" };
}
}
<!-- Para evitar que los password managers llenen los campos -->
<input type="text" id="hidUser" style="display: none" />
<!-- Para evitar que los password managers llenen los campos -->
<input type="password" id="hidPassword" style="display: none" />
#Html.PasswordFor(m => m.Password, htmlAttributes)
<span class="fa fa-key form-control-feedback left" aria-hidden="true"></span>
</div>
<div class="item col-md-6 col-sm-6 col-xs-12 form-group has-feedback">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control has-feedback-left", placeholder = "E-mail", required = "required" })
<span class="fa fa-envelope form-control-feedback left" aria-hidden="true"></span>
</div>
<div class="item col-md-6 col-sm-6 col-xs-12 form-group has-feedback">
#Html.TextBoxFor(m => m.PhoneNumber, new { #class = "form-control has-feedback-left", placeholder = "Teléfono" })
<span class="fa fa-phone form-control-feedback left" aria-hidden="true"></span>
</div>
<div class="item col-md-12 col-sm-12 col-xs-12 form-group">
#Html.DropDownListFor(m => m.City, new SelectList(new List<SelectListItem>()), new { style = "width: 100%" })
</div>
<div class="item col-md-12 col-sm-12 col-xs-12 form-group">
#Html.DropDownListFor(m => m.Role, new SelectList(new List<SelectListItem>()), new { style = "width: 100%" })
</div>
<div class="item col-md-12 col-sm-12 col-xs-12 form-group">
#Html.DropDownListFor(m => m.Empresas, new SelectList(new List<SelectListItem>()), new { style = "width: 100%", multiple = "multiple" })
</div>
<div class="item col-md-12 col-sm-12 col-xs-12 form-group">
Está Vigente
#Html.CheckBoxFor(m => m.Vigente, new { #class = "flat" })
</div>
}
Please change the type of City Property in UserViewModal
public string City { get; set; }
Then it will return selected option value to controller for e.g
<select
<option value="1">Delhi </option>
<option value="2">Surat </option>
</select>
if you select Delhi then it will assign value 1 to property
I wonder there's show nothing in your dropdown.
In your view model, it should contain at least two properties, such as AvailableCities and City.
public List<SelectListItem> AvailableCities { get;set; }
public string City { get;set; }
AvailableCities contains all cities which should show in dropdow. And the City is using for getting the value user selected.
In your view,
#Html.DropDownListFor(m => m.City, Model.AvailableCities, new { #class = "form-control" })
For now, you should see the dropdown shawn and which could get the selected value in your action.

Field required attribute acidentially invoked but clicking a button

I have these fields, and I implemented required attribute on them.
#using (Html.BeginForm("Edit", "ChannelsGrid", FormMethod.Post, new {name = "channelForm", #class = "channelForm", #enctype = "multipart/form-data"}))
{
<div class="form-group">
#Html.HiddenFor(model => Model.Id)
<div class="row">
<div class="col-md-6">
#Html.Label("Part/Location", new {#class = "control-label"})
#Html.TextBox("PartLocation", null, new { #class = "form-control", #required = "required" })
</div>
<div class="col-md-6">
#Html.Label("Index", new {#class = "control-label"})
#Html.TextBox("Index", null, new {#class = "form-control"})
</div>
</div>
<div class="row">
<div class="col-md-6">
#Html.Label("Measurement", new {#class = "control-label"})
#Html.DropDownListFor(model => model.Measurement, (SelectList)ViewBag.Measurements, "-- Select Measurement --", new { #class = "form-control", #required = "required" })
</div>
<div class="col-md-6">
#Html.Label("Location", new {#class = "control-label"})
#Html.DropDownList("Directions", ViewBag.DirectionTypes as List<SelectListItem>, "-- Select Direction --", new { #class = "form-control", #required = "required" })
</div>
</div>
<div class="row">
<div class="col-md-6">
#Html.LabelFor(model => model.ChannelGroupId, new {#class = "control-label"})
#Html.DropDownListFor(x => x.ChannelGroupId, Model.ChannelGroups, "Select Channel Group", new {#class = "form-control"})
#Html.ValidationMessageFor(model => model.ChannelGroupId)
</div>
<div class="col-md-3">
<label class="control-label"></label>
<a href="#" id="addChannelGroup" class="form-control" style="border: none">
<i class="fa fa-plus-circle">Add Group</i>
</a>
</div>
<div class="col-md-3">
<label class="control-label"></label>
<a href="#" id="addMeasurement" class="form-control" style="border: none">
<i class="fa fa-plus-circle">Add Measurement</i>
</a>
</div>
</div>
<br/>
<div class="row">
<div class="col-md-6">
#Html.Label("Channel name: ", new {id = "channelName", #class = "control-label"})
</div>
<div class="col-md-6">
#Html.TextBox("HiddenTextBox", null, new {#class = "hidden"})
<div class="col-md-1">
#Html.TextBoxFor(a => a.Name, new {#class = "hidden"})
</div>
</div>
</div>
</div>
<div class="row" id="pnlAddChannelGroupName" style="display: none">
<div class="col-md-6">
<label class="control-label">Channel Group Name :</label>
<input type="text" id="ChannelGroupName" name="ChannelGroupName" class="form-control"/>
<input type="button" value="Cancel" id="channelGroupButton" />
#*<button id="channelGroupButton">Cancel</button>*#
</div>
</div>
<div class="row" id="pnlMeasurement" style="display: none">
<div class="col-md-6">
#Html.Label("Measurement :", new {#class = "control-label"})
#Html.TextBox("MeasurementName", null, new {#class = "form-control"})
<input type="button" value="Cancel" id="measurementButton" />
#*<button id="measurementButton">Cancel</button>*#
</div>
</div>
}
I also have two buttons which are used to toggle other textboxes in this form. Here is the code.
<div class="row" id="pnlAddChannelGroupName" style="display: none">
<div class="col-md-6">
<label class="control-label">Channel Group Name :</label>
<input type="text" id="ChannelGroupName" name="ChannelGroupName" class="form-control"/>
<button id="channelGroupButton">Cancel</button>
</div>
</div>
<div class="row" id="pnlMeasurement" style="display: none">
<div class="col-md-6">
#Html.Label("Measurement :", new {#class = "control-label"})
#Html.TextBox("MeasurementName", null, new {#class = "form-control"})
<button id="measurementButton">Cancel</button>
</div>
</div>
The problem is whenever I click these two Cancel buttons in that field, the three fields seems to be invoked and there is brown border around the textbox dropdownlist. I guess these field have been submitted. But I thought I use button element instead of type button of an input so I can eliminate the submitting action of the button, right? Any clues? And how can I click these Cancel buttons withouts invoking validation in these other field?
Edited: I changed all the buttons to input type="button" and the validation of these other field dissapeared. Can someone explain?
This is my viewmodel:
namespace CrashTestScheduler.Entity.ViewModel
{
public class ChannelViewModel
{
public int Id { get; set; }
//[Display(Name = "Name")]
//[Required(ErrorMessage = "Please specify the channel name.")]
public string Name { get; set; }
public string Description { get; set; }
public string ChannelGroupName { get; set; }
public string MeasurementName { get; set; }
[Required(ErrorMessage = "Please select a channel group.")]
public int ChannelGroupId { get; set; }
public IEnumerable<SelectListItem> ChannelGroups { get; set; }
//[Required]
public string Measurement { get; set; }
}
}
The reason your form is submitting when clicking buttons is that the default action for a <button> element is type="submit" (refer documentation). You need to explicitly set the type attribute
<button type="button" ....>
However you have numerous issues with your approach.
By removing the [Required] attributes and using the required =
"required" html attribute, you now need to include manual
validation on the controller (never trust the user!)
Your mixing up Razor and manual html in the view, potentially
creating problems for model binding. Some of your label elements
wont work. (e.g. the first one is associated with a control named
"Part/Location" but there is no control named "Part/Location").
The user interface where your force users to click buttons to swap
between textboxes and dropdown lists is confusing and a sure way to
lose customers. Instead you should use an autocomplete control such
as jQuery Autocomplete which allows selection from a list or
direct text entry.
Your view model should contain validation attributes for its properties and can be simplified to
public class ChannelViewModel
{
public int Id { get; set; }
[Display(Name = "Part/Location")]
[Required]
public string PartLocation { get; set; }
public string Index { get; set; }
[Required]
public string Measurement { get; set; }
[Required]
[Display(Name = "Location")]
public int Direction { get; set; }
.... // other properties
public SelectList DirectionList { get; set; }
}
View
#Html.HiddenFor(model => Model.Id)
#Html.LabelFor(m => m.PartLocation, new {#class = "control-label"})
#Html.TextBoxFor(m => m.PartLocation, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.PartLocation)
#Html.LabelFor(m => m.Index, new {#class = "control-label"})
#Html.TextBoxFor(m => m.Index, new {#class = "form-control"})
#Html.LabelFor(m => m.Measurement, new {#class = "control-label"})
#Html.TextBoxFor(m => m.Measurement, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Measurement)
#Html.LabelFor(m => m.Direction, new {#class = "control-label"})
#Html.DropDownListFor(m => m.Direction, Model.DirectionList, "-- Select Direction --", new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Direction)
.... // more controls
The attach the autocomplete to $(#Measurement).autocomplete({...
This will give you client and server side validation out of the box, and a better user interface.

modelstate.isvalid not getting all the errors

I have this model :
[Required(ErrorMessage = "Please provide a valid EmailAddress")]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required(ErrorMessage = "Please provide a company name")]
[Display(Name = "Company")]
public string CompanyName { get; set; }
[Required(ErrorMessage = "Please provide a username")]
[Display(Name = "Username")]
public string UserName { get; set; }
[Required(ErrorMessage = "Please select at least one language")]
public int[] SelectedLanguages { get; set; }
[Required(ErrorMessage = "Please select at least one business unit")]
public int[] SelectedBusinessUnits { get; set; }
Now when I do a post from my form using this model and I don't provide any of the values, I only get errormessages for Email, Company and UserName.
I don't get messages for the SelectedLanguages or the SelectedBusinessUnits.
What am i doing wrong?
THis is the view
#using (Html.BeginForm("Register", "Account", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Create a new account.</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.CompanyName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.CompanyName, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.UserName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.UserName, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#foreach (var la in Model.Languages)
{
<input type="checkbox"
name="SelectedLanguages" value="#la.Id" id="#la.Id" />
<label for="#la">#la.Title</label>
}
</div>
<div class="form-group">
#foreach (var bu in Model.BusinessUnits)
{
<input type="checkbox"
name="SelectedBusinessUnits" value="#bu.Id" id="#bu.Id" />
<label for="#bu.Id">#bu.Title</label>
}
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Register" />
</div>
</div>
}
I think you have to go the way of writing a custom validation routine accompanied with a ValidationAttribute. Don't think a simple "out-of-the-box" validator exists for checking if one or more values are present in an array.
Check out this SO post to point you in the right direction.
Basic setup:
public class ArrayContainsValueAttribute: ValidationAttribute
{
// your checks here (pseudo)
if(!array.Any())
return false;
return true;
}
[ArrayContainsValue(ErrorMessage = "Please select at least one business unit")]
public int[] SelectedBusinessUnits { get; set; }

Resources