Nesta seção, você incorporará o Microsoft Graph no aplicativo.In this section you will incorporate Microsoft Graph into the application. Para este aplicativo, você usará a biblioteca de cliente do Microsoft Graph para .net para fazer chamadas para o Microsoft Graph.For this application, you will use the Microsoft Graph Client Library for .NET to make calls to Microsoft Graph.

Obter um modo de exibição de calendárioGet a calendar view

Um modo de exibição de calendário é um conjunto de eventos do calendário do usuário que ocorrem entre dois pontos de tempo.A calendar view is a set of events from the user's calendar that occur between two points of time. Você o usará para obter os eventos do usuário para a semana atual.You'll use this to get the user's events for the current week.

  1. Abra ./Controllers/CalendarController.cs e adicione a função a seguir à classe CalendarController .Open ./Controllers/CalendarController.cs and add the following function to the CalendarController class.

    private DateTime GetUtcStartOfWeekInTimeZone(DateTime today, string timeZoneId)
    {
        // Time zone returned by Graph could be Windows or IANA style
        // TimeZoneConverter can take either
        TimeZoneInfo userTimeZone = TZConvert.GetTimeZoneInfo(timeZoneId);
    
        // Assumes Sunday as first day of week
        int diff = System.DayOfWeek.Sunday - today.DayOfWeek;
    
        // create date as unspecified kind
        var unspecifiedStart = DateTime.SpecifyKind(today.AddDays(diff), DateTimeKind.Unspecified);
    
        // convert to UTC
        return TimeZoneInfo.ConvertTimeToUtc(unspecifiedStart, userTimeZone);
    }
    
  2. Adicione a seguinte função para lidar com exceções retornadas pelas chamadas do Microsoft Graph.Add the following function to handle exceptions returned from Microsoft Graph calls.

    private async Task HandleGraphException(Exception exception)
    {
        if (exception is MicrosoftIdentityWebChallengeUserException)
        {
            _logger.LogError(exception, "Consent required");
            // This exception indicates consent is required.
            // Return a 403 with "consent_required" in the body
            // to signal to the tab it needs to prompt for consent
            HttpContext.Response.ContentType = "text/plain";
            HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
            await HttpContext.Response.WriteAsync("consent_required");
        }
        else if (exception is ServiceException)
        {
            var serviceException = exception as ServiceException;
            _logger.LogError(serviceException, "Graph service error occurred");
            HttpContext.Response.ContentType = "text/plain";
            HttpContext.Response.StatusCode = (int)serviceException.StatusCode;
            await HttpContext.Response.WriteAsync(serviceException.Error.ToString());
        }
        else
        {
            _logger.LogError(exception, "Error occurred");
            HttpContext.Response.ContentType = "text/plain";
            HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            await HttpContext.Response.WriteAsync(exception.ToString());
        }
    }
    
  3. Substitua a função Get existente pelo seguinte.Replace the existing Get function with the following.

    [HttpGet]
    public async Task<IEnumerable<Event>> Get()
    {
        // This verifies that the access_as_user scope is
        // present in the bearer token, throws if not
        HttpContext.VerifyUserHasAnyAcceptedScope(apiScopes);
    
        // To verify that the identity libraries have authenticated
        // based on the token, log the user's name
        _logger.LogInformation($"Authenticated user: {User.GetDisplayName()}");
    
        try
        {
            // Get the user's mailbox settings
            var me = await _graphClient.Me
                .Request()
                .Select(u => new {
                    u.MailboxSettings
                })
                .GetAsync();
    
            // Get the start and end of week in user's time
            // zone
            var startOfWeek = GetUtcStartOfWeekInTimeZone(
                DateTime.Today, me.MailboxSettings.TimeZone);
            var endOfWeek = startOfWeek.AddDays(7);
    
            // Set the start and end of the view
            var viewOptions = new List<QueryOption>
            {
                new QueryOption("startDateTime", startOfWeek.ToString("o")),
                new QueryOption("endDateTime", endOfWeek.ToString("o"))
            };
    
            // Get the user's calendar view
            var results = await _graphClient.Me
                .CalendarView
                .Request(viewOptions)
                // Send user time zone in request so date/time in
                // response will be in preferred time zone
                .Header("Prefer", $"outlook.timezone=\"{me.MailboxSettings.TimeZone}\"")
                // Get max 50 per request
                .Top(50)
                // Only return fields app will use
                .Select(e => new
                {
                    e.Subject,
                    e.Organizer,
                    e.Start,
                    e.End,
                    e.Location
                })
                // Order results chronologically
                .OrderBy("start/dateTime")
                .GetAsync();
    
            return results.CurrentPage;
        }
        catch (Exception ex)
        {
            await HandleGraphException(ex);
            return null;
        }
    }
    

    Revise as alterações.Review the changes. Esta nova versão da função:This new version of the function:

    • Retorna IEnumerable<Event> em vez de string .Returns IEnumerable<Event> instead of string.
    • Obtém as configurações de caixa de correio do usuário usando o Microsoft Graph.Gets the user's mailbox settings using Microsoft Graph.
    • Usa o fuso horário do usuário para calcular o início e o fim da semana atual.Uses the user's time zone to calculate the start and end of the current week.
    • Obtém uma visão de calendárioGets a calendar view
      • Usa a .Header() função para incluir um Prefer: outlook.timezone cabeçalho, o que faz com que os eventos retornados tenham seus horários de início e término convertidos no fuso horário do usuário.Uses the .Header() function to include a Prefer: outlook.timezone header, which causes the returned events to have their start and end times converted to the user's timezone.
      • Usa a .Top() função para solicitar no máximo 50 eventos.Uses the .Top() function to request at most 50 events.
      • Usa a .Select() função para solicitar apenas os campos usados pelo aplicativo.Uses the .Select() function to request just the fields used by the app.
      • Usa a OrderBy() função para classificar os resultados pela hora de início.Uses the OrderBy() function to sort the results by the start time.
  4. Salve suas alterações e reinicie o aplicativo.Save your changes and restart the app. Atualize a guia no Microsoft Teams.Refresh the tab in Microsoft Teams. O aplicativo exibe uma lista de JSON dos eventos.The app displays a JSON listing of the events.

