Search code examples
c#outlookmicrosoft-graph-api

Displaying Outlook Calendar Event information with Microsoft Graph


I have seen a few questions but can't quite work this out. I adjusted my code to include event information from each calendar:

   public void DisplayCalendarsList(bool bDetailed)
    {
        try
        {
            foreach (Calendar oCalendar in _ListCalendars)
            {
                string strCalendarInfo = $"Calendar Name: {oCalendar.Name}";
                strCalendarInfo += $" Calendar Id: {oCalendar.Id}";
                Console.WriteLine(strCalendarInfo);

                if(bDetailed)
                {
                    if(oCalendar.Events?.Count > 0)
                    {
                        foreach (Event oEvent in oCalendar.Events)
                        {
                            string strEventInfo = $"Subject: {oEvent.Subject}" + Environment.NewLine;
                            strEventInfo += $"Body: {oEvent.Body}" + Environment.NewLine;
                            strEventInfo += $"Times: Start - {oEvent.Start} End - {oEvent.End}" + Environment.NewLine;
                            strEventInfo += $"Location: {oEvent.Location}" + Environment.NewLine;
                            strEventInfo += $"All Day: {oEvent.IsAllDay}" + Environment.NewLine;
                            Console.WriteLine(strEventInfo);
                        }

                    }
                }
            }
        }
        catch(Exception ex)
        {
            Console.WriteLine($"Error DisplayCalendarsList: {ex.Message}");
        }
     }

But in each case the oEvent is null and I don't know why.

Update

For example, I know that the Keynsham Congregation calendar has two test events in it. Yet:

Debug Output

The Microsoft Snippets does this:

// Get events in all the current user's mail folders.
public async Task<List<ResultsItem>> GetMyEvents(GraphServiceClient graphClient)
{
    List<ResultsItem> items = new List<ResultsItem>();

    // Get events.
    IUserEventsCollectionPage events = await graphClient.Me.Events.Request().GetAsync();

    if (events?.Count > 0)
    {
        foreach (Event current in events)
        {
            items.Add(new ResultsItem
            {
                Display = current.Subject,
                Id = current.Id
            });
        }
    }
    return items;
}

But the context is not the same. I am not using graphClient.Me.Events because it is not what I want.

Update 2

I found another resource that has helped me. I adjusted things like this so that instead of using oCalendar.Events I use the graph:

public async Task BuildCalendarsList()
{
    if (_AuthResult == null)
        return;

    try
    {
        _graphClient = new GraphServiceClient(
                 new DelegateAuthenticationProvider(
                     (requestMessage) =>
                     {
                         // Append the access token to the request.
                         requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", _AuthResult.AccessToken);
                         return Task.FromResult(0);
                     }));

        var calendars = await _graphClient
                             .Me
                             .Calendars
                             .Request()
                             .GetAsync();


        Console.WriteLine($"Number of calendars: {calendars.Count}");

        _ListCalendars = calendars.ToList();

        foreach (Calendar oCalendar in _ListCalendars)
        {
            var oEvents = await _graphClient
                                .Me
                                .Calendars[oCalendar.Id]
                                .Events
                                .Request()
                                .GetAsync();
            if(oEvents?.Count > 0)
            {
                foreach(Event oEvent in oEvents)
                {
                    string strEventInfo = $"Subject: {oEvent.Subject}" + Environment.NewLine;
                    strEventInfo += $"Body: {oEvent.Body}" + Environment.NewLine;
                    strEventInfo += $"Times: Start - {oEvent.Start} End - {oEvent.End}" + Environment.NewLine;
                    strEventInfo += $"Location: {oEvent.Location}" + Environment.NewLine;
                    strEventInfo += $"All Day: {oEvent.IsAllDay}" + Environment.NewLine;
                    Console.WriteLine(strEventInfo);
                }
            }
        }

    }
    catch (Exception ex)
    {
        _ListCalendars = null;
        Console.WriteLine($"Error BuildCalendarsList: {ex.Message}");
    }
}

Why did I have to do it like this?

Ideally, I was hoping to adjust this method:

private async Task Run()
{
    Outlook oOutlook = new Outlook();
    await oOutlook.AquireToken();
    if(oOutlook.AuthResult == null)
    {
        if (oOutlook.ResultsText != "")
            Console.WriteLine(oOutlook.ResultsText);
    }
    else
    {
        oOutlook.DisplayBasicTokenInfo();

        await oOutlook.BuildCalendarsList();
        oOutlook.DisplayCalendarsList(false);
        //oOutlook.DisplayCalendarsList(true);

        oOutlook.SignOut();
    }
}

So that if I passed true it would provide a detailed event output.

I appreciate any advice on how to break my BuildCalendarsList down into two methods.


Solution

  • The events collection can be tricky to work with. It is a raw view into the underlying data which is heavily rules based. For example, a recurring meeting has a "master" event and a list of exceptions (moved date/times, canceled occurrence, etc.). The events collection typically shouldn't be used to grab a "view" of someone's calendar.

    Instead of events, take a look at calendarView. This gives you the "rendered" view of a calendar (i.e. what a user would normally see in Outlook).