Copied to clipboard

Flag this post as spam?

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


  • Jason Espin 368 posts 1335 karma points
    Jan 14, 2015 @ 15:34
    Jason Espin
    0

    Loading a partial view or Macro partial using a surface controller and Ajax

    Hi all,

    I am currently in the process of building a payment system for a new client and was wondering if it is possible to load a partial view or Macro partial into an area of my page using Ajax?

    The idea is that I initially have a screen that looks like the example below: Book Now

    Upon clicking 'Book Now' an Ajax call is made using the following jQuery code:

    $('#productavailability').click(function () {
            var package = {};
            package.packageCode = $(this).data('id');
    
            $.ajax({
                url: '/umbraco/surface/product/GetAvailability',
                type: 'POST',
                dataType: 'html',
                data: JSON.stringify(test),
                contentType: 'application/json; charset=utf-8',
                success: function (data) {
                    $('#availabilityResult').html(data);
                }
            })
    });
    

    This process is fine and is working as intended however, when I get to the method within my surface controller I was wondering if it is possible to load in (using the return from the AJAX call) a MacroPartial or Partial view to display a form below the button if the controller indicates that there are an adequate number available of the product. Much like the diagram below:

    Buy

    So far, my surface controller code is as follows:

    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Linq;
    using System.Web;
    using Newtonsoft.Json;
    using System.Web.Mvc;
    using Umbraco.Web.Mvc;
    using IMG_Prototype_Solution.TailorMadeWebService;
    
    namespace IMG_Prototype_Solution.Controllers
    {
        public class ProductController : SurfaceController
        {
            // Declare security credentials globally for use with all methods
            Guid guid = new Guid(ConfigurationManager.AppSettings["axumcompanyguid"]);
            String companyName = ConfigurationManager.AppSettings["axumcompanyname"];
    
            // Setup managed user header
            ManagedUserHeader managedUserHeader = new ManagedUserHeader();
    
            // Setup compression soap header
            CompressionSoapHeader compressionSoapHeader = new CompressionSoapHeader();
    
            // Setup Web Service
            TailorMadeWebServiceSoapClient ws = new TailorMadeWebServiceSoapClient();
    
            [HttpPost]
            public ActionResult GetAvailability(int packageCode)
            {
                managedUserHeader.CompanyName = companyName;
                managedUserHeader.RegistrationKey = guid;
                compressionSoapHeader.CompressionMethodUsed = CompressionMethods.None;
    
                ProductAvailDataGroup[] ws_availability = null;
                ws_availability = ws.GetProductAvailability(ref compressionSoapHeader, ref managedUserHeader, packageCode, DateTime.Today, DateTime.Today.AddDays(28));
                IHtmlString data = null;
    
                if (ws_availability.Count() > 0)
                {
                    data = new HtmlString("<div>Product Available</div>");
                }
                else
                {
                    data = new HtmlString("<div>Product Unavailable</div>");
                }
    
                return Content(data);
    
            }
        }
    }
    

    Unfortunately, this code is invalid so will never work as it is expecting an ActionResult to be returned rather than the HTML I am actually trying to return to my Javascript. How I get around this, I do not know (any pointers would be greatly appreciated for future reference).

    Anyway, the ideal situation would be that I could return a MacroPartial which would then be rendered on the page to produce the form shown above which would then be processed by a separate controller. The problem I then have is what will happen when I run RedirectToCurrentUmbracoPage() on this newly rendered form. I am assuming it just will not process anything.

    If anyone has any pointers, it would be greatly appreciated as the Umbraco Level 2 certification does not go into as much detail as it should with regards to complex issues such as these.

  • Jason Espin 368 posts 1335 karma points
    Jan 15, 2015 @ 10:18
    Jason Espin
    0

    Come on, someone must know something about this...

  • Dave Woestenborghs 3504 posts 12134 karma points MVP 9x admin c-trib
    Jan 15, 2015 @ 11:52
    Dave Woestenborghs
    0

    You can return a partial view from your surface controller

    if(ws_availability.Count()>0)
               
    {
                    return PartialView("ProductAvailable");

               
    }
               
    else
               
    {
                    return PartialView("ProductNotAvailable")

               
    }

    Dave

  • Sebastiaan Janssen 5058 posts 15520 karma points MVP admin hq
    Jan 15, 2015 @ 11:53
    Sebastiaan Janssen
    0

    You're making it really hard on yourself. I'd recommend that you have the form already available in a hidden div and you show it based on the availability result. Of course people can try to game the system by inspecting your HTML but once the form is submitted you should check again if the product is available.

    Also, I recommend you read up on ASP.NET WebApi and use an ApiController instead of a SurfaceController. http://our.umbraco.org/documentation/Reference/WebApi/

  • Jason Espin 368 posts 1335 karma points
    Jan 15, 2015 @ 12:31
    Jason Espin
    0

    Hi Dave & Sebastiaan,

    Thanks for the feedback. The problem is the initial (checkavailability) call goes away to a web service and returns whether something is available and the dates on which it is available. It's basically a tour / holiday booking system. Therefore the datepicker needs to be constructed in the partial view then output to the page with the available dates. After submitting this, they then need to enter their card details etc in a separate form.

  • Sebastiaan Janssen 5058 posts 15520 karma points MVP admin hq
    Jan 15, 2015 @ 13:09
    Sebastiaan Janssen
    0

    Any datepicker worth it's salt should be able to update through an event or something, I'm sure that would be no problem.

  • Jason Espin 368 posts 1335 karma points
    Jan 20, 2015 @ 16:54
    Jason Espin
    0

    Okay I really am having no joy with this whatsoever. I have tried WebAPI, surface controllers and have read a stack of Umbraco documentation on Surface Controllers and the WebAPI but like I say no joy. I don't understand why it is so difficult to return a form using an Ajax request to a method in a controller because essentially the form is just HTML so should render to the page easily.

    One of the the other main issues I have is using the CurrentUmbracoPage() method which clearly should not be used with Ajaz. Any ideas? I'm beginning to give up hope of implementing this system in Umbraco.

  • Sebastiaan Janssen 5058 posts 15520 karma points MVP admin hq
    Jan 20, 2015 @ 18:47
    Sebastiaan Janssen
    0

    All I can tell you is that "returning" a form is a really bad idea (you've already experienced that through your struggles). You really shouldn't be returning hardcoded HTML from controllers, that's really messy.

    So: once available is true: show a hidden form that's already on the page, using a normal simple SurfaceController to post and handle it. You can send back a bit of json indicating if something is available and when on what dates, unhide the hidden form and call into the datepicker's events to set a start date and an end date. I'll even go as far as looking up the exact javascript call you'll need to do to update the datepicker if you can specify which exact picker you're using.

  • Jason Espin 368 posts 1335 karma points
    Jan 21, 2015 @ 10:29
    Jason Espin
    0

    Hi Sebastiaan,

    I know how to do the datepicker update for the Jquery UI bit. That is really simple and I prototyped that the other day. The problem I have is that the workflow we require for this process needs to make use of multiple forms so the method you have described is fine and will cater for the first stage of the process where we check a trip is available then populate a datepicker in a form that is already on the page however once they have selected a date and time for their trip we then need them to specify how many adults and children will be going. Again, this part is fine but its the stage that follows where the issues begin.

    After selecting the adults and children we then need to load or redirect to somewhere else where we have a form that has a number of fields for them to enter passenger names and details depending on their selection at the adults and children stage. The remainder of this form will then capture their personal details and payment details and forward them to an external payment service whilst also adding them to our internal system using web services.

    Now if it is a bad idea to try and return a form from an Ajax call then that is fine and you are a much better developer than me so I take your advice on that one. Ideally I wanted to make the experience as fast and user friendly as possible as it will also be displayed on mobile and tablet devices hence why I wanted to use Ajax but if I don't do that where I run into the issue is with the second form where I capture the names and details of the passengers.

    How would I redirect to this new form? I have tried return View('Payment') but this does not allow me to use the master template and also how do I pass the previous data that we have captured from the first form into this?

    The payment process I am trying to recreate is here (this is a live site so I wouldn't make any payments :-) ):

    https://www.mountainguides.is/day-tours/glacier-tours/from-reykjavik/take-a-walk-on-the-ice-side/

    It is an old Umbraco 6 site so it pretty much solely built using XSLT meaning we can't use and modify the existing code base because I am not familiar with XSLT and that is not the way to go anymore. I really appreciate all of the help by the way.

Please Sign in or register to post replies

Write your reply to:

Draft