Exibir os resultadosDisplay the results

Agora você pode exibir a lista de eventos de forma mais amigável.Now you can display the list of events in a more user friendly way.

  1. Abra ./pages/index.cshtml e adicione as seguintes funções dentro da <script> marca.Open ./Pages/Index.cshtml and add the following functions inside the <script> tag.

    function renderSubject(subject) {
      if (!subject || subject.length <= 0) {
        subject = '<No subject>';
      }
    
      return $('<div/>', {
          class: 'ms-fontSize-18 ms-fontWeight-bold',
          text: subject
      });
    }
    
    function renderOrganizer(organizer) {
      return $('<div/>', {
        class: 'ms-fontSize-14 ms-fontWeight-semilight',
        text: organizer.emailAddress.name
      }).append($('<i/>', {
        class: 'ms-Icon ms-Icon--PartyLeader',
        style: 'margin-right: 10px;'
      }));
    }
    
    function renderTimeSpan(start, end) {
      return $('<div/>', {
        class: 'ms-fontSize-14 ms-fontWeight-semilight',
        text: `${formatDateTime(start.dateTime)} - ${formatDateTime(end.dateTime)}`
      }).append($('<i/>', {
        class: 'ms-Icon ms-Icon--DateTime2',
        style: 'margin-right: 10px;'
      }));
    }
    
    function formatDateTime(dateTime) {
      const date = new Date(dateTime);
    
      // Format like 10/14/2020 4:00 PM
      let hours = date.getHours();
      const minutes = date.getMinutes();
      const ampm = hours >= 12 ? 'PM' : 'AM';
      hours = hours % 12;
      hours = hours ? hours : 12;
      const minStr = minutes < 10 ? `0${minutes}` : minutes;
    
      return `${date.getMonth()+1}/${date.getDate()}/${date.getFullYear()} ${hours}:${minStr} ${ampm}`;
    }
    
    function renderLocation(location) {
      if (!location || location.displayName.length <= 0) {
        return null;
      }
    
      return $('<div/>', {
        class: 'ms-fontSize-14 ms-fontWeight-semilight',
        text: location.displayName
      }).append($('<i/>', {
        class: 'ms-Icon ms-Icon--MapPin',
        style: 'margin-right: 10px;'
      }));
    }
    
  2. Substitua a função renderCalendar existente pelo seguinte.Replace the existing renderCalendar function with the following.

    function renderCalendar(events) {
      $('#tab-container').empty();
    
      // Add title
      $('<div/>', {
        class: 'tab-title ms-fontSize-42',
        text: 'Week at a glance'
      }).appendTo('#tab-container');
    
      // Render each event
      events.map(event => {
        const eventCard = $('<div/>', {
          class: 'event-card ms-depth-4',
        });
    
        eventCard.append(renderSubject(event.subject));
        eventCard.append(renderOrganizer(event.organizer));
        eventCard.append(renderTimeSpan(event.start, event.end));
    
        const location = renderLocation(event.location);
        if (location) {
          eventCard.append(location);
        }
    
        eventCard.appendTo('#tab-container');
      });
    }
    
  3. Salve suas alterações e reinicie o aplicativo.Save your changes and restart the app. Atualize a guia no Microsoft Teams.Refresh the tab in Microsoft Teams. O aplicativo exibe eventos no calendário do usuário.The app displays events on the user's calendar.

    Uma captura de tela do aplicativo exibindo o calendário do usuário