I am trying to popup a form so user fill it then I save that record. If data is wrong I want to inform the user just a classic validation issue.
I am trying this code but when model is not valid it show the mistake but literally it only returns what is in the partial view, it is not loading my layout nor my modal form, all I get is a white page just with my partial.
so what am I doing wrong?
This is my modal form:
And after validation all I get is this:
Code:
Model:
public class Car
{
public int Id { get; set; }
[Required]
[StringLength(50, MinimumLength = 6)]
public string Model { get; set; }
public string Brand { get; set; }
public string Year { get; set; }
public string Color { get; set; }
}
View:
<!-- 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">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Add Car</h4>
</div>
<div class="modal-body">
#Html.Partial("CreatePartialView",new Car())
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="savechanges">Save changes</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
my partial:
#model ControliBootstrap.Models.Car
#using (Ajax.BeginForm("ModalAdd", "Cars",new AjaxOptions()
{
UpdateTargetId = "mymodalform"
}))
{
<div class="form-horizontal" id="mymodalform">
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Model, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Model)
#Html.ValidationMessageFor(model => model.Model)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Brand, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Brand)
#Html.ValidationMessageFor(model => model.Brand)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Year, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Year)
#Html.ValidationMessageFor(model => model.Year)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Color, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Color)
#Html.ValidationMessageFor(model => model.Color)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
and finlly my controler:
public ActionResult ModalAdd(Car car)
{
if (ModelState.IsValid)
{
db.Cars.Add(car);
db.SaveChanges();
return RedirectToAction("Index");
}
return PartialView("CreatePartialView",car);
}
Don't forget to include jQuery Unobtrusive AJAX - it's the library that makes normal HTML forms have some AJAX capabilities.
Related
your text
I added validation to my ASP.NET MVC .NET FRAMEOWRK project and get this error:
your text
Unable to cast object of type 'System.Int32' to type 'System.String'.
My project connect to data base with one table.
my code:
Customer.cs:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ConnectToDB
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public partial class Customers : IValidatableObject
{
[StringLength(1000, ErrorMessage = "Queue number must be no more than 1000 digits")]
[Required(ErrorMessage = "Queue number is required")]
[DataType(DataType.Text)]
[DisplayName("Queue number")]
public int queueNumber { get; set; }
[StringLength(30, ErrorMessage = "First name must be no more tha 1000 letters")]
[RegularExpression("^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$")] // RegEx: Used to validate a person name
[Required(ErrorMessage = "First name is required")]
[DisplayName("First name")]
[DataType(DataType.Text)]
public string firstName { get; set; }
[StringLength(30, ErrorMessage = "Last name must be no more tha 1000 letters")]
[RegularExpression("^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$")] // RegEx: Used to validate a person name
[Required(ErrorMessage = "Last name is required")]
[DisplayName("Last name")]
[DataType(DataType.Text)]
public string lastName { get; set; }
[Required(ErrorMessage = "Time customer enter is required")]
[DisplayName("Time customer enter")]
[DataType(DataType.Time)]
public Nullable<System.TimeSpan> timeCusEnter { get; set; }
// Validation for queue number using IValidatableObject interface:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> errors = new List<ValidationResult>();
if (queueNumber < 0)
{
errors.Add(new ValidationResult("Queue number can not be negative.", new List<string> { "queueNumber" }));
}
return errors;
}
}
}
addCustomer.cshtml:
#model ConnectToDB.Customers
#{
ViewBag.Title = "addCustomer";
}
<link rel="stylesheet" href="~/CSS/addCusDesign.css" />
<link rel="stylesheet" href="~/CSS/Local.css" />
<body>
#*Menu:*#
<div class="navBar">
<span class="navItem">
#Html.ActionLink("Dequeue to the queue", "addCustomer")
</span>
<span class="navItem">
#Html.ActionLink("Customers list", "customersList")
</span>
</div>
<h2>Enqueue</h2>
<span id="secondTitle">Fill in the following details, then press the button and enter the queue.<br>Have a good day :)</span>
<br />
<br />
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Customers</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.queueNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.queueNumber, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.queueNumber)
</div>
</div>
<br />
<div class="form-group">
#Html.LabelFor(model => model.firstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.firstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.firstName)
</div>
</div>
<br />
<div class="form-group">
#Html.LabelFor(model => model.lastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.lastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.lastName)
</div>
</div>
<br />
<div class="form-group">
#Html.LabelFor(model => model.timeCusEnter, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.timeCusEnter, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.timeCusEnter)
</div>
</div>
<br />
<br />
#Html.ValidationSummary(true, "Add customer was unsuccessful. Please coorect the following errors: ")
#*Dequeue customer to the queue input: *#
<div class="form-group">
<div class="GetInTheQueue">
<input type="submit" value="GET IN THE QUEUE" class="btn btn-default" />
</div>
</div>
</div>
}
<br />
<br />
#*Carusel in boostrap: *#
<!-- #region Carusel -->
<div id="carouselExampleFade" class="carousel slide carousel-fade" data-bs-ride="carousel">
<div class="carousel-inner">
<div class="carousel-item active">
<img src="~/Images/image1.jpeg" class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="~/Images/image2.png" class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="~/Images/Image3.jpeg" class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="~/Images/Image4.jpeg" class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="~/Images/Image5.jpeg" class="d-block w-100" alt="...">
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleFade" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselExampleFade" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
<!-- #endregion -->
<br />
<br />
#*Images: *#
<!-- #region Images -->
<div class="images">
<img width="200" height="200" src="~/Images/image1.jpeg" alt="Queue image1" />
<img width="200" height="200" src="~/Images/image2.png" alt="Queue image2" />
<img width="200" height="200" src="~/Images/Image3.jpeg" alt="Queue image3" />
<img width="200" height="200" src="~/Images/Image4.jpeg" alt="Queue image4" />
<img width="200" height="200" src="~/Images/Image5.jpeg" alt="Queue image5" />
</div>
<!-- #endregion -->
</body>
Would appreciate help
The validation work for me yesterday, but today not working.
I implemented google invisible recaptcha on my login form but when i submit the form by pressing Enter key, it does not send any response token. However, when i clicked button whose type submit, it validates successfully.
How can I get response with both press enter and click button?
C# - MVC application used as technologhy. #Model.GoogleRecaptchaSiteKey property is filled on my application.
Here is my login form html
#using (Html.BeginForm("Login", "Account", new { ReturnUrl = Request.QueryString["ReturnUrl"] }, FormMethod.Post, new { #class = "login-form", id = "login-form" }))
{
<div class="login-form">
<h3 class="form-title">Login Form</h3>
<div class="form-group">
<!--ie8, ie9 does not support html5 placeholder, so we just show field title for that-->
<label class="control-label visible-ie8 visible-ie9">Kullanıcı Adı</label>
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-user"></i>
</div>
#Html.TextBoxFor(f => f.UserName, new { title = "Kullanıcı adınızı giriniz.", #class = "form-control placeholder-no-fix", #placeholder = "Kullanıcı Adı", #value = "", #autofocus = "true" })
</div>
#Html.ValidationMessageFor(m => m.UserName)
</div>
<div class="form-group">
<label class="control-label visible-ie8 visible-ie9">password</label>
<div class="input-group" id="show_hide_password">
<div class="input-group-addon">
<i class="fa fa-lock"></i>
</div>
#Html.TextBoxFor(f => f.Password, new { #title = "password.", #type = "password", #class = "form-control placeholder-no-fix", #placeholder = "password", #value = "" })
<div class="input-group-addon">
<i class="fa fa-eye-slash" id="i_show_hide_password" aria-hidden="true"></i>
</div>
</div>
#Html.ValidationMessageFor(m => m.Password)
</div>
<div class="form-actions">
#Html.AntiForgeryToken()
<input id="login" type="submit" class="btn green pull-right g-recaptcha" data-size="invisible" data-sitekey="#Model.GoogleRecaptchaSiteKey" data-callback="onSubmit" value="Login" />
#Html.ValidationMessage("reCaptcha")
<br />
</div>
</div>
}
Script is below here
function onSubmit(token) {
document.getElementById("login-form").submit();
}
In my MVC application I have simple model for project:
public class Project
{
public int Id { get; set; }
[Required]
[MinLength(5, ErrorMessage = "Project name must have at leat 5 characters")]
public string ProjectName { get; set; }
[Required]
[MinLength(10, ErrorMessage = "Project description name must have at leat 10 characters")]
public string ProjectDescription { get; set; }
public ICollection<BugTrackerUser> Users { get; set; }
public Project()
{
Users = new List<BugTrackerUser>();
}
}
On the index page I have button that triggers bootstrap modal window. As a button, modal itself located in Index.chtml, but form that belongs to this model located in partial view _addProjectPartialView:
<form method="post" id="projectForm">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="ProjectName">Project Name</label>
<input asp-for="ProjectName" class="form-control" />
<span asp-validation-for="ProjectName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ProjectDescription">Project Description</label>
<input asp-for="ProjectDescription" class="form-control" />
<span asp-validation-for="ProjectDescription" class="text-danger"></span>
</div>
In HomeController I have this post method for adding new project:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult AddProject(Project project)
{
if (ModelState.IsValid)
{
_repository.AddProject(project);
return RedirectToAction("Index", "Home");
}
return PartialView("_addProjectPartialView", project);
}
Logic of adding new project works fine, and I have all references that i need, jquery, jquery-validation and jquery-validation-unobtrusive, but I have problems with validation. Validation errors doesn't displays in my modal window. What can I try to solve this problem? I already read a bunch of tutorials, related questions etc, but it seems to me that there is no problems with code. I only have doubts with my return statement in AddProject method, should I return something else?
I solved this problem by removing partial view. Form that I Have in partial view and modal window I placed in Index.cshtml, also instead of asp.net tag helpers I use Html.BeginForm, and it works fine. Here is my modal:
<div class="modal fade" id="addProjectModal" tabindex="-1" aria-labelledby="addProjectModallLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
#using (Html.BeginForm("AddProject", "Home", FormMethod.Post))
{
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Project Information</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(p => p.Id)
<div class="form-group">
#Html.LabelFor(p => p.ProjectName, htmlAttributes: new { #class = "control-label col-3" })
<div class="col-9">
#Html.TextBoxFor(p => p.ProjectName, new { #class = "form-control" })
#Html.ValidationMessageFor(p => p.ProjectName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(p => p.ProjectDescription, htmlAttributes: new { #class = "control-label col-3" })
<div class="col-9">
#Html.TextBoxFor(p => p.ProjectDescription, new { #class = "form-control" })
#Html.ValidationMessageFor(p => p.ProjectDescription, "", new { #class = "text-danger" })
</div>
</div>
#*<partial name="_addProjectPartialView" />*#
</div>
<div class="modal-footer">
<div>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary" id="btnSave">Save</button>
</div>
</div>
}
</div>
</div>
I also using ajax post method to add projects and render list of projects async on the client side:
<script type="text/javascript">$(document).ready(function () {
$('#btnSave').click(function () {
var projectData = $('#projectForm').serialize();
$.ajax({
type: "POST",
url: "/Home/AddProject",
data: projectData,
success: function () {
window.location.href = "/Home/Index";
}
})
})
})
$('#closeButton').click(function () {
$('#addProjectModal').modal('hide');
})</script>
But I still want to understand how to solve this problem, because using partial views have some benefits
I think the problem here is , when you triggers the modal that modal doesn't have the references to (validator unobtrusive).
So try manually register this where you triggers the modal like this
$.validator.unobtrusive.parse("#idForModal");
I have a partial view within a modal popup. Client side field validation works, such as required fields. But there are some server side validations that don't present themselves whilst keeping the modal popup open.
For example, I create a new 'teacher band' and the controller checks for a duplicate band. When I press submit, the page actually browses to the partial view and presents the error in the validationsumary, rather than keeping it within the modal.
Controller -
public async Task<IActionResult> Add()
{
CreateTeacherBandViewModel model = new CreateTeacherBandViewModel();
return PartialView(model);
}
[HttpPost]
public async Task<IActionResult> Add(CreateTeacherBandViewModel model)
{
if (ModelState.IsValid)
{
if (await _teacherBandService.BandExists(model.BandName))
{
ModelState.AddModelError("", "A band with that name already exists");
return PartialView(model);
}
else
{
await _teacherBandService.Add(model);
return RedirectToAction("Index", "TeacherBand", null);
}
}
else
{
return PartialView();
}
}
Partial View
#model Models.CreateTeacherBandViewModel
<script src="~/assets/js/plugins/pickers/color/spectrum.js"></script>
<script src="~/assets/js/demo_pages/picker_color.js"></script>
#using (Html.BeginForm("Add", "TeacherBand", null))
{
<!-- Iconified modal -->
<div id="modal_addband" class="modal fade" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header bg-primary text-white">
<h5 class="modal-title"><i class="icon-user-plus mr-2"></i> Add New Band</h5>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Name</label>
#Html.TextBoxFor(model => model.BandName, new { #class = "form-control"})
#Html.ValidationMessageFor(model => model.BandName)
</div>
<h6 class="font-weight-semibold">Charge Rates</h6>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label>AM</label>
#Html.TextBoxFor(model => model.DefaultChargeRateAM, new { #class = "form-control"})
#Html.ValidationMessageFor(model => model.DefaultChargeRateAM)
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>PM</label>
#Html.TextBoxFor(model => model.DefaultChargeRatePM, new { #class = "form-control"})
#Html.ValidationMessageFor(model => model.DefaultChargeRatePM)
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>Daily</label>
#Html.TextBoxFor(model => model.DefaultChargeRateDaily, new { #class = "form-control"})
#Html.ValidationMessageFor(model => model.DefaultChargeRateDaily)
</div>
</div>
</div>
<h6 class="font-weight-semibold">Pay Rates</h6>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label>AM</label>
#Html.TextBoxFor(model => model.DefaultPayRateAM, new { #class = "form-control"})
#Html.ValidationMessageFor(model => model.DefaultPayRateAM)
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>PM</label>
#Html.TextBoxFor(model => model.DefaultPayRatePM, new { #class = "form-control"})
#Html.ValidationMessageFor(model => model.DefaultPayRatePM)
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>Daily</label>
#Html.TextBoxFor(model => model.DefaultPayRateDaily, new { #class = "form-control"})
#Html.ValidationMessageFor(model => model.DefaultPayRateDaily)
</div>
</div>
</div>
<hr />
<div class="form-group">
<label>Colour</label>
#Html.TextBoxFor(model => model.Colour, new { #class = "form-control"})
#Html.ValidationMessageFor(model => model.Colour)
</div>
#Html.ValidationSummary()
<div class="modal-footer">
<button type="button" class="btn btn-link" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Create Band</button>
</div>
</div>
</div>
</div>
<!-- /iconified modal -->
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js">
</script>
}
Finally, the Index page that renders the partial view
#Html.Partial("Add", new CreateTeacherBandViewModel())
I am trying to use the Ajax.BeginForm to post a message back to the server and I need to give a name to the form, i.e. use the parameter htmlAttributes. For that I am using the following signature:
#using (Ajax.BeginForm("SendEmail", "Contacts", null, new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "sendMessageArea" }, new { Name = "sendEmail" }))
This code doestn't work, it updates the whole page and the controller is expecting an object as a paramenter:
public ActionResult SendEmail(Contacts contacts)
Here is the view:
<div class="row">
<div class="large-12 columns" >
#using (Ajax.BeginForm("SendEmail", "Contacts", null, new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "sendMessageArea" }, new { Name = "sendEmail" }))
{
<fieldset class="form-group">
<legend>Leave a message</legend>
<div class="panel">
<div class="row">
<div class="large-offset-2 large-8 columns">
<div class="row">
<div class="large-2 columns">
<div class="form-group">
#Html.LabelFor(model => model.Name, new { #class = "control-label" })
</div>
</div>
<div class="large-8 columns">
#Html.TextBox("Name", Model.Name, new { placeholder = "Your name..." })
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="large-2 columns">
</div>
</div>
<div class="row">
<div class="large-2 columns">
<div class="form-group">
#Html.LabelFor(model => model.EMail, new { #class = "control-label" })
</div>
</div>
<div class="large-8 columns">
<div class="form-group">
#Html.TextBox("EMail", Model.EMail, new { placeholder = "Your email..." })
#Html.ValidationMessageFor(model => model.EMail)
</div>
</div>
<div class="large-2 columns">
</div>
</div>
<div class="row">
<div class="large-2 columns">
<div class="form-group">
#Html.LabelFor(model => model.Message, new { #class = "control-label" })
</div>
</div>
<div class="large-8 columns">
#Html.TextArea("Message", Model.Message, new { placeholder = "Your message here...", #class = "comment-control", id = "message" })
#Html.ValidationMessageFor(model => model.Message)
</div>
<div class="large-2 columns">
</div>
</div>
<div class="row">
<div class="large-offset-8 large-3 columns">
<input type='submit' style='position:absolute;top:0;left:-9999px;width:1px;height:1px' />
<a class='submit-button' href="javascript:sendEmail.submit()">
<span class='submit-button-inner'>Submit</span>
</a>
</div>
</div>
</div>
<div class="large-2 columns">
</div>
</div>
</div>
</fieldset>
}
</div>
and the partial view:
<span class="success label">#Resources.Contacts.Index.SuccessSendMessage</span>
I think the problem should be related with the routeValues parameter because if I use a simple example without the htmlAttributes and routeValues it works well.
Any guess?