Copied to clipboard

Flag this post as spam?

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


  • Richard Green 6 posts 88 karma points
    Nov 25, 2016 @ 17:50
    Richard Green
    0

    Surface Controller Not Invoking on Submit

    Hi all.

    Sometime ago, I created a surface controller, model and partial for a contact form. Nothing complicated, just a simple form that uses SendGrid to deliver an email on submission.

    Somehow, I've broken the hook between the page and the surface controller such that hitting Submit triggers a HTTP POST but then nothing actually happens and I can't figure out why.

    Can anyone offer any suggestions as to what stupid thing I have done? FWIW, I'm running Umbraco version 7.4.3.

    Surface Controller

    using System.Web.Mvc;
    using ArcibleWebsite.Models;
    using System.Net.Mail;
    using SendGrid.Helpers.Mail;
    using Newtonsoft.Json;
    
    namespace ArcibleWebsite.Controllers
    {
    public class ContactSurfaceController :                                   Umbraco.Web.Mvc.SurfaceController
    {
        [HttpPost]
        public ActionResult CreateContactMessage(ContactViewModel contactFormData)
        {
            if (!ModelState.IsValid)
            {
                return CurrentUmbracoPage();
            }
    
            ViewBag.Contact = contactFormData;
    
            // Global variables for building the messages
                SENDGRID STUFF HAPPENS HERE
            // return CurrentUmbracoPage();
            return RedirectToCurrentUmbracoPage;
        }
      }
    }
    

    Model

    using System.ComponentModel.DataAnnotations;
    
    namespace ArcibleWebsite.Models
    {
        public class ContactViewModel
        {
        [Required]
        [StringLength(50, MinimumLength = 3)]
        [Display(Name = "First Name")]
        public string FirstName { get; set; }
    
        [Required]
        [StringLength(50, MinimumLength = 3)]
        [Display(Name = "Last Name")]
        public string LastName { get; set; }
    
        [Required]
        [EmailAddress]
        [DataType(DataType.EmailAddress)]
        [Display(Name = "Email Address")]
        public string EmailAddress { get; set; }
    
        [StringLength(20, MinimumLength = 10)]
        [Display(Name = "Contact Number")]
        public string ContactNumber { get; set; }
    
        [Required]
        [StringLength(2500, MinimumLength = 10)]
        [DataType(DataType.MultilineText)]
        public string Message { get; set; }
        }
    }
    

    Partial

    @model ArcibleWebsite.Models.ContactViewModel
    
    @using (Html.BeginUmbracoForm<ArcibleWebsite.Controllers.ContactSurfaceController>("CreateContactMessage"))
    
    {
    if (!ViewData.ModelState.IsValid)
    {
        <div class="row">
            <div class="col-xs-12 col-sm-6 col-md-8">
                @Html.ValidationSummary(true, "Sorry, but there is a problem with the data you've entered. Please check the data you entered and try again.")
            </div>
        </div>
    }
    
            FORM STUFF HAPPENS HERE
    
            <input type="submit" class="btn btn-pink" value="Submit your Question" />
    
        </form>
        }
    
  • Aditya 24 posts 128 karma points
    Nov 26, 2016 @ 08:06
    Aditya
    0

    Hmm, looks OK at first glance. Have you tried using Visual Studio's debugger to step through your code? That might help show where it loses the call.

  • Nik 1599 posts 7179 karma points MVP 6x c-trib
    Nov 26, 2016 @ 11:45
    Nik
    0

    My first thought, is check the rendered HTML and network traffic. It might be doing a GET instead of a POST hence never getting to your controller.

    Generally I find it safer to specify the form is a post.

    Also, if the controller code isn't complete, make sure you don't have a GET and a POST called the same thing (on the same controller), I find in Umbraco they conflict and it causes issues.

    Nik

  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    Nov 26, 2016 @ 12:57
    Dennis Adolfi
    0

    Hi Richard.

    Looking at your controller, it looks like it's missing the inheritance for SurfaceController. So at the moment it's just a regular class and not routed as a controller, which is why your code compiles fine but the forms cannot post to your actionresult.

    I'm guessing since it used to work it might be something you've accidentally removed somehow.

    Change it to:

    public class ContactSurfaceController : SurfaceController

    Hope this solves the problem.

    Have a great weekend!

  • Richard Green 6 posts 88 karma points
    Nov 26, 2016 @ 16:17
    Richard Green
    0

    Hi Dennis.

    The reference is there, it's just got a little mangled by the code posted. Here's just that singular line:

    public class ContactSurfaceController : Umbraco.Web.Mvc.SurfaceController
    

    Is the fact that I'm having to reference SurfaceController using it's full name and the lack of a using statement for Umbraco.Web.Mvc a problem?

  • Marc Goodson 2144 posts 14347 karma points MVP 8x c-trib
    Nov 26, 2016 @ 17:46
    Marc Goodson
    0

    Hi Richard

    I just cut and paste what you have into the fanoe starter kit, and it all sort of works...

    you shouldn't need the closing

    </form>
    

    tag though inside your @using (Html.BeginUmbracoForm bit (that will be taken care of by the BeginUmbracoForm itself...

    having that on it's own breaks parsing of the partial razor file...

    is that the issue ?

    If that's not the issue then it could be the way in which you are presenting the form fields, which we can't see:

    I just did:

    @Html.EditorFor(f=>f.FirstName)
    <br  />
    @Html.EditorFor(f=>f.ContactNumber)
    <br  />
    @Html.EditorFor(f=>f.EmailAddress)
    <br />
    @Html.EditorFor(f=>f.LastName)
    <br />
    @Html.EditorFor(f=>f.Message)
    

    so if you have something different to that ? maybe it's not binding to the properties of the model... ?

    Finally it does have some strict validation on the model, eg more than 10 characters for some fields etc, so make sure your validation is showing, I turned on the validation summary

    @Html.ValidationSummary(false, "Sorry, ....

    to see the messages, but you probably have Html.ValidationFor within your form...

    Anyway hope that helps from a sanity perspective.

    regards

    Marc

  • Dan Diplo 1554 posts 6205 karma points MVP 5x c-trib
    Nov 26, 2016 @ 17:59
    Dan Diplo
    100

    It looks like you have an extra closing </form> tag in there. When using Html.BeginUmbracoForm you shouldn't add any other form tags, otherwise the form won't submit. So check that.

  • Piotr Bach 15 posts 129 karma points c-trib
    Nov 26, 2016 @ 18:09
    Piotr Bach
    0

    Hi.
    Check the form-generated output html:

    <form action="/Contact" class="email-form" enctype="multipart/form-data" method="post" role="form" novalidate="novalidate"><input name="__RequestVerificationToken" type="hidden" value="HJP27AVfpIJgJf3p9NHsArq8k1Jts01vzwEyr3f5dKizkA42zRBGlAUqqv3by_pUlr1vUDq5cS4jWe3Sn_yBLbA1e_VVNuawYX9BdIt1DAA1">    <h2>Send a quick message</h2>
    <div class="form-group">
        <label for="Email">Your Email *</label>
        <input class="form-control" data-val="true" data-val-email="The Email field is not a valid e-mail address." data-val-required="The Email field is required." id="Email" name="Email" type="text" value="">
        <span class="field-validation-valid" data-valmsg-for="Email" data-valmsg-replace="true"></span>
    </div>
    <div class="form-group">
        <label for="Message">Your Message *</label>
        <textarea class="form-control" cols="20" data-val="true" data-val-required="The Message field is required." id="Message" name="Message" rows="2"></textarea>
        <span class="field-validation-valid" data-valmsg-for="Message" data-valmsg-replace="true"></span>
    </div>
    <div class="overflow-hidden">
        <input class="btn btn-success pull-right" type="submit" value="Send">
    </div>
    

    Then check if you're really hitting controller method with post (console debugger in browser + vs debug)

    This code is working for me:

    @{ Html.RenderPartial("_Contact", new ContactFormViewModel()); }
    

    _Contact.cshtml

    @model Site.Web.ViewModel.ContactFormViewModel      
    @using Site.Web.Controllers;    
    @using System.Web.Mvc.Html
    @using ClientDependency.Core.Mvc
    @using Umbraco.Web
    @using Umbraco.Web.Models
    @using Umbraco.Web.Controllers
    
    @{
        Html.EnableClientValidation();
        Html.EnableUnobtrusiveJavaScript();
        Html.RequiresJs("/umbraco_client/ui/jquery.js");
        Html.RequiresJs("/umbraco_client/Application/JQuery/jquery.validate.min.js");
        Html.RequiresJs("/umbraco_client/Application/JQuery/jquery.validate.unobtrusive.min.js");
    }
    
    @Html.RenderJsHere()
    
            @if (TempData["Status"] == null) {
    using (Html.BeginUmbracoForm<ContactController>("Submit", new object { }, new { @class = "email-form", @role = "form" }))
    {
        @Html.AntiForgeryToken()
    
        <h2>Send a quick message</h2>
    
        <div class="form-group">
            @Html.LabelFor(m => m.Email, "Your Email *")
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Email)
        </div>
    
        <div class="form-group">
            @Html.LabelFor(m => m.Message, "Your Message *")
            @Html.TextAreaFor(m => m.Message, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Message)
        </div>
    
        <div class="overflow-hidden">
            <input class="btn btn-success pull-right" type="submit" value="Send" />
        </div>
    }
            }
    @if (TempData["Status"] != null)
    {
        <div class="alert alert-success" role="alert">@TempData["Status"] <a href="/Home" class="alert-link">go to home page</a> </div>
    }
    

    ContactController.cs

     public class ContactController : SurfaceController
        {
            [HttpPost]
            [ValidateAntiForgeryToken]
            public ActionResult Submit(ContactFormViewModel model)
            {
                if (!ModelState.IsValid)
                {
                    return CurrentUmbracoPage();
                }
                //some logic
                TempData["Status"] = "Message was send";
                return CurrentUmbracoPage();
            }
        }
    

    Good luck

  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    Nov 26, 2016 @ 18:37
    Dennis Adolfi
    0

    Ah i see! Thought I found the obvious answer! :)

    Maybe, not sure though. You could try to reference Umbraco.Web.Mvc with the using statement and see if that works, but I'm skeptical..

    As Nik mentioned, could you paste in the rendered HTML and maybe we can see what actually gets rendered.

  • Richard Green 6 posts 88 karma points
    Dec 03, 2016 @ 00:30
    Richard Green
    1

    Thanks everyone for the replies. I updated the code, adding the reference to Umbraco.Web.Mvc so that SurfaceController didn't need to be fully qualified and I updated the form tags in the partial.

    Everything is now working so I'm not exactly sure which of those two actually resolved it but I suspect it was the form tags.

    Many thanks to all.

Please Sign in or register to post replies

Write your reply to:

Draft