Reputation: 4855
I am migrating an existing site from WebForms to MVC 5.
I have a Contact Us page that has client-side validation for checking if the fields are completed, etc. However, I am using BotDetect CAPTCHA which has server-side validation to check if the CAPTCHA was completed correctly.
If I enter the correct CAPTCHA, all works as expected -- an email is sent and all the form fields are represented in the email.
If I enter the wrong CAPTCHA, I should be returned to the form, an error message will be displayed for the invalid CAPTCHA but all the other fields should be still filled in.
However, this isn't happening. The form field is lost. I am guessing this is because the Model is getting regenerated. What I haven't figured out is how to get my ActionResult to just abandon doing any actions and leave the form contents in place.
My view:
@using BotDetect.Web.UI.Mvc;
@model Framework.Models.FrameworkModel
@section Styles {
<link href="@BotDetect.Web.CaptchaUrls.Absolute.LayoutStyleSheetUrl" rel="stylesheet" type="text/css" />
}
<h1>@Html.Raw(Model.Page.Heading)</h1>
<div class="main-container">
@if (string.IsNullOrWhiteSpace(ViewBag.Status))
{
@Html.Raw(Model.Page.Body)
<br />
<fieldset id="ContactFields" class="contact-fields">
<ol>
<li>
<label id="FullNameLabel" labelfor="FullName">@Resources.Contact.FullNameLabel</label>
@Html.TextBoxFor(model => model.Contact.FullName, new { @id = "FullName", @Name = "FullName", @class = "standard-textbox", @autocompletetype = "DisplayName", @data_validation_required = Resources.Contact.FullNameValidationErrorMessage})
</li>
<li>
<label id="EmailLabel" labelfor="Email">@Resources.Contact.EmailLabel</label>
@Html.TextBoxFor(model => model.Contact.Email, new { @id = "Email", @Name = "Email", @class = "standard-textbox", @autocompletetype = "Email", @data_validation_required = Resources.Contact.EmailValidationErrorMessage, @data_validation_format = Resources.Contact.EmailValidationErrorMessageFormat })
</li>
<li>
<label id="SubjectLabel" labelfor="Subject">@Resources.Contact.SubjectLabel</label>
@Html.TextBoxFor(model => model.Contact.Subject, new { @id = "Subject", @Name = "Subject", @class = "standard-textbox", @data_validation_required = Resources.Contact.SubjectValidationErrorMessage })
</li>
<li>
<label id="MessageLabel" labelfor="Message">@Resources.Contact.MessageLabel</label>
@Html.TextAreaFor(model => model.Contact.Message, new { @id = "Message", @Name = "Message", @class = "multiline-textbox", @rows = 5, @data_validation_required = Resources.Contact.MessageValidationErrorMessage })
</li>
<li>
<div class="captcha-control">
<br />
@{ MvcCaptcha captcha = Model.CaptchaHelper.GenerateCaptcha(); }
@Html.Captcha(captcha)
<br />
@Html.TextBox("CaptchaCode", "", new { @id = "CaptchaCode", @Name = "CaptchaCode", @class = "captcha-code short-textbox", @data_validation_required = Resources.Captcha.CaptchaValidationErrorMessage })
@Html.ValidationMessage("CaptchaCode")
</div>
<br />
<button id="SendButton" type="submit" class="send-button">@Resources.Contact.SendButton</button>
</ol>
</fieldset>
}
else
{
<span class="alert">@Html.Raw(ViewBag.Status)</span>
}
</div>
@section Scripts {
@Scripts.RenderFormat("<script type=\"text/javascript\" src=\"{0}\" defer=\"defer\"></script>", "~/bundles/scripts/contact")
}
Part of my controller (removed calls to irrelevant actions):
using Framework.App_Code.ViewRendering;
using Framework.Models;
using System.Web.Mvc;
using BotDetect.Web.UI.Mvc;
namespace Framework.Controllers
{
public class PagesController : AsyncController
{
[HttpGet]
[ActionName("Contact")]
public ActionResult Contact()
{
Contact viewRendering = new Contact();
return View(viewRendering.GenerateModel());
}
[HttpPost]
[ActionName("Contact")]
[AllowAnonymous]
[CaptchaValidation("CaptchaCode", "Captcha")]
public ActionResult ContactPost(ContactModel contactModel, bool captchaValid)
{
Contact viewRendering = new Contact();
if (ModelState.IsValid)
{
contactModel.IPAddress = Request.ServerVariables["REMOTE_ADDR"].Trim();
ViewBag.Status = viewRendering.SendMail(contactModel);
}
MvcCaptcha.ResetCaptcha("Captcha");
return View(viewRendering.GenerateModel());
}
}
}
Upvotes: 0
Views: 1100
Reputation: 250922
When you return back to the view in the invalid case, pass the model back to have it re-displayed (i.e. when !ModelState.IsValid
do this...)
return View(contactModel); // this is the one that was submitted
Upvotes: 4