Why is my form validation not working when I have my validation summary in place - asp.net-mvc

I have a #HTML.ValidationSummary within my form which is in a modal (dialog), however, it does not seem check if the form inputs have valid values before the modal closes. I will like the validation summary to be displayed, as shown below, my view model has validation attributes on it's properties.
#using (Html.BeginForm("Index", "Home", null, FormMethod.Post, new { Id = "frmSendEmail", #class = "form-horizontal" }))
{
<div class="modal fade" id="modalSendEmail" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="modalLabel">Email</h4>
</div>
<div class="modal-body">
#Html.ValidationSummary("Oops! Seems like we are missing some information, please provide details for the required field marked with a *", new { #class = "alert alert-danger" })
<div class="form-group">
<label for="txtName" class="col-sm-2 control-label">* Name:</label>
<div class="col-sm-10">
#Html.TextBoxFor(model => model.SenderName, null, new {id = "txtName", #class = "form-control", placeholder = "Name"})
#Html.ValidationMessageFor(model => model.SenderName)
</div>
</div>
<div class="form-group">
<label for="txtEmail" class="col-sm-2 control-label">* Email:</label>
<div class="col-sm-10">
#Html.TextBoxFor(model => model.SenderEmail, null, new { id = "txtEmail", #class = "form-control", placeholder = "Email", type = "email" })
#Html.ValidationMessageFor(model => model.SenderEmail)
</div>
</div>
<div class="form-group">
<label for="txtTelephone" class="col-sm-2 control-label">Telephone:</label>
<div class="col-sm-10">
#Html.TextBox("telephone", null, new { id = "txtTelephone", #class = "form-control", placeholder = "Telephone" })
</div>
</div>
<div class="form-group">
<label for="txtEnquiry" class="col-sm-2 control-label">* Enquiry:</label>
<div class="col-sm-10">
#Html.TextAreaFor(model => model.SenderEnquiry, new { id = "txtEnquiry", #class = "form-control", rows = "5" })
#Html.ValidationMessageFor(model => model.SenderEnquiry)
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-warning" id="btnSendEmail">Send</button>
</div>
</div>
</div>
</div>
}
**Model**
public class Enquiry
{
[Required]
public string SenderName { get; set; }
[Required]
public string SenderEmail { get; set; }
public string SenderTelephone { get; set; }
[Required]
public string SenderEnquiry { get; set; }
}

In the View, change
#Html.ValidationSummary("Oops! Seems like we are missing some information, please provide details for the required field marked with a *", new { #class = "alert alert-danger" })
to
#Html.ValidationSummary(true, "", new { #class = "alert alert-danger" })
In the controller:
public ActionResult Index(Enquiry emailEnquiry)
{
if (ModelState.IsValid)
{
// all done
return ...
}
ModelState.AddModelError("", "Something is invalid.");
return View(emailEnquiry); // don't forget returning with model
}

Related

Not getting the object values or formcollection values

