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).
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.
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;
}
}
}
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!
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!
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).
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.
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.
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:
That's the gist of it anyway!
regards
Marc
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!
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
is working on a reply...