Copied to clipboard

Flag this post as spam?

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


  • Elliott Quick 8 posts 80 karma points
    Jun 02, 2016 @ 16:25
    Elliott Quick
    1

    Trouble with Route Hijacking

    Hey Everyone, after googling and looking at the Development Wiki I believe the correct path for my goal (see below) is that I need to create a Controller, document type and template in order to essentially pass data between pages.

    My Issue

    I can't seem to get a content page I created that uses the custom template and is of documentType Custom to load properly when I browse too it. I want all of my pages manageable through Umbraco, I know that I can easily route to a custom view but that defeats the purpose of being able to edit it in my CMS.

    My Goal

    Data gathered on my Umbraco page (using Javascript in the template and some HTML code editors) needs to make it's way to a follow-up page that will then provide options that elaborate and are based on the data passed. Ideally I want to do this using a querystring

    My Created Content

    • DocumentType called "Custom"
    • Template called "CharacterSelection" (see below)
    • Controller called: "CustomController" (see below)
    • Model called: "CharacterSelectionModel" (see below)

    Controller:

        public class CustomController : Umbraco.Web.Mvc.RenderMvcController
        {
            public override ActionResult Index(RenderModel model)
            {
                //Do some stuff here, then return the base method
                return base.Index(model);
            }
    
            public ActionResult CharacterSelection(RenderModel model, String name, String membership)
            {
                CharacterSelectionModel csModel = new CharacterSelectionModel(model.Content);
    
                csModel.Player = new PlayerSearchResult() { PlayerName = name, MembershipId = membership };
    
                //Create delicious Cookie/Check delicious Cookie/Redirect if no values for name and membership
    
                return CurrentTemplate(csModel);
            }
    
        }
    

    Model:

    public class CharacterSelectionModel : RenderModel
    {
        //Standard Model Pass Through
        public CharacterSelectionModel(IPublishedContent content) : base(content) { }
    
        public PlayerSearchResult Player { get; set; }
    }
    

    Template:

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        Layout = "Master.cshtml";
    }
    
    
    
    <script type="text/javascript">
        $(document).ready(function () {
            $("#testDiv").html("<p>NAME: " + @Model + ", MEMBERSHIP: " + "</p>")
        });
    </script>
    
    
    
    @CurrentPage.GetGridHtml("content", "fanoe")
    
  • Jordan 24 posts 182 karma points
    Jun 03, 2016 @ 09:14
    Jordan
    0

    Hey Elliott,

    Have you looked into SurfaceControllers and the UmbracoAPIController? I believe from what I can see, you should be able to achieve this with a SurfaceController or UmbracoAPIController.

    The UmbracoAPIController allows you to make easy request backs to the server through ajax to retrieve information from the database. The SurfaceController allows you to high jack page rendering for pages that call on that SurfaceController, This allows for custom code to be returned and used within the view.

    Documentation for SurfaceContollers (there are some good videos on this in the umbraco video library as well): https://our.umbraco.org/documentation/reference/routing/surface-controllers

    Documentation for the UmbracoAPIController: https://our.umbraco.org/documentation/reference/routing/webapi/

    Here is some example code for a simple API controller function I coded a while back:

    API Controller

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using Test_Json_WebApi.Models;
    using Umbraco.Web.WebApi;
    using Umbraco.Web.Mvc;
    
    namespace Test_Json_WebApi.Controllers
    {
        public class ForensicsApiController : UmbracoApiController
        {
            public JsonResult GetJsonString(Forensics viewModel)
            {
                var allVisits = Umbraco.TypedContent(5630).Children;
                List<Forensics> Logs = new List<Forensics>();
                foreach(var visits in allVisits) {
                    Logs.Add(new Forensics                {
                        city = visits.GetProperty("city").Value.ToString(),
                        country = visits.GetProperty("country").Value.ToString(),
                        lat = visits.GetProperty("latitude").Value.ToString(),
                        lon = visits.GetProperty("longitude").Value.ToString(),
                        org = visits.GetProperty("organization").Value.ToString(),
                        query = visits.GetProperty("iPAddress").Value.ToString(),
                        zip = visits.GetProperty("postCode").Value.ToString(),
                        numVisits = visits.GetProperty("numberOfVisits").Value.ToString()
                    });
                }
            }
        }
    }
    

    Model code

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace Test_Json_WebApi.Models
    {
        public class Forensics
        {
            public string city { get; set; }
            public string country { get; set; }
            public string lat { get; set; }
            public string lon { get; set; }
            public string org { get; set; }
            public string query { get; set; }
            public string zip { get; set; }
            public string numVisits { get; set; }
        }
    }
    

    Angular Resource Request

    angular.module("umbraco.resources").factory("gmapsResource", function ($http) {
        var myService = new Object;
    
            myService.getAll = function () {
                var test = $http.get("api/ForensicsApi/GetJsonString");
                return test;
            };
            return myService;
        });
    

    This snippet of code grabs data from populated fields in the umbraco backend and stores it all in an angular control, this was used to display the content as pins on a google map and was part of a plugin for the umbraco backend.

    If you are calling on the api for front end purposes then you can can make a call to:

    umbraco/api/forensicsApi/GetJsonString
    

    Hope that helps to give some inspirations, and will work with what you are trying to do.

  • Elliott Quick 8 posts 80 karma points
    Jun 06, 2016 @ 12:48
    Elliott Quick
    0

    I am re-trying this approach, however it raises a few concerns.

    1. I don't believe I am able to edit a surface controller's View through Umbraco's Content Manager. (sure I can see the raw cshtml view but I was hoping that non technical users could edit this page

    2. I imagine it is not good practice for a user's browsing page URL to include "Umbraco/Surface". Doesn't that break the expected browsing paths?

    I can't use the view as a partial view or child action because I need to pass 2 values to the controller. If I was able to just query string an existing Umbraco Content Managed Page and pull the two values from the query string I would be able to use a surface controller to load a partial view.

  • Elliott Quick 8 posts 80 karma points
    Jun 06, 2016 @ 16:04
    Elliott Quick
    0

    Alright, when it was all said and done. I was able to achieve this by using the RenderMvcController and route hijacking.

    The key things that were missing highlighted below.

    For starters I followed this example: http://umbraco.com/follow-us/blog-archive/2014/1/27/a-practical-example-of-route-hijacking-in-umbraco.aspx

    I made sure my parameters were null-able, used "RenderModel model" as the first required paramater and routed my request to the umbraco content/managed page adding the query string to the end of the url but ommiting the RenderModel as I believe Umbraco must handle that bit internally.

    For example:

    url: /services/character-selection?parmOne=something&parmTwo=somethingElse
    

    In my view I had to reference the master template page, I am working out if it is possible to reference the template used in the route (otherwise that template.cshtml is just wasted)

Please Sign in or register to post replies

Write your reply to:

Draft