I'm trying to verify user's login verification in MVC. I used a pop-up where it displays two forms as 1 for login and one for Register. I'm unable to get the object values or text box values of user inputs(username & password) even though its hitting the controller.
[HttpPost]
public ActionResult CheckUser(UserInfo obj)
{
int res = udaObj.CheckUser(obj.UserName, obj.Password);
if (res >= 1)
{
return RedirectToAction("Appointment", "Home");
}
else
{
//For testing purpose
return RedirectToAction("Appointment", "Home");
}
}
My cshtml is as follows :
#using (Html.BeginForm("RegisterUser", "Home", FormMethod.Post, new { id = "regForm" }))
{
<div class="tab-pane fade" id="signup">
<fieldset>
<!-- Sign Up Form -->
<!-- Text input-->
<div class="control-group">
<label class="control-label" for="Email">Email:</label>
<div class="controls">
#Html.TextBoxFor(x => x.Email, new { #class = "form-control input-large", #placeholder = "Joek#irawath.com", #required = "" })
</div>
</div>
<!-- Text input-->
<div class="control-group">
<label class="control-label" for="userid">Alias:</label>
<div class="controls">
#Html.TextBoxFor(x => x.UserName, new { #class = "form-control input-large", #placeholder = "Joek#irawath.com", #required = "" })
</div>
</div>
<!-- Password input-->
<div class="control-group">
<label class="control-label" for="password">Password:</label>
<div class="controls">
#Html.TextBoxFor(x => x.Password, new { #class = "form-control input-large", #placeholder = "********", #required = "", #type = "password" })
<em>1-8 Characters</em>
</div>
</div>
<!-- Text input-->
<div class="control-group">
<label class="control-label" for="reenterpassword">Re-Enter Password:</label>
<div class="controls">
<input id="reenterpassword" class="form-control" name="reenterpassword" type="password" placeholder="********" class="input-large" required="">
</div>
</div>
<!-- Button -->
<div class="control-group">
<label class="control-label" for="confirmsignup"></label>
<div class="controls">
<button id="btnconfirmsignup" type="submit" name="signin" class="btn btn-success">Sign Up</button>
#* <button id="btnsignin" type="submit" name="signin" class="btn btn-success">Sign In</button>*#
</div>
</div>
</fieldset>
</div>
}
#using (Html.BeginForm("CheckUser", "Home", FormMethod.Post, new { id = "loginForm" }))
{
<div class="tab-pane fade active in" id="signin">
<fieldset>
<!-- Sign In Form -->
<!-- Text input-->
<div class="control-group">
<label class="control-label" for="userid">Alias:</label>
<div class="controls">
#* <input required="" id="userid" name="userid" type="text" class="form-control" placeholder="JoeSixpack" class="input-medium" required="">*#
#Html.TextBoxFor(x => x.UserName, new { #class = "form-control input-large", #placeholder = "Joek#irawath.com", #required = "" })
</div>
</div>
<!-- Password input-->
<div class="control-group">
<label class="control-label" for="passwordinput">Password:</label>
<div class="controls">
#*<input required="" id="passwordinput" name="passwordinput" class="form-control" type="password" placeholder="********" class="input-medium">*#
#Html.TextBoxFor(x => x.Password, new { #class = "form-control input-large", #placeholder = "********", #required = "", #type = "password" })
</div>
</div>
<!-- Multiple Checkboxes (inline) -->
<div class="control-group">
<label class="control-label" for="rememberme"></label>
<div class="controls">
<label class="checkbox inline" for="rememberme-0">
<input type="checkbox" name="rememberme" id="rememberme-0" value="Remember me" style="margin-left: 0px">
Remember me
</label>
</div>
</div>
<div class="control-group">
<label class="control-label" for="confirmsignup"></label>
<div class="controls">
<button id="btnsignin" type="submit" name="signin" class="btn btn-success">Sign In</button>
#* <button id="btnsignin" type="submit" name="signin" class="btn btn-success">Sign In</button>*#
</div>
</div>
</fieldset>
</div>
}
UserInfo.cs
public class UserInfo
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public bool Gender { get; set; }
public DateTime? Dob { get; set; }
public string PhNumber { get; set; }
public string ImagePath { get; set; }
public DateTime? RegDate { get; set; }
public string Email { get; set; }
}
I do not see anything wrong with your code.
But what I can guess is that your controller does not follow the naming convention of controllers. Your controller name should have a "Controller" suffix.
In your case it should be
public class HomeController : Controller
{
....
}
Let me know if that helps

partial view renders as full view on validation fail

