0

I'm trying to make some modifications to the DotNetCoreRazor_MSGraph sample project so that instead of just presenting mails, regardless of folder, it first creates the folder structure.

This is the code for EmailFolders.cshtml:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DotNetCoreRazor_MSGraph.Graph;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Microsoft.Graph;
using Microsoft.Identity.Web;
using Newtonsoft.Json;

namespace DotNetCoreRazor_MSGraph.Pages
{
    [AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")]
    public class EmailFoldersModel : PageModel
    {
        private readonly GraphEmailClient _graphEmailClient;
        private readonly GraphServiceClient _graphServiceClient;
        private string inboxid = null;
        private string sentitemsid = null;
        private string draftsid = null;

        [BindProperty(SupportsGet = true)]
        public string NextLink { get; set; }
        public IEnumerable<Message> Messages  { get; private set; }

        public EmailFoldersModel(GraphEmailClient graphEmailClient, GraphServiceClient graphServiceClient)
        {
            _graphEmailClient = graphEmailClient;
            _graphServiceClient = graphServiceClient;
        }

        public StringBuilder sb = new StringBuilder();
        public List<MailFolder> folders = new List<MailFolder>();

        public async Task OnGetAsync()
        {
            MailFolder inbox = await _graphServiceClient.Me.MailFolders.Inbox.Request().GetAsync();
            inboxid = inbox.Id;
            MailFolder sentitems = await _graphServiceClient.Me.MailFolders.SentItems.Request().GetAsync();
            sentitemsid = sentitems.Id;
            MailFolder drafts = await _graphServiceClient.Me.MailFolders.Drafts.Request().GetAsync();
            draftsid = drafts.Id;
            
            //get all folders on all pages
            IUserMailFoldersCollectionPage flds = await _graphServiceClient.Me.MailFolders.Request().GetAsync();
            folders.AddRange(flds.CurrentPage);
            while (flds.NextPageRequest != null)
            {
                flds = await flds.NextPageRequest.GetAsync();
                folders.AddRange(flds.CurrentPage);
            }

            //move drafts to the top of the list
            foreach (MailFolder folder in folders)
            {
                if (folder.Id == draftsid)
                {
                    folders.Remove(folder);
                    folders.Prepend(folder);
                    break;
                }
            }
            //move sentitems to the top of the list
            foreach (MailFolder folder in folders)
            {
                if (folder.Id == sentitemsid)
                {
                    folders.Remove(folder);
                    folders.Prepend(folder);
                    break;
                }
            }
            //move inbox to the top of the list
            foreach (MailFolder folder in folders)
            {
                if (folder.Id == inboxid)
                {
                    folders.Remove(folder);
                    folders.Prepend(folder);
                    break;
                }
            }

            //create the HTML <ul> structure
            sb.AppendLine("<ul id=\"myUL\">");
            foreach (MailFolder folder in folders.Where(f => f.ParentFolderId == null))
            {
                if (folder.ChildFolderCount > 0)
                    sb.AppendLine("<li class=\"caret\">");
                else
                    sb.AppendLine("<li>");
                sb.AppendLine(folder.DisplayName);
                if (folder.ChildFolderCount > 0)
                {
                    await CreateList(folder.Id);
                }
                sb.AppendLine("</li>");
            }
            sb.AppendLine("</ul>");
            await Task.CompletedTask;
        }

        //html recursor
        private async Task CreateList(string MailFolderId)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("<ul class=\"nested\">");
            foreach (MailFolder folder in folders.Where(f => f.ParentFolderId == MailFolderId))
            {
                if (folder.ChildFolderCount > 0) 
                    sb.AppendLine("<li class=\"caret\">");
                else
                    sb.AppendLine("<li>");
                sb.AppendLine(folder.DisplayName);
                if (folder.ChildFolderCount > 0)
                {
                    await CreateList(folder.Id);
                }
                sb.AppendLine("</li>");
            }
            sb.AppendLine("</ul>");
        }

        //folder recursor
        private async Task GetChildFolders(string MailFolderId)
        {
            List<MailFolder> childfolders = new List<MailFolder>();

            IMailFolderChildFoldersCollectionPage chlds = await _graphServiceClient.Me.MailFolders[MailFolderId].ChildFolders.Request().GetAsync();
            childfolders.AddRange(chlds.CurrentPage);
            while (chlds.NextPageRequest != null)
            {
                chlds = await chlds.NextPageRequest.GetAsync();
                childfolders.AddRange(chlds.CurrentPage);
            }

            folders.AddRange(childfolders);

            foreach (MailFolder folder in childfolders)
            {
                if (folder.ChildFolders.Count > 0)
                {
                    await GetChildFolders(folder.Id);
                }
            }
        }
    }
}

On the EmailFolders.cshtml page, I'm trying to grab the folder structure with @Html.Raw(Model.sb.ToString()). I know OnGetAsync is being called, because the result is <ul id="myUL"></ul> (with carriage returns after each tag). But I'm trying to see why nothing is being added to the folders list, and it's bypassing any breakpoints I use. Breakpoints on EmailFolders.cshtml work, but that doesn't help, because it's after the codebehind is finished.

4
  • Could you confirm that await _graphServiceClient.Me.MailFolders.Request().GetAsync() returns at least one folder? What's definitely wrong is folders.Where(f => f.ParentFolderId == null). What I know ParentFolderId is never null for any of user's mail folder. Commented Aug 14, 2024 at 12:49
  • Oh. No, I can't confirm it, because the breakpoints are being ignored, but I bet I need to get the root folder id and use that. Thanks. That's very helpful. And it may have solved the coding issue. But the breakpoint issue is still a problem generally. And no, it didn't work. I got the root id from inboxid.ParentFolderId, but that didn't work. I don't know how to figure this out without the breakpoints. Commented Aug 14, 2024 at 14:45
  • could you try to use ParentFolderId to find other folders at the same level e.g:var rootParentFolderId = inbox.ParentFolderId; Then, instead of checking for null, use:foreach (MailFolder folder in folders.Where(f => f.ParentFolderId == rootParentFolderId)) { AppendFolderHtml(folder); } Commented Aug 15, 2024 at 8:55
  • to check folder is being retrieve as your break point is not hitting you could try logging: Console.WriteLine("Retrieving all folders..."); IUserMailFoldersCollectionPage flds = await _graphServiceClient.Me.MailFolders.Request().GetAsync(); if (flds.CurrentPage.Count == 0) { Console.WriteLine("No folders retrieved."); } else { Console.WriteLine($"{flds.CurrentPage.Count} folders retrieved."); } Commented Aug 15, 2024 at 8:55

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.