Copied to clipboard

Flag this post as spam?

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


  • MatsStam 50 posts 195 karma points
    Jan 27, 2015 @ 10:30
    MatsStam
    0

    Umbraco Forms and Ajax

    Hi there!

    When I used Contour, I managed to change the form to use an ajaxform, instead of an html form.

    But heres the issue. With the new Umbraco Forms the code looks like this:

    @using (Html.BeginUmbracoForm<Umbraco.Forms.Web.Controllers.UmbracoFormsController>("HandleForm"))

    And when I made a feeble attempt to use an Ajaxform instead, it didnt work. So is it possible to use an AjaxCall for this? I'm sure there must be a way to make an ajaxcall so you don't have to make a postback. Could someone please explain how? =)


    Cheers,

    Mats

  • Jesper Ordrup 975 posts 1411 karma points MVP
    Feb 12, 2015 @ 14:05
    Jesper Ordrup
    1

    Would like to know this too.

    best
    Jesper 

  • Ismail Mayat 4285 posts 9244 karma points MVP 2x admin c-trib
    Feb 12, 2015 @ 14:20
    Ismail Mayat
    0

    Did you add jquery ajax libs I have done this and it works

  • Jesper Ordrup 975 posts 1411 karma points MVP
    Feb 12, 2015 @ 14:38
    Jesper Ordrup
    1

    yes sir :)

    Ive added:

     <scriptsrc="/js/jquery.js"></script>
     <scriptsrc="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.13.1/jquery.validate.min.js"></script>
    <scriptsrc="http://ajax.aspnetcdn.com/ajax/mvc/5.1/jquery.validate.unobtrusive.min.js"></script>
    @Umbraco.RenderMacro("umbracoforms.RenderScripts")

    but form is submittet with full reload. But if thats all it takes then it might be something else that interferes. 

    Best
    Jesper 

  • Jesper Ordrup 975 posts 1411 karma points MVP
    Feb 12, 2015 @ 14:57
    Jesper Ordrup
    1

    @ismail .. and you did no change to the form rendering? So it still using this? :

    @using (Html.BeginUmbracoForm<Umbraco.Forms.Web.Controllers.UmbracoFormsController>("HandleForm"))

     

  • Ismail Mayat 4285 posts 9244 karma points MVP 2x admin c-trib
    Feb 12, 2015 @ 15:45
    Ismail Mayat
    0

    Jesper,

    Ah yes my bad, so I had todo 

      @Html.Action("RenderReviewSearchForm", "AdminReviewSurface")

    becuase if i do not then i get errors something about missing page, the BeginUmbracoForm puts in some hidden fields route values think it uses those to give you a page? The other issue i had was in my surfacecontroller i was using dictionary items and they would be blank as it would lose the thread culture so i had to do 

            protected void SetCultureForAjax()
            {
                //we lose culture and dictionary wont get labels therefore set it on the thread
                string code = _umbracoService.GetCultureCode();
                //Get the culture info of the language code
                CultureInfo culture = CultureInfo.CreateSpecificCulture(code);
                Thread.CurrentThread.CurrentCulture = culture;
                Thread.CurrentThread.CurrentUICulture = culture;
            }

    also from what i can remember none of my models with ajax calls were inheriting from rendermodel

    Regards

    Ismail

  • Jesper Ordrup 975 posts 1411 karma points MVP
    Feb 12, 2015 @ 15:47
    Jesper Ordrup
    0

    Hi Ismail,

    Thanks a bunch. I'll give it a go. 

    best
    Jesper 

  • Jesper Ordrup 975 posts 1411 karma points MVP
    Feb 12, 2015 @ 17:16
    Jesper Ordrup
    0

    It didnt seem to work for me. I might be doing something wrong but I have no time. 

    I'll wait for an official ajax support for Umbraco Forms and do my custom ones until then .. https://gist.github.com/jesperordrup/8cae76e368f65b7a1346

    best
    Jesper 

  • marcelh 170 posts 470 karma points
    Aug 25, 2015 @ 17:29
    marcelh
    0

    Anyone sorted this already?

    1) I added references to the scripts

    <script type="text/javascript" src="/scripts/jquery.validate.min.js"></script>
    <script type="text/javascript" src="/scripts/jquery.validate.bootstrap.min.js"></script>
    <script type="text/javascript" src="/scripts/jquery.validate.unobtrusive.min.js"></script>
    <script type="text/javascript" src="/scripts/jquery.unobtrusive-ajax.min.js"></script>

    2) I changed the Form.cshtml from

    @using (Html.BeginUmbracoForm<Umbraco.Forms.Web.Controllers.UmbracoFormsController>("HandleForm"))
    

    to

    @using (Html.BeginForm("HandleForm", "UmbracoForms", FormMethod.Post, new { enctype = "multipart/form-data", role = "form" }))
    

    But no luck. When the form is submitted, the button gets disabled and nothing happens... When I review the HTML, I see the correct URL is rendered:

    <form role="form" method="post" enctype="multipart/form-data" action="/umbraco/Surface/UmbracoForms/HandleForm">...</form>
    
  • MatsStam 50 posts 195 karma points
    Aug 28, 2015 @ 09:25
    MatsStam
    0

    I never got it to work, and I didnt have time to keep trying, but if I remember correctly it had to do with some code that was compiled into the Umbraco Forms DLL's. Sorry, I never got it to work atleast, and the same for Jesper it seems.

    Too bad that it was real easy to do with Countour :(

  • Jesper Ordrup 975 posts 1411 karma points MVP
    Aug 28, 2015 @ 09:31
    Jesper Ordrup
    0

    I didnt get it to work . Time didnt allow me to work much with it so I went with rolling my own.

    Crossing fingers for future Contour version supporting Ajax and some docs that shows it.

    /Jesper

  • marcelh 170 posts 470 karma points
    Aug 28, 2015 @ 10:35
    marcelh
    0

    Time is always the issue, same here.

    I got close, but in the AJAX call the UmbracoContext was lost, and that is needed inside the controller. Think it is the same as MatsStam experienced.

    I got even closer this week by posting to the page's url using an Ajax request (see also Tom's post in this thread https://our.umbraco.org/forum/developers/api-questions/48945-Current-Page-doesnt-exist-in-SurfaceController-With-Ajax-Form- ). But the response was about to render the form again which caused some issues, and I had to alter the Form.cshtml that much that I left it for what it was. Also because of not knowing the side effects of posting back to the same page.

    At that point, I ran out of time and decided to go the old-fashioned-postback-way.

  • Marko Jovanov 10 posts 114 karma points
    Nov 05, 2015 @ 14:29
    Marko Jovanov
    0

    Has anyone managed to get close to solving this issue?

    I have added the same changes to custom 'Form.cshtml' file as marcelh mentioned:

    Form tag:

    @using (Html.BeginForm("HandleForm", "UmbracoForms", FormMethod.Post, new { enctype = "multipart/form-data", role = "form" }))
    

    and I get the correct form tag rendered:

    <form action="/umbraco/Surface/UmbracoForms/HandleForm" enctype="multipart/form-data" method="post" role="form" novalidate="novalidate"> 
    

    Script references:

    <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.11/jquery-ui.min.js"></script>
    
    
    
    
    
    <script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js"></script>
    
    
    
    
    
    <script src="http://ajax.aspnetcdn.com/ajax/mvc/5.2.3/jquery.validate.unobtrusive.min.js"></script>
    
    
    
    
    
    <script src="http://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.unobtrusive-ajax.min.js"></script>
    

    Although I do not get the same error, but rather the exception when hitting the submit button: http://prntscr.com/8zbjsg.

    Previously I have tried to implement the 'Ajax.BeginForm' method, but the website was reporting 404 to the action method: /umbraco/Surface/UmbracoForms/HandleForm.

    I have also posted the question on StackOverflow.

  • Nicholas Westby 1893 posts 6332 karma points c-trib
    Nov 07, 2015 @ 22:59
    Nicholas Westby
    0

    I haven't tried to get AJAX working with Umbraco Forms (yet), but reading through this thread I haven't seen anybody try to inject the "ufprt" hidden field that Umbraco injects when you call BeginUmbracoForm(): https://github.com/umbraco/Umbraco-CMS/blob/775e63148d9c9e0ba4ffad3b697f6f2e2ca9f28b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs#L351

    The two key lines in that file are these:

    _encryptedString = UmbracoHelper.CreateEncryptedRouteString(controllerName, controllerAction, area, additionalRouteVals);
    _viewContext.Writer.Write("<input name='ufprt' type='hidden' value='" + _encryptedString + "' />");
    

    That creates an encrypted value containing route information, then outputs that as a hidden input field, "ufprt". That is used on postback to locate the action method and controller (rather than the typical MVC technique of using the URL to do that locating). If you use BeingForm rather than BeginUmbracoForm, you will be missing that value, so I imagine you'd have to add it back yourself.

    If you generate that in your form, and pass it along in your AJAX request, you may have better luck.

  • Thomas 126 posts 280 karma points
    Jan 23, 2016 @ 18:56
    Thomas
    0

    Hi,

    I have done all the above, i follow your comments for the extra hidden field but still not working.

    Any solution?

  • Nicholas Westby 1893 posts 6332 karma points c-trib
    Jan 23, 2016 @ 19:52
    Nicholas Westby
    0

    Could you post the code that you are using and clarify what you mean by "not working"? When you say "not working", that could mean a number of things:

    • A request isn't being sent to the server.
    • The server isn't responding to the request.
    • The server is responding to the request in a way you aren't expecting.
    • The server seems to be responding as you expect, but when you update the page based on the response you are seeing something different than what you'd expect to see.
    • Any number of other possible ways things can go wrong.

    More info will be needed before we can give specific advise on what may be going wrong in your scenario.

  • Thomas 126 posts 280 karma points
    Jan 23, 2016 @ 21:02
    Thomas
    0
    1. all the jquery scripts and the umbracoForms scripts are loaded in master page.
    2. i change the @using (Html.BeginUmbracoForm<Umbraco.Forms.Web.Controllers.UmbracoFormsController>("HandleForm")) to @using (Ajax.BeginForm("UmbracoForms", "HandleForm", new { area = "Surface" }, new AjaxOptions { HttpMethod = "POST", OnSuccess = "Success()", OnFailure = "Failure()", InsertionMode = InsertionMode.Replace, UpdateTargetId = "contour_form_" + Model.FormName.Replace(" ", "") }, new { enctype = "multipart/form-data", role = "form" }))
    3. inside the form object i enter the extra hidden field you mention as follows var _encryptedString = EncryptedRoute.GetEncryptedRoute("UmbracoForms", "HandleForm", "Surface", null); <input type="hidden" name="ufprt" value="@_encryptedString" />
    4. i create the EncryptedRoute.GetEncrytedRoute public static funtion copied from the UmbracoHelper.CreateEncryptedRouteString because this function in UmbracoHelper is internal and not available from razor syntax.

    So everything was ok, when i press the submit button i am getting failure from the ajax post.

  • Nicholas Westby 1893 posts 6332 karma points c-trib
    Jan 23, 2016 @ 21:34
    Nicholas Westby
    0

    You should continue to use Html.BeginUmbracoForm (i.e., do not use Ajax.BeginForm). That will atuomatically add the ufprt hidden field for you (I only explained how it was doing it to help others understand what was going on). I repeat, you do not need to generate the ufprt field for yourself.

    Once you have the form rendered, I'd use jQuery to intercept the submit event for the form and create an AJAX request using $.ajax (also cancelling the initial full postback). When you do the $.ajax, be sure to include the hidden ufprt field in the request (along with the rest of the form fields).

    I'm not sure what Umbraco Forms will give you as a result. My guess is it will give you the entire markup for the page, but you'll just have to try it out to see. It may be clever enough to detect an AJAX submission and return some sort of partial result.

  • Thomas 126 posts 280 karma points
    Jan 24, 2016 @ 00:01
    Thomas
    2

    Nicholas that was great idea. I follow what you said and now everything it works fine. So as you said i am using the Html.BeginUmbracoForm but i change it a bit like

    Html.BeginUmbracoForm<Umbraco.Forms.Web.Controllers.UmbracoFormsController>("HandleForm", null, new { id= Model.FormId }, FormMethod.Post)
    

    in order to give an id. I am doing that because in the jquery script i have to be sure that i will intercept the submition only for this form.

    Then i wrote the following script:

    <script type="text/javascript">
    $(document).ready(function () {
        //Intercept Submit button in order to make ajax call instead of a postback
        $('#@Model.FormId').preventDoubleSubmission();
    })
    
    // jQuery plugin to prevent double submission of forms
    jQuery.fn.preventDoubleSubmission = function () {
        $(this).on('submit', function (e) {
            e.preventDefault();
    
            var $form = $(this);
    
            if ($form.data('submitted') === true) {
                // Previously submitted - don't submit again
            } else {
                if ($form.valid()) {
                    // Mark it so that the next submit can be ignored
                    $form.data('submitted', true);
    
                    // Make ajax call form submission
                    $.ajax({
                        url: $form.attr('action'),
                        type: 'POST',
                        cache: false,
                        data: $form.serialize(),
                        success: function (result) {
                            console.log(result);
                            //ToDo: Add code to replace html inside the div that holds the form with a Success message.
                        }
                    });
                }
            }
        });
    
        // Keep chainability
        return this;
    };
    

    Thank you for the idea.

  • Steve Bentley 21 posts 64 karma points
    Apr 06, 2016 @ 16:13
    Steve Bentley
    0

    Hi Thomas,

    Does this actually work?

    When I try this approach I get a "request must be made in the context of an Umbraco request" error.

    Thanks

    Steve

  • Thomas 126 posts 280 karma points
    Apr 07, 2016 @ 11:39
    Thomas
    0

    Yes it does. I am already using it in live environment.

  • Mark 116 posts 248 karma points
    May 16, 2016 @ 10:07
    Mark
    0

    Hi Thomas,

    I am using your technique and at first glance all appears to be working great, form entries are saved etc. so have been using in a live environment.

    However, requirements have since changed and now I have had to add a workflow to my ajax enabled form.. But.. on debugging, it would appear that my workflow is not being hit when the form is submitted via ajax. Should I be doing something special to get it being called? The workflow isn't the issue as it's being called by other forms submitted in the usual way.

    Any thoughts would be appreciated, unfortunately this is a change that needs to go live today, never figured it would be an issue when I said it should be fine to go live :-/

    Cheers..

    Mark

  • Marty Patches 6 posts 85 karma points
    Jul 22, 2016 @ 11:27
    Marty Patches
    0

    Hi Mark,

    Have you found a solution for using workflows and Ajax posting?

    In version 4.2.1 it worked great but after I updated to 4.3.2 it stopped working. It just doesn't hit the workflow

  • Steve Bentley 21 posts 64 karma points
    Apr 07, 2016 @ 11:45
    Steve Bentley
    0

    Thanks Thomas,

    I got it working this morning. Turns out I was posting to the wrong URL.

    Thanks

    Steve

  • Amir Khan 962 posts 1916 karma points
    Sep 08, 2016 @ 18:53
    Amir Khan
    0

    Any idea why the method Thomas recommends would break form conditions?

  • Jeroen van Tongeren 1 post 71 karma points
    Aug 28, 2018 @ 13:09
    Jeroen van Tongeren
    0

    Not sure how relevent this is since this is an old topic, but I've sold it this way. I created a controller which inherited from the UmbracoFormsController and a ActionResult to handle the ajax calls:

    public class UmbracoFormsAjaxController : UmbracoFormsController
    {
        private IPublishedContent _basePage;
    
        protected override IPublishedContent CurrentPage {
            get
            {
                return _basePage;
            }
        }
    
        [HttpPost, ValidateInput(false), ValidateFormsAntiForgeryToken, ValidateCaptcha]
        public ActionResult HandleFormAjax(FormViewModel model, bool captchaIsValid, int currentPageId)
        {
            // Set base page
            var helper = new UmbracoHelper(UmbracoContext.Current);
            _basePage = helper.TypedContent(currentPageId);
    
            // Handle form
            HandleForm(model, captchaIsValid);
    
            // Return rendered view only
            return RenderForm(model.FormId, model.RecordId, model.Theme, true);
        }
    }
    

    The HandleForm method handles the validation and record creation, and the RenderForm the rendering of your UmbracoForms form.

    The reason I overloaded CurrentPage is because in an AJAX call, which usually is to a different url than the current page url, Umbraco can't find the actual current page, so I set it in my overloaded HandleForm method using a hidden field in my form. I also added a hidden field for the theme, since by default it's not added to the form and it's null.

    So basically my form looks like:

    @using (Ajax.BeginForm("HandleFormAjax", "UmbracoFormsAjax", new AjaxOptions
        {
            InsertionMode = InsertionMode.ReplaceWith,
            UpdateTargetId = "umbraco_form_" + Model.FormClientId,
            AllowCache = false
        }))
        {
            @* Standard form meta data *@
    
            @Html.AntiForgeryToken()
    
            @Html.HiddenFor(x => Model.FormId)
            @Html.HiddenFor(x => Model.FormName)
            @Html.HiddenFor(x => Model.RecordId)
            @Html.HiddenFor(x => Model.PreviousClicked)
    
            if (TempData.ContainsKey("parent"))
            {
                <input type="hidden" name="currentPageId" value="@(((RenderModel)TempData["parent"]).Content.Id)" />
    
                TempData.Remove("parent");
            }
    
            <input type="hidden" name="Theme" value="landingspage" />
    
            @* These 2 cannot use the htmlhelper *@
            <input type="hidden" name="FormStep" value="@Model.FormStep" />
            <input type="hidden" name="RecordState" value="@Model.RecordState" />
    
    
            @* Render the form html *@
            @Html.Partial(formThemedView)
        }
    

    This way I'm actually using an AJAX postback the way it's supposed to work

  • Eric Wilkinson 8 posts 78 karma points
    Nov 09, 2018 @ 19:13
    Eric Wilkinson
    0

    Jeroen, thanks for posting code that works for you. Question for you regarding this example, how is "parent" set into the TempData? I'm having an issue where the form just redirects to a returned partial view of the form upon submit - and I think it's because the parent / currentPageId vars aren't getting set.

Please Sign in or register to post replies

Write your reply to:

Draft