my controller
public ActionResult Create()
{
return PartialView();
}
//
// POST: /User/Create
[HttpPost]
public ActionResult Create(User user)
{
if (ModelState.IsValid)
{
db.User.Add(user);
db.SaveChanges();
TempData["Message"] = "Data has been saved successfully!";
return RedirectToAction("Index");
}
return View(user);
}
my view
<div class="row">
#Html.ActionLink("Create New", "Create", null, new { #class = "modal-with-form btn btn-default", href = "#modalForm" })
<!-- Modal Form -->
<div id="modalForm" class="modal-block modal-block-primary mfp-hide">
#Html.Partial("Create", new jQuery_CRUD.DAL.User())
</div>
</div>
my partial view
#using (Ajax.BeginForm("Create", "User", null, new AjaxOptions { UpdateTargetId = "modalForm", InsertionMode = InsertionMode.Replace }))
{
<section class="panel">
<header class="panel-heading">
<h2 class="panel-title">Create</h2>
</header>
<div class="panel-body">
<div class="form-group mt-lg">
#Html.LabelFor(model => model.Name, new { #class = "col-sm-3 control-label" })
<div class="col-sm-9">
#Html.TextBoxFor(model => model.Name, new { name = "name", #class = "form-control", placeholder = "Type your name..."})
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Address, new { #class = "col-sm-3 control-label" })
<div class="col-sm-9">
#Html.TextBoxFor(model => model.Address, new { name = "address", #class = "form-control", placeholder = "Type your Address..." })
#Html.ValidationMessageFor(model => model.Address)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ContactNo, new { #class = "col-sm-3 control-label" })
<div class="col-sm-9">
#Html.TextBoxFor(model => model.ContactNo, new { name = "contactno", #class = "form-control", placeholder = "Type your Contact No..." })
#Html.ValidationMessageFor(model => model.ContactNo)
</div>
</div>
</div>
<footer class="panel-footer">
<div class="row">
<div class="col-md-12 text-right">
<input type="submit" value="Create" class="btn btn-primary" />
<button class="btn btn-default modal-dismiss" id="btnCancel">Cancel</button>
</div>
</div>
</footer>
</section>
}
when i click the button , modal pops up,upon validation fail on post action, the view returns to full view. where could be the problem????..
i'm new to mvc help me with this..
Add in the beginning of your partial view
{
Layout = null;
}
And return partialView in Validation Error not View
[HttpPost]
public ActionResult Create(User user)
{
if (ModelState.IsValid)
{
db.User.Add(user);
db.SaveChanges();
TempData["Message"] = "Data has been saved successfully!";
return RedirectToAction("Index");
}
return PartialView(user);
}

How to Login/Register from bootstrap modal without redirecting?

I'm using the default web application mvc project, and i'm trying to login/register from modal:
So i made a new model containing the models for login and register
public class LogInRegisterViewModel
{
public LoginViewModel login { get; set; }
public RegisterViewModel register { get; set; }
}
then in my layout page i provide that model along with the partial view for the login/register:
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
#if (User.Identity.IsAuthenticated)
{
<li>#Html.ActionLink("MyUploads", "Index", "Tutorials")</li>
<li>#Html.ActionLink("Upload", "Create", "Tutorials")</li>
}
</ul>
#Html.Partial("_LoginPartial",model) #*model = new LogInRegisterViewModel()*#
</div>
the html code for the modal is in my _LoginPartial view(maybe this is my mistake?), and the login and register forms(copied from the Account controller):
<div class="modal fade" id="myModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content mc">
<div class="modal-body">
<div class="row">
<div class="col-md-6 login-modal">
<section id="loginForm">
#using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Use a local account to log in.</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<div>
<h5 class="user-name login-labels"><i class="fa fa-user" aria-hidden="true"></i> User Name</h5>
</div>
<div class="col-md-8 login-input">
#Html.TextBoxFor(m => m.login.UserName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.login.UserName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<h5 class="user-password login-labels"><i class="fa fa-lock" aria-hidden="true"></i> Password</h5>
<div class="col-md-8 login-input">
#Html.PasswordFor(m => m.login.Password, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.login.Password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-10 login-btn">
<input type="submit" value="Log in" class="btn btn-primary" />
</div>
</div>
#* Enable this once you have account confirmation enabled for password reset functionality
<p>
#Html.ActionLink("Forgot your password?", "ForgotPassword")
</p>*#
}
</section>
</div>
<div class="col-md-6">
#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.register.FirstName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.register.FirstName, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.register.LastName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.register.LastName, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.register.ProfileAvatar, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.register.ProfileAvatar, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.register.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.register.Email, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.register.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.register.Password, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.register.ConfirmPassword, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.register.ConfirmPassword, new { #class = "form-control" })
</div>
</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>
}
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>
and now if you click on log in button without providing username and password, the page will redirect me to Account/Login, same thing for the register.
So how can i fix this so the validation errors popup on the modal and not to be redirected to Account controller?
Thanks in advance for any help.
Ensure first of all you have included the scripts to actually validate the form:
<script src=".../Scripts/jquery.validate.js"></script>
<script src=".../Scripts/jquery.validate.unobtrusive.js"></script>
For client side validation include jquery validation bundle in your view or layout.
#section scripts
{
#Scripts.Render("~/bundles/jqueryval")
}
Also, you can use Ajax.BeginForm() helper instead of Html.BeginForm to implement your registration and login form.

