Copied to clipboard

Flag this post as spam?

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


  • Charles Afford 1163 posts 1709 karma points
    Feb 08, 2013 @ 10:45
    Charles Afford
    0

    Umbraco MVC(4.11.1) Surface controller using an AJAX form

    Hello :).  I have a website using Umbraco MVC (V: 4.11.1).  At the top of all the pages we a login form with a username.  The actual surface controller is working and if i use UmbracoBeginForm() everything works fine and the page reloads.

    However we do not want the page to full reload, just part of the page, so decided to use an Ajax form.  However when the post is made an error is thrown that the view Login cannot be found.

    Has anyone got any ideas?  Thanks.  Charlie.

  • firepol 125 posts 173 karma points
    Jun 07, 2013 @ 17:50
    firepol
    0

    Actually it would have been cool to see an answer here... I'm looking exactly for the same thing...

    I have such a form:

    @{ var ajaxOptions = new AjaxOptions
    {
        OnSuccess = "feedback",
        HttpMethod = "POST"
    }; }
    @using(Ajax.BeginForm("Contact", "FormSurface", ajaxOptions))
    {

    <label for="FirstName">FirstName</label>
    <input name="FirstName" />

    <input type="submit"/>
    }

    when I click submit, the page does a full post... I was expecting an ajax call to be done and my function "feedback" to be called...

    ...any ideas/help is appreciated. THX

  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Jun 07, 2013 @ 18:30
    Matt Brailsford
    0

    Hey guys,

    How are you hooking up the Ajax parts? As long as you submit as a post to the surface controller action including the hidden var that the surface controller uses for "context" you should be able to post via Ajax fine (you may want to make sure your action returns a Json result instead of a standard view result though at the end)

    If you could post some code it might help us point you in the right direction.

    Matt

  • Andreas Iseli 150 posts 427 karma points
    Jun 08, 2013 @ 15:28
    Andreas Iseli
    0

    I personaly use JQuery with asynchronous form postbacks for this purpose. I then return a JSON result which works fine.

  • Charles Afford 1163 posts 1709 karma points
    Jun 08, 2013 @ 20:33
    Charles Afford
    1

    Wow this seems like so long ago, ended up using the implemtation you mention above Andreas :).  Ajax with some jquery that gets the JSON result :)

  • firepol 125 posts 173 karma points
    Jun 10, 2013 @ 10:53
    firepol
    0

    Hi there, here some code so you see what I have.

    Controllers\FormSurfaceController.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using MySite.Models;
    
    namespace MySite.Controllers
    {
        public class FormSurfaceController : Umbraco.Web.Mvc.SurfaceController
        {
            [HttpPost]
            public JsonResult Contact(FormModel model)
            {    
                if (!ModelState.IsValid)
                {
                    return Json(new { success = false });
                }
    
                return Json(new { success = true });
            }
        }
    }
    
    

    Models\FormModel.cs

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace MySite.Models
    {
        public class FormModel
        {
            [Required]
            public string FirstName { get; set; }
        }
    }

    Views\Shared\_Layout.cshtml

    <!DOCTYPE html>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    
            <title>MySite</title>
    
            <link rel="stylesheet" href="/css/main.css" type="text/css">
            <script src="/Scripts/jquery-1.9.1.min.js"></script> 
            <script src="/Scripts/common.js"></script>
        </head>
    
        @RenderBody()
    
    </html>
    

    Views\Form.cshtml

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        Layout = "Shared/_Layout.cshtml";
    }
    
    <body>
    
    @{ var ajaxOptions = new AjaxOptions
    {
        OnSuccess = "feedback",
        HttpMethod = "POST"
    }; }
    @using(Ajax.BeginForm("Contact", "FormSurface", ajaxOptions))
    {
    
    <label for="FirstName">FirstName</label>
    <input name="FirstName" />
    
    <input type="submit"/>
    }
    
    </body>

    /Scripts/common.js

    function feedback(result) {
    
        if (result.success) {
            console.log('ok');
        } else {
            var error = "Error";
    
            if (result.error) {
                error = result.error;
            }
    
            console.log(error);
        }
    }

    So when I do something like this in a standard ASP.NET MVC 4 project with jquery validation, Ajax.BeginForm generates HTML that looks like this (Browser inspector shows like this):

    <form id="form0" method="post" data-ajax-success="feedback" data-ajax-method="POST" data-ajax="true" action="/Letter/Edit/1" novalidate="novalidate">

    When I click the "submit" button an ajax post request is sent, and my "feedback" method is fired to get the result (the controller returns a JsonResult). The form works.

    Umbraco generates HTML that looks like this:

    <form onsubmit="Sys.Mvc.AsyncForm.handleSubmit(this, new Sys.UI.DomEvent(event), { insertionMode: Sys.Mvc.InsertionMode.replace, httpMethod: 'POST', onSuccess: Function.createDelegate(this, feedback) });" onclick="Sys.Mvc.AsyncForm.handleClick(this, new Sys.UI.DomEvent(event));" method="post" action="/umbraco/Surface/FormSurface/Contact">

    In this form generated by umbraco, when I click on "submit" the form is fully posted and the browser shows the contents of "/umbraco/Surface/FormSurface/Contact" ({"success":true}) instead of firing just an ajax request like in a stanrd ASP.NET MVC4 project and handle the result via feedback method. Can you help?

  • firepol 125 posts 173 karma points
    Jun 10, 2013 @ 13:39
    firepol
    0

    @Matt, what is the "hidden var that the surface controller uses for "context"" ? Can you provide an example? Maybe my example does a full post because I don't include that var, but as I don't see any documented example I find it hard to guess how to proceed... Thanks for letting me know...

  • Andreas Iseli 150 posts 427 karma points
    Jun 10, 2013 @ 13:46
    Andreas Iseli
    0

    The form is missing an ID, that could be a problem. Also it does not define the data-ajax attributes required. Is this the same @Ajax.BeginForm call?

  • firepol 125 posts 173 karma points
    Jun 11, 2013 @ 09:45
    firepol
    0

    Yes it's the same call, but in umbraco, the generated HTML is unluckily like I posted above.

    I posted my code, it doesn't work as expected. There must be somewhere a bug, in my code, or in umbraco.

    Can someone help and share some working code for a simple ajax form?

    What I'm requesting should be a piece of cake for who has done it already:

    • A surface controller with JsonResult
    • A view with a form created via Ajax.BeginForm and an input field as example
    • A javascript function called e.g. "feedback" that will capture the Json response, and on success just console.log("it works"); or alert("it works")
    • Expected result: clicking on submit will fire an ajax request and the console will display "it works" (or an alert)

    I really do not know what to do, if I don't get this working I must move on, forget about "Ajax.BeginForm" and do everything manually, but then I wonder what kind of MVC I can use in umbraco if it doesn't work... to achieve the scenario described above, using an MVC 4 template from visual studio 2012 I need just a few minutes and it works. If you want I share a zip file containing a solution.

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Jun 11, 2013 @ 10:16
    Dave Woestenborghs
    0

    I haven't done it with a Ajax.BeginForm but I've done it with my own jQuery ajax calls.

    I create a surface controller with 2 actions. One to render the form and one to handle the post.

    In my ajax call I just called the action to handle the post and return JSON.

    There was one catch. And that is how surface controller actions are routed.

    See the documentation page here : http://our.umbraco.org/documentation/Reference/Mvc/surface-controllers

    Especially the part about Routing for locally declared controllers

     

  • firepol 125 posts 173 karma points
    Jun 11, 2013 @ 15:52
    firepol
    0

    Ok I can also create my own ajax calls, but this is what I wanted to avoid...

    I would like to use those cool things that come with MVC such as:

    • jquery validation
    • jquery unotrusive validation
    • handle ajax form
    You wanna say that this is not possible? Then why do we have Ajax.BeginForm if it doesn't work?
  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Jun 11, 2013 @ 15:56
    Dave Woestenborghs
    1

    Haven't tried that yet but just found this blog post about it : http://www.systenics.com/blog/creating-an-ajax-enabled-contact-form-in-umbraco-6-with-aspnet-mvc-4-and-twitter-bootstrap/?tag=Umbraco+6

    Maybe you can find a solution there ?

     

    Dave

  • Charles Afford 1163 posts 1709 karma points
    Jun 11, 2013 @ 20:59
    Charles Afford
    0

    Yea that post looks an ok implimentation.  That will work.  Should not have all that logic in your controller though.  Abstract is and have the controller called a method returning an enum result you can switch on :).  Charlie.

  • firepol 125 posts 173 karma points
    Jun 12, 2013 @ 10:56
    firepol
    1

    Hi Dawoe,

    SOLVED. THANK YOU. The blog post you found helped me to solve my issue.

    To sum up, to fix the code I shared in my previous posts:

    • I had to move the form inside another partial view, as explained in the umbraco partial views documentation in order to use my strongly typed model (FormModel) and have all the nice client validation given automatically by jquery validation + unobtrusive.
    • I forgot (shame on me) to insert the jquery-validate, jquery-validate-unobtrusive and jquery.unobtrusive-ajax javascript files (I noticed that before, but somehow something didn't work)
    • I had to add 2 keys in my web.config file to allow client validation
    So here the corrections:
    Form.cshtml looks like this:
    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        Layout = "Shared/_Layout.cshtml";
    }
    
    <h1>Form</h1>
    
    @Html.Partial("_FormAjax", new TranscorAstra.Website.Models.FormModel())
    
    <script src="/Scripts/jquery.validate.js"></script>
    <script src="/Scripts/jquery.validate.unobtrusive.js"></script>
    <script src="/Scripts/jquery.unobtrusive-ajax.js"></script>
    <script src="/Scripts/common.js"></script>
    <script src="/Scripts/extra.js"></script>
    Partials\_FormAjax.cshtml looks like this:
    @inherits Umbraco.Web.Mvc.UmbracoViewPage<TranscorAstra.Website.Models.FormModel>
    @{
        Layout = null;
    }
    
    @{ var ajaxOptions = new AjaxOptions { HttpMethod = "POST", OnSuccess = "feedback" }; }    
    @using(Ajax.BeginForm("ContactAjax", "FormSurface", ajaxOptions))
    {
        @Html.LabelFor(model => model.FirstName)
        @Html.EditorFor(model => model.FirstName)
    
        <input type="submit" value="Send" />  
    }
    In the web.config file, I had to add the following keys under appSettings:
    <add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
    The rest of the code I shared is basically ok.
    Note, in the turorial dawoe mentioned, the AjaxOptions are too many for my needs & taste. My "feedback" function takes the resulting JSON result and handles success = true or success = false and takes -if existing- extra information such as a message (for success) or error for failure (these of course have to be added in the Controller) also I didn't use the UpdateTargetId as I don't want to update a div in my page, I do it manually via feedback function.
    AGAIN THANK YOU.
    P.s. talking about MVC Forms, I have another issue to solve. How do I populate a dropdown list in my form, taking all child nodes of type "office" under my form node? See question Model.Content not available in Partial View (MyModel, not RenderModel)
  • Tom 713 posts 954 karma points
    Feb 04, 2014 @ 02:11
    Tom
    0

    I couldn't seem to get the routing right using Ajax.BeginForm the form url for the action it generates is:

    /umbraco/RenderMvc/SendMail?Length=7

     

    instead of /umbraco/surface/Contact/SendMail if I try and use the out of the box functionality in v7.2

     

    anyone got any hints short of hardcoding the form open tag to something like:

    <form action="/umbraco/surface/Contact/SendMail" class="form quick-contact" data-ajax="true" data-ajax-failure="ShowError()" data-ajax-loading="#contact-load" data-ajax-method="POST" data-ajax-mode="replace" data-ajax-success="ShowSuccess()" data-ajax-update="#target" id="form0" method="post" role="form" novalidate="novalidate">

Please Sign in or register to post replies

Write your reply to:

Draft