Contentment data list get current node
# help-with-other
s
Why isn't this working 😦
Copy code
cs
public class DiscordChannelDataList : IDataListSource
{
    private readonly IContentmentContentContext _contentContext;
    private readonly IDiscordService _discordService;

    public DiscordChannelDataList(IContentmentContentContext contentContext, IDiscordService discordService)
    {
        _contentContext = contentContext;
        _discordService = discordService;
    }

    public string Name => "Discord Server Channels";
    public string Description => "A list of channels from a Discord server";
    public string Icon => "icon-badge";
    public Dictionary<string, object> DefaultValues { get; } = new();
    public IEnumerable<ConfigurationField> Fields { get; } = new List<ConfigurationField>();
    public string Group => "Discord";
    public OverlaySize OverlaySize => OverlaySize.Large;

    public IEnumerable<DataListItem?> GetItems(Dictionary<string, object> config)
    {
        try
        {
            var currentNode = _contentContext.GetCurrentContent(out bool isParent);
            if (currentNode is null)
                return Enumerable.Empty<DataListItem>();
            
            var server = currentNode.Ancestor<Server>();
            if (server?.ServerId == null)
                return Enumerable.Empty<DataListItem>();

            var serverId = ulong.Parse(server.ServerId);

            var channels = Task.Run(async () => await _discordService.GetTextChannelsAsync(serverId));

            var rolesResult = channels.Result.ToList();
            if (rolesResult.Count == 0)
                return Enumerable.Empty<DataListItem>();

            return rolesResult.Select(x => new DataListItem
            {
                Value = x.Id.ToString(),
                Name = x.Name,
            });
        }
        catch
        {
            // intentionally empty
        }
        
        return Enumerable.Empty<DataListItem>();
       
    }
}
I have very simliar code in another project and it works fine. I want to get the current node id, to access the root node property. My tree is: DiscordServer -> node DiscordServer -> node I am on "node" and want "discord server" property. I've tried the above code, and also some weirdness:
Copy code
cs
var gotContext = _umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext);
            if (!gotContext || umbracoContext?.Content == null)
                return Enumerable.Empty<DataListItem>();

            var gotId = int.TryParse(_requestAccessor.GetQueryStringValue("id"), out var id);
            if (!gotId)
                return Enumerable.Empty<DataListItem>();

            var publishedContent = umbracoContext.Content.GetById(id);
            if (publishedContent == null)
                return Enumerable.Empty<DataListItem>();
Umbraco Cloud 13 👆
j
There is a known issue where the context can't be found from within a blocklist, is your property within a blocklist? 🙂 https://github.com/leekelleher/umbraco-contentment/issues/384
s
Ahhh - that's exactly where it is. I just noticed that my "working" code is not in a blocklist, but my "broken" code is. Ahh! That's so frustrating. It's sent in this request, which I have access to inside of the data list but I can't get the payload out 😦 https://cdn.discordapp.com/attachments/1232970455259021342/1232989408362369105/image.png?ex=662b765e&is=662a24de&hm=0acd9b9fa37bfabd5fa7217163b80be8e7dbcdf65fb01acc10fb24a75b4fcf80&
I got it! (possibly hacky, may be a bad idea) I added some middleware:
Copy code
cs
app.Use(async (context, next) =>
{
    context.Request.EnableBuffering();

    string bodyContent;
    using (StreamReader reader = new StreamReader(context.Request.Body, Encoding.UTF8, false, leaveOpen: true))
    {
        bodyContent = await reader.ReadToEndAsync();

        // Reset the request body stream position so it can be read again further in the pipeline
        context.Request.Body.Position = 0;
    }

    // Store the request body content to be accessed later in the pipeline
    context.Items["RequestBody"] = bodyContent;

    await next.Invoke();
});
Now I have access to the body (as it's already read by the time it's received)
Copy code
cs
            if (_httpContextAccessor.HttpContext == null)
                return Enumerable.Empty<DataListItem>();
            
            var requestBody = _httpContextAccessor.HttpContext.Items["RequestBody"]?.ToString();
            if (string.IsNullOrEmpty(requestBody))
                return Enumerable.Empty<DataListItem>();
            
            var request = System.Text.Json.JsonSerializer.Deserialize<GetByEmptyKeysRequest>(requestBody);
            if (request is null)
                return Enumerable.Empty<DataListItem>();

            // get parent id
            var parentId = request.ParentId;
I can now do my get at root of this node just fine
thanks, @Jemayn - I probably would've waste a bunch of time trying to get something to work that would've never.
j
That's a nice workaround, I wonder how it will affect performance for regular frontend requests though 🤔
s
umbraco frontend, or user frontend?
j
Well I guess it depends on your setup, mainly the middleware I was thinking of
s
I don't see any performance degradation in the backoffice at all, which is nice, there is no frontend to this (consumer facing) as it's just a Discord bot asking for details. so hopefully it'll be ok
j
Ahh ok no biggie then 🙂
2 Views