mvc No data in ActionResult method after submit

I have an Index page on which there is a section to write a project name and select from a dropdownlist a project type.
Below that I have a submit button that directs to the ActionResult method Create in the Projects controller.
Code:
[UPDATE]
index.cshtml:
#using reqcoll.ViewModels
#model myViewModel
#{
ViewBag.Title = "ReqColl - project";
}
#* First half *#
#using (Html.BeginForm("CreateProject", "Projects"))
{
#Html.AntiForgeryToken()
<div class="top-spacing col-md-12 col-lg-12 col-sm-12">
#RenderTopHalf(Model.modelProject)
</div>
}
#* Second half *#
#using (Html.BeginForm("CreateRequirement", "Projects"))
{
#Html.AntiForgeryToken()
<div class="form-group" id="pnSecondHalf">
#* Requirements list *#
<div class=" col-md-6 col-lg-6 col-sm-12">
#RenderBottomLeftHalf(Model.modelRequirement)
</div>
#* New/Edit requirements panel *#
<div class="col-md-6 col-lg-6 col-sm-12">
#RenderBottomRightHalf(Model.modelRequirement)
</div>
</div>
}
#* ================================================================================= ============= *#
#* Helpers *#
#helper RenderTopHalf(reqcoll.Models.Project project)
{
<div class=" well">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row">
#Html.LabelFor(model => project.projectName, htmlAttributes: new { #class = "control-label col-md-2 col-lg-2 col-sm-12" })
<div class="col-md-10 col-lg-10 col-sm-12">
#Html.TextBoxFor(model => project.projectName, htmlAttributes: new { #class = "ProjectNameInput" })
#Html.ValidationMessageFor(model => project.projectName)
</div>
</div>
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row row-spacing">
#Html.LabelFor(model => project.projectType, htmlAttributes: new { #class = "control-label col-md-2 col-lg-2 col-sm-12" })
<div class="col-md-10 col-lg-10 col-sm-12">
#Html.DropDownListFor(model => project.projectType, new SelectList(
new List<Object>{
new { value = 0 , text = "...Select..." },
new { value = 1 , text = "Windows application" },
new { value = 2 , text = "Web application" },
new { value = 3 , text = "Device application"}
},
"value",
"text",
project.projectType), htmlAttributes: new { #class = "DropDownList" })
#Html.ValidationMessageFor(model => project.projectType)
</div>
<input type="hidden" value="" id="hdProjectID" />
</div>
<div class="row top-spacing col-md-offset-5 col-sm-offset-5">
<div id="pnCreate" class=" col-sm-4 col-md-4 col-lg-4">
<input type="submit" class="btn btn-default" value="Create" />
</div>
<div id="pnEdit" class=" col-sm-4 col-md-4 col-lg-4">
<input type="submit" class="btn btn-default" value="Edit" />
|
<input type="submit" class="btn btn-default" value="Delete" />
</div>
</div>
</div>
}
#helper RenderBottomLeftHalf(reqcoll.Models.Requirement requirement)
{
<div class=" well">
<table class="table">
<tr>
<th>
#if (Model.modelProject.Requirements != null)
{
var m = Model.modelProject;
if (m.Requirements.Count > 0)
{
#Html.DisplayNameFor(model => model.modelProject.Requirements[0].shortDesc)
}
}
else
{
<label class="label label-primary col-sm-12 col-md-6 col-lg-6">No requirements available</label>
}
</th>
<th></th>
</tr>
#if (Model.modelProject.Requirements != null)
{
var m = Model.modelProject;
if (m.Requirements.Count > 0)
{
foreach (var item in Model.modelProject.Requirements)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.shortDesc)
</td>
<td>
#* buttons here*#
#*#Html.ActionLink("E", "Edit", new { id = item.requirementID }) |
#Html.ActionLink("D", "Delete", new { id = item.requirementID })*#
</td>
</tr>
}
}
}
</table>
</div>
}
#helper RenderBottomRightHalf(reqcoll.Models.Requirement requirement)
{
<div class=" well">
#Html.ValidationSummary(true)
<div class="row">
#Html.LabelFor(model => requirement.shortDesc, htmlAttributes: new { #class = "control-label col-md-4 col-lg-4 col-sm-12" })
<div class="col-md-8 col-lg-8 col-sm-12">
#Html.TextBoxFor(model => requirement.shortDesc, htmlAttributes: new { #class = "RequirementShortDesc" })
#Html.ValidationMessageFor(model => requirement.shortDesc)
</div>
</div>
#Html.ValidationSummary(true)
<div class="row row-spacing">
#Html.LabelFor(model => requirement.longDesc, htmlAttributes: new { #class = "control-label col-md-4 col-lg-4 col-sm-12" })
<div class="col-md-8 col-lg-8 col-sm-12 RequirementLongDesc">
#Html.EditorFor(model => requirement.longDesc)
#Html.ValidationMessageFor(model => requirement.longDesc)
</div>
</div>
#Html.ValidationSummary(true)
<div class="row row-spacing">
#Html.LabelFor(model => requirement.priorityCode, htmlAttributes: new { #class = "control-label col-md-4 col-lg-4 col-sm-12" })
<div class="col-md-8 col-lg-8 col-sm-12">
#foreach (var value in Enum.GetValues(requirement.priorityCode.GetType()))
{
<div class="control-label col-sm-5 col-md-5 col-lg-5">
#Html.RadioButtonFor(m => requirement.priorityCode, value)
#Html.Label(value.ToString())
</div>
}
#Html.ValidationMessageFor(model => requirement.priorityCode)
</div>
</div>
<input type="hidden" value="" id="hdRequirementID" />
<div class="row top-spacing col-md-offset-5 col-sm-offset-5">
<div id="pnReqCreate" class=" col-sm-12 col-md-6 col-lg-6">
#* submit button here *#
#*#Html.ActionLink("Add", "Add", "Requirement", new { #class = "btn btn-default btnSize" })*#
</div>
<div id="pnReqEdit" class=" col-sm-12 col-md-6 col-lg-6">
#* submit buttons here *#
#*#Html.ActionLink("Edit", "Edit", "Requirement", new { #class = "btn btn-default btnSize" })
#Html.ActionLink("Delete", "Delete", "Requirement", new { #class = "btn btn-default btnSize" })*#
</div>
</div>
</div>
}
#section Scripts {
<script>
$(function () {
var pID = $('#hdProjectID').val();
if (pID != null) {
if (pID.length > 0) {
$('#pnEdit').show();
$('#pnCreate').hide();
$('#pnSecondHalf').show();
} else {
$('#pnEdit').hide();
$('#pnCreate').show();
$('#pnSecondHalf').hide();
}
} else {
$('#pnEdit').hide();
$('#pnCreate').show();
$('#pnSecondHalf').hide();
}
var rID = $('#hdRequirementID').val();
if (rID != null) {
if (rID.length > 0) {
$('#pnReqEdit').show();
$('#pnReqCreate').hide();
} else {
$('#pnReqEdit').hide();
$('#pnReqCreate').show();
}
} else {
$('#pnReqEdit').hide();
$('#pnReqCreate').show();
}
});
</script>
#Scripts.Render("~/bundles/jqueryval")
}
ViewModel:
using reqcoll.Models;
namespace reqcoll.ViewModels
{
public class myViewModel
{
public Project modelProject;
public Requirement modelRequirement;
}
}
Controller:
using System.Web.Mvc;
using reqcoll.Models;
using reqcoll.ViewModels;
namespace reqcoll.Controllers
{
public class ProjectsController : Controller
{
private myContext db = new myContext();
// GET: Projects
public ActionResult Index()
{
// allow more than one model to be used in the view
var vm = new myViewModel()
{
modelProject = new Project() { projectName = "test", projectType = 1 },
modelRequirement = new Requirement() { requirementID = -1 },
};
return View(vm);
}
[HttpPost]
[ValidateAntiForgeryToken]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateProject(myViewModel vm)
{
if (vm != null)
{
var ab = Request.Form;
// key 1: __RequestVerificationToken
// key 2: project.projectName
// key 3: project.projectType
if (ModelState.IsValid)
{
Project project = vm.modelProject;
// db.Project.Add(project.Item1);
// db.SaveChanges();
// return RedirectToAction("Index");
}
}
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
[ORIGINAL]
#using (Html.BeginForm("Create", "Projects"))
{
#Html.AntiForgeryToken()
<div class="top-spacing col-md-12 col-lg-12 col-sm-12">
<div class=" well">
#Html.ValidationSummary(true)
<div class="row">
#Html.LabelFor(model => model.Item1.projectName, htmlAttributes: new { #class = "control-label col-md-2 col-lg-2 col-sm-12" })
<div class="col-md-10 col-lg-10 col-sm-12">
#Html.TextBoxFor(model => model.Item1.projectName, htmlAttributes: new { #class = "ProjectNameInput" })
#Html.ValidationMessageFor(model => model.Item1.projectName)
</div>
</div>
#Html.ValidationSummary(true)
<div class="row row-spacing">
#Html.LabelFor(model => model.Item1.projectType, htmlAttributes: new { #class = "control-label col-md-2 col-lg-2 col-sm-12" })
<div class="col-md-10 col-lg-10 col-sm-12">
#Html.DropDownListFor(model => model.Item1.projectType, new SelectList(
new List<Object>{
new { value = 0 , text = "...Select..." },
new { value = 1 , text = "Windows application" },
new { value = 2 , text = "Web application" },
new { value = 3 , text = "Device application"}
},
"value",
"text",
0), htmlAttributes: new { #class = "DropDownList" })
#Html.ValidationMessageFor(model => model.Item1.projectType)
</div>
<input type="hidden" value="" id="hdProjectID" />
</div>
<div class="row top-spacing col-md-offset-5 col-sm-offset-5">
<div id="pnCreate" class=" col-sm-4 col-md-4 col-lg-4">
<input type="submit" class="btn btn-default" value="Create" />
</div>
<div id="pnEdit" class=" col-sm-4 col-md-4 col-lg-4">
<input type="submit" class="btn btn-default" value="Edit" />
|
<input type="submit" class="btn btn-default" value="Delete" />
</div>
</div>
</div>
</div>
}
ProjectsController:
private myContext db = new myContext();
// GET: Projects
public ActionResult Index()
{
// allow more than one model to be used in the view
return View(new Tuple<Project, Requirement, Priority>(new Project(), new Requirement(), new Priority()));
}
[HttpPost]
[ValidateAntiForgeryToken]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Include = "projectName,projectType")] Project project)
{
if (ModelState.IsValid)
{
db.Project.Add(project);
db.SaveChanges();
return RedirectToAction("Index");
}
return RedirectToAction("Index");
}
So when the submit button is clicked, the ActionResult Create is called, but the ModelState is not valid and does not have the information enterd by the user.
What am I doing wrong?
Your model is looking like complex object as you are using model.Item1.projectName and model.Item1.projectType, but in action method you are trying to get values directly which is wrong.
[Updated code]
With the new code posted, this quick correction to your model will allow it to bind correctly from your view:
namespace reqcoll.ViewModels
{
public class myViewModel
{
public Project project;
public Requirement requirement;
}
}
[Original]
Despite the fact of using a Tuple<> type instead of defining a class that would encapsulate the data to pass to the view. You can still achieve what you want by creating a helper in your view.
#helper RenderMyProject(Project project) {
...
#Html.TextBoxFor(x=> project.projectType)
...
}
Then, you will call this helper
#RenderMyProject(model.Item1)
Whats the difference?
The name of the input will change. Instead of posting [Item1.projectType] Inside the response object to your controller, it will look like [project.projectType] which will be mapped to your project parameter automatically.
Found the problem.
I added {get; set;} in the myViewModel to both the models and then it worked.
so:
using reqcoll.Models;
namespace reqcoll.ViewModels
{
public class myViewModel
{
public Project Project { get; set; }
public Requirement Requirement { get; set; }
}
}

