Copied to clipboard

Flag this post as spam?

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


  • Joey Kincer 51 posts 83 karma points
    Aug 13, 2022 @ 20:46
    Joey Kincer
    0

    Using Surface Controller / Service in Umbraco 10

    Hoping someone can assist. What I want to do is simply pass a GUID of an Umbraco media file into a Surface Controller and have it spit back the URL path. This will be called via ajax (jQuery).

    var img_guid = $e.data("image-guid");
    $.get("/umbraco/surface/JournalImage/GetImagePath", img_guid)
         .done(function(path) { ... }).fail(function() { ... });
    

    I've been banging my head trying to figure out where I'm going wrong on the surface controller side. Looking at the API documentation, it looks l need to call IMediaService for passing the GUID and returning the path, but it doesn't like the fact that _services is non-static and I get an object reference error when trying to use it for getting the IMedia object.

    public class JournalImageController : SurfaceController
    {
        private readonly ServiceContext _services;
    
        public JournalImageController(IUmbracoContextAccessor umbracoContextAccessor, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IPublishedUrlProvider publishedUrlProvider) : base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider)
        {
            _services = services;
        }
    
        public IActionResult GetImagePath(string guid)
        {
            string mediaPath = "fail";
            if (String.IsNullOrWhiteSpace(guid)) return mediaPath;
    
            Guid? gid = new Guid(guid);
            if (gid.HasValue)
            {
                IMedia mediaObj = _services.MediaService.GetById(gid.Value);
                mediaPath = mediaObj.GetUrl();
            }
    
            return mediaPath;
        }
    
    }
    

    Trying to make it static just cascades into errors within the constructor so going down that path is a dead-end. I'm not well-versed in this stuff yet, so perhaps I'm trying to make it too complicated. Most of what I've searched is Umbraco 8 and earlier, so I'm not too sure what's the most recent and efficient way to accomplish this with the current Umbraco codebase.

  • Marc Goodson 2138 posts 14321 karma points MVP 8x c-trib
    Aug 14, 2022 @ 10:41
    Marc Goodson
    100

    Hi Joey

    I'd probably use an ApiController here instead of a SurfaceController...

    https://our.umbraco.com/documentation/Reference/Routing/Umbraco-API-Controllers/

    A Surface Controller is mainly used for handling a Form Post within the Umbraco pipeline, where here I think you just want to call an endpoint async and get some data back.

    The ApiControllers are autorouted, based on controller action names form the /Umbraco/Api based URL eg:

    /Umbraco/Api/JournalImage/GetImagePath?guid=

    Then once inside your APIController, you wouldn't need the MediaService (counter intuitive I know!) - The MediaService is there for CRUD actions, eg updating and uploading Media programmatically in Umbraco, and it works off of the database and is slow for 'read only' operations - instead you can read the information you need using something called the IPublishedContentQuery that allows you to find content and media from a published cache, so doesn't hit the database, and is super quick!

    I think something like this might be what you need:

    using System;
    using Umbraco.Cms.Core;
    using Umbraco.Cms.Web.Common.Controllers;
    using Umbraco.Extensions;
    
    namespace YourProjectNamespace.Controllers
    {
        public class JournalImageController : UmbracoApiController
        {
            private readonly IPublishedContentQuery _contentQuery;
            public JournalImageController(IPublishedContentQuery contentQuery)
            {
                _contentQuery = contentQuery;
            }
    
            public string GetIamgePath(string guid)
            {
                string mediaPath = "fail";
                if (String.IsNullOrWhiteSpace(guid)) return mediaPath;
                Guid? gid = new Guid(guid);
                if (gid.HasValue)
                {
                    var mediaObj = _contentQuery.Media(gid);
                    mediaPath = mediaObj.Url();
                }
    
                return mediaPath;
    
            }
    
        }
    }
    

    That's the gist of it anyway!

    regards

    Marc

  • Joey Kincer 51 posts 83 karma points
    Aug 15, 2022 @ 00:30
    Joey Kincer
    0

    Marc,

    This is fantastic. Had a feeling I was barking up the wrong tree so thank you for pointing me in the right direction. In hindsight, of course I’d want to use Umbraco’s API to retrieve published content from the cache and not resort to database calls, but I spend most of my time in the backoffice GUI so there’s just too many things to choose from when it comes to adding Controllers.

    Yeah I saw all that CRUD in the Media Service but since it contained a GetById method of course I had to assume its intentions. In any case, I went another direction with Macro View Partials which solved my issue, but I’ll definitely need your example code later on for some ajax pagination calls, so I really appreciate it!

  • Marc Goodson 2138 posts 14321 karma points MVP 8x c-trib
    Aug 15, 2022 @ 07:15
    Marc Goodson
    0

    Hi Joey

    Great, glad you got something working, and yes lots of different options, as Umbraco has evolved, has made it confusing!

    I used to deliver the official 'Level 2' Umbraco Training back in the day, and I'd introduce the ContentService / MediaService and then spend the rest of the course emphasising 'not to use them' when rendering things... they are too well named!

    regards

    Marc

Please Sign in or register to post replies

Write your reply to:

Draft