Trying to implement data validation and error handling on a simple contact form. When I add the check for ModelState.IsValid
I'm in a chicken and egg situation. I have looked at other similar questions and am just not getting this. Moving from Web Forms to MVC and struggling. Trying to toggle HTML elements based on what's happening - success/error message, etc. RIght now, not even the validation is working.
Right now I'm just trying to get server-side validation working but would welcome advice on how to add client-side validation also; for example, is it necessary to use jQuery for this or is there something baked in?
View:
@using (Html.BeginForm("Contact", "Home", FormMethod.Post))
{
if (ViewData["Error"] == null && ViewData["Success"] == null)
{
<h3>Send us an email</h3>
Html.ValidationSummary(true);
<div class="form-group">
<label class="sr-only" for="contact-email">Email</label>
<input type="text" name="email" placeholder="Email..."
class="contact-email" id="contact-email">
</div>
<div class="form-group">
<label class="sr-only" for="contact-subject">Subject</label>
<input type="text" name="subject" placeholder="Subject..."
class="contact-subject" id="contact-subject">
</div>
<div class="form-group">
<label class="sr-only" for="contact-message">Message</label>
<textarea name="message" placeholder="Message..."
class="contact-message" id="contact-message"></textarea>
</div>
<button type="submit" class="btn">Send it</button>
<button type="reset" class="btn">Reset</button>
}
else if (ViewData["Error"] == null && ViewData["Success"] != null)
{
<h4>We will get back to you as soon as possible!</h4>
<p>
Thank you for getting in touch with us. If you do not hear
from us within 24 hours, that means we couldn't contact you
at the email provided. In that case, please feel free to call
us at (xxx) xxx-xxxx at any time.
</p>
}
else if (ViewData["Error"] != null)
{
<h3>Oops!</h3>
<p>
We apologize. We seem to be having some problems.
</p>
<p>
Please come back and try again later. Alternatively,
call us anytime at (xxx) xxx-xxxx.
</p>
}
}
Model:
public class ContactModel
{
[Required(ErrorMessage = "Email address is required")]
[EmailAddress(ErrorMessage = "Invalid Email Address")]
public string Email { get; set; }
[Required(ErrorMessage = "Subject is required")]
public string Subject { get; set; }
[Required(ErrorMessage = "Message is required")]
public string Message { get; set; }
}
Controller:
[HttpPost]
public ActionResult Contact(ContactModel contactModel)
{
if (ModelState.IsValid)
{
try
{
MailMessage message = new MailMessage();
using (var smtp = new SmtpClient("mail.mydomain.com"))
{
// Standard mail code here
ViewData["Success"] = "Success";
}
}
catch (Exception)
{
ViewData["Error"]
= "Something went wrong - please try again later.";
return View("Error");
}
}
return View();
}
Error View:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Error</title>
</head>
<body>
<hgroup>
<h1>Error.</h1>
<h2>An error occurred while processing your request.</h2>
</hgroup>
</body>
</html>
UPDATE - 05/09/2017
Per Guruprasad's answer, if ModelState.IsValid
evaluates to false, then no validation error messages are being reported on the form.
Note I had to change the AddModelError
signature to not use the "Extension ex" parameter:ModelState.AddModelError("Error", "Server side error occurred");
as I do not want system errors being reported to users.
Note also that at this point I am only trying out validation on the server side (have yet to work through client-side validation).
I have updated the Contact.cshtml view as follows as no model errors were being displayed - I have included the Bootstrap .has-error
and .help-block
CSS rules for the validation errors:
@using (Html.BeginForm("Contact", "Home", FormMethod.Post))
{
<h3>Send us an email</h3>
Html.ValidationSummary(true);
<div class="form-group has-error">
<label class="sr-only" for="contact-email">Email</label>
@Html.TextBoxFor(m => m.Email, new { type = "text", name = "email",
placeholder = "Email..", @class = "contact-email" })
@Html.ValidationMessageFor(model => model.Email, String.Empty,
new { @class="help-block" })
</div>
<div class="form-group has-error">
<label class="sr-only" for="contact-subject">Subject</label>
@Html.TextBoxFor(m => m.Subject, new { type = "text",
name = "subject",
placeholder = "Subject..", @class = "contact-subject" })
@Html.ValidationMessageFor(model => model.Subject, String.Empty,
new { @class = "help-block" })
</div>
<div class="form-group has-error">
<label class="sr-only" for="contact-message">Message</label>
@Html.TextAreaFor(m => m.Message, new { name = "message",
placeholder = "Message..", @class = "contact-message" })
@Html.ValidationMessageFor(model => model.Message, String.Empty,
new { @class = "help-block" })
</div>
<button type="submit" class="btn">Send it</button>
<button type="reset" class="btn">Reset</button>
if (ViewData["Success"] != null)
{
<h4>We will get back to you as soon as possible!</h4>
<p>
Thank you for getting in touch with us. If you do not hear
from us within 24 hours, that means we couldn't contact you
at the email provided. In that case, please feel free to
call us at (xxx) xxx-xxxx at any time.
</p>
}
}