Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Petar Petrov 1 post 71 karma points
    Mar 29, 2022 @ 21:33
    Petar Petrov
    0

    Form does not keep the submitted data when validation fails

    I have the following problem:

    simple contact form. If I omit for example a required field, then the form displays errors, but the data that was filled does not appear.

    I would greatly appreciate if someone can explain to me why the submitted that is not displayed back.

    I would expect that CurrentUmbracoPage(); just resubmits the POST method. instead it redirects to the RenderForm. Is this normal? Given that flow, how could I even expect the submitted model given I have a line that creates new one:

                ContactUsViewModel model = this.contactUsViewModelFactory.CreateContactUsViewModel();
    

    I am missing something - either the flow should not be returning to the RenderForm or somehow the old data from the post should be passed to it.

    Here is the code:

        [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
        public ActionResult RenderForm(int id, string recaptchaKey)
        {
            ContactUsViewModel model = this.contactUsViewModelFactory.CreateContactUsViewModel();
            model.Id = id;
            model.RecaptchaKey = recaptchaKey;
            return this.PartialView("~/Views/Partials/Forms/_ContactUsForm.cshtml", model);
        }
    
        [HttpPost]
        [ValidateInput(false)]
        public async Task<ActionResult> ContactUs(ContactUsViewModel contactUsModel)
        {
            if (!await this.recaptchaService.Validate(this.Request))
            {
                this.ModelState.AddModelError("RecaptchaKey", "Recaptcha error");
            }
    
            if (this.ModelState.IsValid)
            {
                // send email
    
                return this.RedirectToUmbracoPage(contactUsModel.Id);
            }
    
            return this.CurrentUmbracoPage();
        }
    

    The viewmodel is pretty standard I believe:

    public class ContactUsViewModel
    {
        public int Id { get; set; }
    
        public string RecaptchaKey { get; set; }
    
        [Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(FormTranslations))]
        public string Name { get; set; }
    
        [Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(FormTranslations))]
        [EmailAddress(ErrorMessageResourceName = "EmailError", ErrorMessageResourceType = typeof(FormTranslations))]
        public string Email { get; set; }
    
        [Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(FormTranslations))]
        public string Message { get; set; }
    }
    

    The partial _ContactUsForm.cshtml:

    @inherits UmbracoViewPage<ACS.Web.Models.ContactUs.ContactUsViewModel>
    @using ACS.Web.Translations;
    @{
    this.Layout = null;
    
    string currentCulture = (string)ViewBag.CurrentCulture;
    string inactiveCulture = (string)ViewBag.InactiveCulture;
    
    }
    
    @using (Html.BeginUmbracoForm("ContactUs", "Contact", new { }, new { id = "contact-us-form" }, FormMethod.Post))
    
    {
    <div class="row">
        <div class="col-md-12">
            <div class="ac-contact-us-form-title mx-auto"><h1 @if (currentCulture.Equals("bg-BG")) { <text> style="line-height: 1;" </text> }>@FormTranslations.ContactFormTitle</h1></div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-8 col-lg-5 mx-auto">
            <div class="ac-contact-us-form-fields">
                <div>@Html.HiddenFor(x => x.Id)</div>
    
                <div class="ac-contact-us-form-name form-group">
                    @Html.TextBoxFor(x => x.Name, new { @class = "form-control", placeholder = FormTranslations.Name })
                    @Html.ValidationMessageFor(x => x.Name)
                </div>
    
                <div class="ac-contact-us-form-emial form-group">
                    @Html.TextBoxFor(x => x.Email, new { @class = "form-control", placeholder = FormTranslations.Email })
                    @Html.ValidationMessageFor(x => x.Email)
                </div>
    
                <div class="ac-contact-us-form-message form-group">
                    @Html.TextAreaFor(x => x.Message, new { @class = "form-control", @rows = 10, placeholder = FormTranslations.Message })
                    @Html.ValidationMessageFor(x => x.Message)
                </div>
    
                <div class="btn-wrapper" id="contact-submit-btn" type="submit" style="float: right">
                    <svg height="50" width="265" xmlns="http://www.w3.org/2000/svg">
                        <rect id="shape1" height="50" width="265" />
                        <rect id="shape" height="50" width="265" />
                        <div id="text">
                            <a href="#">
                                <span class="spot">@FormTranslations.Send</span>
                            </a>
                        </div>
                    </svg>
                </div>
                <div class="text-center loader-container hidden">
                    <img src="@Url.Content("~/Media/img/loading_spinner.gif")" alt="Alternate Text" />
                </div>
            </div>
        </div>
    </div>
    
    <div style="position: relative; z-index: 500;">
        <div>@Html.ValidationMessageFor(x => x.RecaptchaKey)</div>
        <div id='recaptcha' class="g-recaptcha"
             data-sitekey="@Model.RecaptchaKey"
             data-callback="onSubmit"
             data-size="invisible"></div>
    </div>
    }
    

    And the view itself has just slightly been modified to use the recaptcha:

        <script>
        function onSubmit(token) {
            $(".btn-wrapper").addClass("hidden");
            $(".loader-container").removeClass("hidden");
            $("#contact-us-form").submit();
        }
    
        function validate(e) {
            e.preventDefault();
    
            grecaptcha.execute();
        }
    
        function onload() {
            var element = document.getElementById('contact-submit-btn');
            element.onclick = validate;
        }
    </script>
     @{ Html.RenderAction("RenderForm", "Contact", new { id = successPageId, recaptchaKey = RecaptchaSiteKey }); }
    
Please Sign in or register to post replies

Write your reply to:

Draft