ASP.Net MVC 5 Form in a Twitter Bootstrap Modal - Return to modal if user does not enter correct field information

I have a contact form in a Twitter Bootstrap Modal and if the user happens to not enter a name or email address and hits submit I want to return to the Modal instead of just closing the Modal. Also if the form is valid I would like to let the user know that an we will be contacting them shortly in the same modal. Is this possible?
Here is my controler.
[HttpPost]
public ActionResult Index(Contact model)
{
ViewBag.IsValid = false;
ViewBag.CaptchaError = "";
RecaptchaVerificationHelper recaptchaHelper = this.GetRecaptchaVerificationHelper();
if (String.IsNullOrEmpty(recaptchaHelper.Response))
{
ViewBag.CaptchaError = "The Captcha cannot be empty";
return View();
}
RecaptchaVerificationResult recaptchaResult = recaptchaHelper.VerifyRecaptchaResponse();
if (recaptchaResult != RecaptchaVerificationResult.Success)
{
ViewBag.CaptchaError = "The Captcha was incorrect";
return View();
}
if (ModelState.IsValid)
{
SendSupportEmail(model);
ViewBag.isValid = true;
}
return View();
}
Here is my view with the Modal
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content col-md-12">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Contact Us</h4>
</div>
<center>
<div class="modal-body">
#using (Html.BeginForm())
{
if ((bool)ViewBag.IsValid)
{
}
else
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<div class="form-group">
<div class="col-md-12">
#Html.TextBoxFor(model => model.Name, new { #class = "form-control", placeholder = "Name" })
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
<div class="col-md-12">
#Html.TextBoxFor(model => model.Phone, new { #class = "form-control", placeholder = "Phone" })
#Html.ValidationMessageFor(model => model.Phone)
</div>
</div>
<div class="form-group">
<div class="col-md-12">
#Html.TextBoxFor(model => model.Email, new { #class = "form-control", placeholder = "E-Mail Address" })
#Html.ValidationMessageFor(model => model.Email)
</div>
</div>
<div class="form-group">
<div class="col-md-12">
#Html.TextAreaFor(model => model.Comments, new { #class = "form-control", height = "40", placeholder = "Comments" })
#Html.ValidationMessageFor(model => model.Comments)
</div>
</div>
<div class="form-group">
#if (!string.IsNullOrEmpty(ViewBag.CaptchaError))
{
<span class="field-validation-error">#ViewBag.CaptchaError</span>
}
#Html.Recaptcha(theme: Recaptcha.Web.RecaptchaTheme.Clean)
</div>
<div class="form-group">
<div class="col-md-12">
<input type="submit" id="submit" value="Submit" class="btn btn-default btn-lg btn-primary col-sm-12" />
</div>
</div>
</div>
}
}
</div>
</center>
</div>
</div>
I have searched everywhere and was unable to find a solution.
Don't have enough rep to comment - hence the answer. I reckon the easiest way to do this would be to use ajax. User jquery validation plugin to validate user input on submit click. This way, the validation messages can be displayed on the modal itself and the page doesn't have to be refreshed.
On successful validation, the form can be posted to your controller action. You can send a success message as part of your response and display it as a popup or a notification using notifyjs or your own code.

Resources