Учебное пособие: создание приложения OneNote

Область применения: пользовательские записные книжки в OneDrive и корпоративные записные книжки в Office 365.

В этом учебном пособии показано, как создать простое приложение, которое использует API OneNote для получения и создания содержимого OneNote. Приложение, которое мы создадим, выполняет два вызова с использованием API OneNote REST:

  • Получить имя и ид из 10 последних измененных разделов.

    GET ../notes/sections?select=name,id&top=10&orderby=lastModifiedTime%20desc

  • Создание страницы в определенном разделе.

    POST ../notes/sections/{id}/pages

Выберите свою платформу:

Примечание

Это пособие призван продемонстрировать, как получить доступ к API OneNote, но он не содержит готового к выпуску кода. При создании приложения внимательно изучите свой код для потенциальной безопасности, проверки и других вопросов, связанных с качеством кода.

Создайте приложение OneNote для iOS

Приложение использует OneDrive SDK для iOS для обработки аутентификации и сетевых вызовов.

Необходимые компоненты

Вот что вам нужно, чтобы следовать этому руководству:

Создать приложение OneNote для iOS

  1. Создать проект
  2. Добавьте зависимость OneDrive SDK
  3. Создайте пользовательский интерфейс
  4. Добавьте поддержку проверки подлинности
  5. Вызовите API OneNote

Полный пример кода для ключевых файлов примеров включен в конце руководства.

Создайте проект в Xcode

  1. В Xcode создайте проектПриложение с одним представлением для iOS с именем OneNote-iOS-App. Выберите Цель C и выберите устройства iPhone.

  2. После создания проекта закройте Xcode. После создания подфайла вы откроете рабочее пространство.

Добавьте зависимость OneDrive SDK

Приложение в этом руководстве использует OneDrive SDK для обеих учетных записей Microsoft (ранее Live Connect) и проверку подлинности Azure Active Directory. Проверка подлинности учетной записи Microsoft используется для доступа к пользовательским записным книжкам OneDrive. Проверка подлинности с использованием Azure AD используется для доступа к корпоративным записным книжкам в Office 365.

  1. Запустите эти команды в терминале, чтобы создать подфайл и открыть файл в Xcode.

    cd {path to the OneNote-iOS-App project directory} 
    touch podfile 
    open -a xcode podfile 
    
  2. Добавьте зависимость OneDrive SDK к подфайлу и сохраните файл.

    pod 'OneDriveSDK'
    
  3. Запустите эти команды в терминале, чтобы установить зависимость и открыть рабочую область проекта в Xcode. При завершении установки вы должны получить подтверждение.

    pod install
    open onenote-ios-app.xcworkspace/
    

Приложения Xcode 7, предназначенные для iOS 9.0

Если вы нацеливаете iOS 9 на Xcode 7, вам нужно включить исключения PFS. См. раздел Безопасность перемещения приложений для мобильных устройств iOS 9 в OneDrive SDK для iOS readme для инструкций.

Создайте пользовательский интерфейс

Добавьте средство выбора, которое отображает 10 последних измененных разделов и кнопку, которая создает страницу OneNote в выбранном разделе.

  1. В Xcode откройте Main.storyboard и измените класс размера элемента (под холстом) в wCompact/hAny.

  2. Перетащите представление средства выбора и кнопку из библиотеки объектов в холст. Используйте Создать страницу для текста кнопки.

  3. Создание подключений для представления средства выбора:
    А. Перетащите представление средства выбора на значок Контроллер представления над холстом. Выберите выход dataSource.
    Б. Повторите для выхода делегат .
    В. Выберите Просмотр> Помощники редакторов> Показать помощник редактора и откройте ViewController.h во втором окне.
    Г. Перетащите вид средства выбора в холсте в кодовый блок @interface. Введите подключениеВыход под названием sectionPicker.

  4. Создайте подключения для кнопки:
    А. Перетащите кнопку в холсте в кодовый блок @interface.**** Введите подключение Выход под названием createPageButton.
    Б. Откройте ViewController.m в помощнике редактора.
    В. Перетащите кнопку в холсте в кодовый блок @implementation. Введите подключение Действие с именем createPage для событияОкончание нажатие на кнопку .

  5. Объявите протоколы UIPickerViewDelegate и UIPickerViewDataSource.

    ViewController.h должен выглядеть следующим образом:

     import <UIKit/UIKit.h>
    
     @interface ViewController : UIViewController<UIPickerViewDelegate, UIPickerViewDataSource>
    
     @property (weak, nonatomic) IBOutlet UIPickerView *sectionPicker;
     @property (weak, nonatomic) IBOutlet UIButton *createPageButton;
    
     @end
    
  6. В ViewController.m добавьте следующие методы делегата для представления выбора.

     #pragma mark - Delegate Methods
    -(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
        return 1;
    }
    
    -(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
        return sectionNamesForPicker.count;
    }
    
    -(NSString *)pickerView:(UIPickerView*)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
        return [sectionNamesForPicker objectAtIndex:row];
    }
    

    Не беспокойтесь об ошибках для sectionNamesForPicker. Мы добавим переменную позже.

  7. В методеviewDidLoad добавьте следующий код для подключения средства выбора после строки [super viewDidLoad].

     self.sectionPicker.delegate = self;
     self.sectionPicker.dataSource = self;
    

Добавьте поддержку проверки подлинности

OneDrive SDK обрабатывает проверку подлинности и авторизацию для вас. Вам просто нужно предоставить идентификаторы для вашего приложения, а затем использовать ODClient. SDK вызывает пользовательский интерфейс входа при первом запуске приложения, а затем сохраняет информацию об учетной записи. (Узнайте больше об авторизации в SDK).

  1. В AppDelegate.m импортируйте OneDrive SDK.

     #import <OneDriveSDK/OneDriveSDK.h>
    
  2. Заменить метод didFinishLaunchingWithOptions на следующий код.

    Затем замените значения свойств заполнителя информацией для зарегистрированных вами приложений. Если вы тестируете только одно приложение, вы можете закомментировать свойства, которые вы не используете.

      (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
         // Set the client ID and permission scopes of your app registered on the Microsoft account Developer Center.
         static NSString *const msaClientId = @"000000001A123456";
         static NSString *const msaScopesString = @"wl.signin,wl.offline_access,office.onenote_update";
    
         // Set the client ID and redirect URI of your app registered on the Azure Management Portal.
         static NSString *const aadClientId = @"0b18d05c-386d-4133-b481-az1234567890";
         static NSString *const aadRedirectUri = @"https://localhost/";
    
         // Set properties on the ODClient.
         NSArray *const msaScopes = [msaScopesString componentsSeparatedByString:@","];
         [ODClient setMicrosoftAccountAppId:msaClientId
                                     scopes:msaScopes];
    
         [ODClient setActiveDirectoryAppId:aadClientId
                                capability:@"Notes"
                               redirectURL:aadRedirectUri];
         return YES;
     }
    

    Примечание

    Это приложение позволяет вам войти в систему с одной учетной записью за раз (учетная запись Microsoft, рабочая или школьная учетная запись). Чтобы узнать, как поддерживать оба типа учетных записей и хранить несколько учетных записей, см. образец CloudRoll.

  3. В ViewController.h импортируйте OneDrive SDK и объявите свойство для объекта ODClient. Все вызовы SDK выполняются через объект ODClient.

    А. Добавьте выписку импорта:

      #import <OneDriveSDK/OneDriveSDK.h>
    

    Б. Добавьте свойствоклиента в кодовый блок @interfaceс.

      @property (strong, nonatomic) ODClient *client;
    
  4. В ViewController.m добавьте следующий код в конце метода viewDidLoad для получения ODClient, прошедшего проверку пользованности.

    SDK вызывает пользовательский интерфейс входа при первом запуске приложения, а затем сохраняет информацию об учетной записи.

         [ODClient clientWithCompletion:^(ODClient *odClient, NSError *error) {
             if (!error){
                 self.client = odClient;
                 [self getSections];
             }
             else {
                 NSLog(@"Error with auth: %@", [error localizedDescription]);
             }
         }];
    

    Мы добавим метод getSections в следующем разделе.

  5. В ViewController.m добавьте метод sendRequest в кодовый блок @implementation.

    Этот метод добавляет требуемый заголовок Авторизация в запросы разделов GET и страниц POST и создает задачу передачи данных.

     // Send the request.
     - (void)sendRequest:(NSMutableURLRequest *)request {
    
         // Add the required Authorization header with access token.
         [self.client.authProvider appendAuthHeaders:request completion:^(NSMutableURLRequest *requests, NSError *error) {
    
             // This app also uses the OneDrive SDK to send HTTP requests.
             [[self.client.httpProvider dataTaskWithRequest:(request)
                     completionHandler:^(NSData *data,
                     NSURLResponse *response,
                     NSError *error) {
                         [self handleResponse:data response:response error:error];
             }] resume];
         }];
     }
    

Теперь вы готовы совершать звонки в службу OneNote.

Вызовите API OneNote

Когда приложение загружается, оно получает имя и идентификатор 10 последних измененных разделов и заполняет средство выбора именами разделов. Новая страница создается в выбранном разделе.

  1. В ViewController.h добавьте свойства, которые сохраняют ответ.

    // Variables to store the response data.
    @property (strong, nonatomic) NSHTTPURLResponse *returnResponse;
    @property (strong, nonatomic) NSMutableData *returnData;
    

    Добавьте весь код в следующие шаги к блоку кода @реализация в ViewController.m. Не беспокойтесь об ошибках, которые вы видите во время создания приложения. После завершения кода они исчезнут.

  2. В ViewController.m добавьте переменные для корневого URL-адреса службы OneNote, словарь для имен разделов и идентификаторов, а также массив имен разделов, которые будут заполнять средство выбора.

    static NSString const *serviceRootUrl = @"https://www.onenote.com/api/v1.0/me/notes/";
    NSMutableDictionary *sectionNamesAndIds;
    NSArray *sectionNamesForPicker;
    
  3. Добавьте метод getSections для построения запроса разделы GET.

     // Build the "GET sections" request.
     - (void)getSections {
    
         // Construct the request URI and the request.
         NSString *sectionsEndpoint =
                 [serviceRootUrl stringByAppendingString:@"sections?select=name,id&top=10&orderby=lastModifiedTime%20desc"];
         NSMutableURLRequest *request =
                 [[NSMutableURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:sectionsEndpoint]];
         request.HTTPMethod = @"GET";
         if (self.client)
         {
    
             // Send the HTTP request.
             [self sendRequest:request];
         }
         _createPageButton.enabled = false;
     }
    
  4. Добавьте метод handleResponse для обработки ответа от разделов GET, а также запросов страниц POST.

    // Handle the response.
    - (void)handleResponse:(NSData *)data response:(NSURLResponse *)response error:(NSError *) error {
    
        // Log the response.
        NSLog(@"Response %@ with error %@.\n", response, error);
        NSString *stringData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"Body: %@.\n", stringData);
    
        // Store the response.
        self.returnData = [[NSMutableData alloc] init];
        NSMutableData *convertedData = [data mutableCopy];
        [self.returnData appendData:convertedData];
        self.returnResponse = (NSHTTPURLResponse *)response;
    
        NSInteger status = [self.returnResponse statusCode];
    
        // Check for "GET sections" success.
        if (status == 200) {
            NSLog(@"Sections retrieved!\n");
    
            // Get the section data and populate the picker.
            [self getSectionNamesAndIds];
        }
    
        // Check for "POST pages" success.
        else if (status == 201) {
            NSLog(@"Page created!\n");
    
            // Get the page object and parse out some properties.
            NSDictionary *pageProperties = [self convertData];
            NSString *selfLink = [pageProperties objectForKey:@"self"];
            NSDictionary *links = [pageProperties objectForKey:@"links"];
            NSString *clientUrl = [[links objectForKey:@"oneNoteClientUrl"] objectForKey:@"href"];
            NSString *webUrl = [[links objectForKey:@"oneNoteWebUrl"] objectForKey:@"href"];
            NSLog(@"Link to new page endpoint: %@\n", selfLink);
            NSLog(@"Link open page in the installed client: %@\n", clientUrl);
            NSLog(@"Link to open page in OneNote Online: %@\n", webUrl);
        }
        else {
            NSLog(@"Status code: %ld. Check the logged response for more information.", (long)status);
        }
    }
    
  5. Добавьте метод convertData для преобразования данных ответа в JSON.

    // Get the OneNote entity data from the response.
    - (NSDictionary *)convertData {
    
        // Convert the message body to JSON.
        NSError *parseError;
        NSDictionary *data = [NSJSONSerialization JSONObjectWithData:self.returnData options:kNilOptions error:&parseError];
    
        if (!parseError) {
            return data;
        }
        else {
            NSLog(@"Error parsing response: %@", [parseError localizedDescription]);
            return nil;
        }
    }
    
  6. Добавьте метод getSectionNamesAndIds для хранения имен разделов и идентификаторов и заполнения средства выбора.

    // Store the section names and IDs, and populate the section picker.
    - (void)getSectionNamesAndIds {
    
        // Get the "value" array that contains the returned sections.
        NSDictionary *results = [self convertData];
    
        // Add the name-id pairs to sectionNamesAndIds, which is used to map section names to IDs.
        if ([results objectForKey:@"value"] != nil) {
            NSDictionary *sections =[results objectForKey:@"value"];
            sectionNamesAndIds = [[NSMutableDictionary alloc] init];
            for (NSMutableDictionary *dict in sections) {
                NSString *sectionName = [dict objectForKey:@"name"];
                NSString *sectionId = [dict objectForKey:@"id"];
                sectionNamesAndIds[sectionName] = sectionId;
            }
        }
    
        // Populate the picker with the section names.
        sectionNamesForPicker = [sectionNamesAndIds allKeys];
        dispatch_async(dispatch_get_main_queue(), ^{[_sectionPicker reloadComponent:0];});
    
        _createPageButton.enabled = true;
    }
    
  7. Отредактируйте метод createPage, который был создан для вас, когда вы добавили действие кнопки. Этот код создает простую HTML-страницу.

    // Create a simple page.
    - (IBAction)createPage:(id)sender {
    
        // Get the ID of the section that's selected in the picker.
        NSInteger row = [self.sectionPicker selectedRowInComponent:0];
        NSString *selectedSectionName = sectionNamesForPicker[row];
        NSString *selectedSectionId = sectionNamesAndIds[selectedSectionName];
    
        // Construct the request URI and the request.
        NSString *pagesEndpoint = [NSString stringWithFormat:@"sections/%@/pages", selectedSectionId];
        NSString *fullEndpoint = [serviceRootUrl stringByAppendingString:pagesEndpoint];
        NSString *date = [self formatDate];
        NSString *simpleHtml = [NSString stringWithFormat:@"<html>"
                                "<head>"
                                "<title>A page created from simple HTML from iOS</title>"
                                "<meta name=\"created\" content=\"%@\" />"
                                "</head>"
                                "<body>"
                                "<p>This is some <b>simple</b> <i>formatted</i> text.</p>"
                                "</body>"
                                "</html>", date];
    
        NSData *presentation = [simpleHtml dataUsingEncoding:NSUTF8StringEncoding];
        NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:fullEndpoint]];
        request.HTTPMethod = @"POST";
        request.HTTPBody = presentation;
        [request addValue:@"text/html" forHTTPHeaderField:@"Content-Type"];
        if (self.client)
        {
    
            // Send the HTTP request.
            [self sendRequest:request];
        }
    }
    
  8. Добавьте метод FormatDate для получения даты, отформатированной по ISO 8601 для метатега timestamp.

    // Format the "created" date. OneNote requires the ISO 8601 format.
    - (NSString *)formatDate {
        NSDate *now = [NSDate date];
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        NSLocale *enUSPOSIXLocale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
        [dateFormatter setLocale:enUSPOSIXLocale];
        [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"];
        return [dateFormatter stringFromDate:now];
    }
    

После того, как вы создали приложение, вы можете протестировать его, запустив его на iPhone или эмуляторе iPhone. Войдите в систему, используя учетную запись Microsoft, рабочую или учебную учетную запись.

Когда приложение откроется, выберите раздел, в котором вы хотите создать страницу, а затем выберите Создать страницу. Затем проверьте окно вывода в Xcode для сообщений журнала. Если вызовы работают, в окне вывода будет отображаться URI ресурса новой страницы и ссылки, чтобы открыть страницу в OneNote.

Дальнейшие действия

Добавьте функциональность, проверку ввода и обработку ошибок.

Например, добавьте кнопку выхода, которая вызывает этот метод:

- (IBAction)signOut:(UIButton *)sender  {
    [self.client signOutWithCompletion:^(NSError *signOutError) {
        self.client = nil;
        NSLog(@"Logged out.");
    }];
}

См. раздел Разработка с помощью API OneNote, чтобы узнать больше о том, что вы можете сделать с API OneNote.

Полные примеры кода для iOS

AppDelegate.m

#import "AppDelegate.h"
#import <OneDriveSDK/OneDriveSDK.h>

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // Set the client ID and permission scopes of your app registered on the Microsoft account Developer Center.
    static NSString *const msaClientId = @"000000001A123456";
    static NSString *const msaScopesString = @"wl.signin,wl.offline_access,office.onenote_update";

    // Set the client ID and redirect URI of your app registered on the Azure Management Portal.
    static NSString *const aadClientId = @"0b18d05c-386d-4133-b481-az1234567890";
    static NSString *const aadRedirectUri = @"https://localhost/";

    // Set properties on the ODClient.
    NSArray *const msaScopes = [msaScopesString componentsSeparatedByString:@","];
    [ODClient setMicrosoftAccountAppId:msaClientId
                                scopes:msaScopes];

    [ODClient setActiveDirectoryAppId:aadClientId
                           capability:@"Notes"
                          redirectURL:aadRedirectUri];
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end

ViewController.h

#import <UIKit/UIKit.h>
#import <OneDriveSDK/OneDriveSDK.h>

@interface ViewController : UIViewController<UIPickerViewDelegate, UIPickerViewDataSource>

@property (strong, nonatomic) ODClient *client;

// Variables to store the response data.
@property (strong, nonatomic) NSHTTPURLResponse *returnResponse;
@property (strong, nonatomic) NSMutableData *returnData;

// Outlet connections for controls.
@property (weak, nonatomic) IBOutlet UIPickerView *sectionPicker;
@property (weak, nonatomic) IBOutlet UIButton *createPageButton;

@end

ViewController.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

static NSString const *serviceRootUrl = @"https://www.onenote.com/api/v1.0/me/notes/";
NSMutableDictionary *sectionNamesAndIds;
NSArray *sectionNamesForPicker;

- (void)viewDidLoad {
    [super viewDidLoad];

    self.sectionPicker.delegate = self;
    self.sectionPicker.dataSource = self;

    [ODClient clientWithCompletion:^(ODClient *odClient, NSError *error) {
        if (!error){
            self.client = odClient;
            [self getSections];
        }
        else {
            NSLog(@"Error with auth: %@", [error localizedDescription]);
        }
    }];
}

// Build the "GET sections" request.
- (void)getSections {

    // Construct the request URI and the request.
    NSString *sectionsEndpoint =
            [serviceRootUrl stringByAppendingString:@"sections?select=name,id&top=10&orderby=lastModifiedTime%20desc"];
    NSMutableURLRequest *request =
            [[NSMutableURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:sectionsEndpoint]];
    request.HTTPMethod = @"GET";
    if (self.client)
    {

        // Send the HTTP request.
        [self sendRequest:request];
    }
    _createPageButton.enabled = false;
}

// Send the request.
- (void)sendRequest:(NSMutableURLRequest *)request {

    // Add the required Authorization header with access token.
    [self.client.authProvider appendAuthHeaders:request completion:^(NSMutableURLRequest *requests, NSError *error) {

        // This app also uses the OneDrive SDK to send HTTP requests.
        [[self.client.httpProvider dataTaskWithRequest:(request)
                completionHandler:^(NSData *data,
                NSURLResponse *response,
                NSError *error) {
                    [self handleResponse:data response:response error:error];
        }] resume];
    }];
}

// Store the section names and IDs, and populate the section picker.
- (void)getSectionNamesAndIds {

    // Get the "value" array that contains the returned sections.
    NSDictionary *results = [self convertData];

    // Add the name-id pairs to sectionNamesAndIds, which is used to map section names to IDs.
    if ([results objectForKey:@"value"] != nil) {
        NSDictionary *sections =[results objectForKey:@"value"];
        sectionNamesAndIds = [[NSMutableDictionary alloc] init];
        for (NSMutableDictionary *dict in sections) {
            NSString *sectionName = [dict objectForKey:@"name"];
            NSString *sectionId = [dict objectForKey:@"id"];
            sectionNamesAndIds[sectionName] = sectionId;
        }
    }

    // Populate the picker with the section names.
    sectionNamesForPicker = [sectionNamesAndIds allKeys];
    dispatch_async(dispatch_get_main_queue(), ^{[_sectionPicker reloadComponent:0];});

    _createPageButton.enabled = true;
}

// Get the OneNote entity data from the response.
- (NSDictionary *)convertData {

    // Convert the message body to JSON.
    NSError *parseError;
    NSDictionary *data = [NSJSONSerialization JSONObjectWithData:self.returnData options:kNilOptions error:&parseError];

    if (!parseError) {
        return data;
    }
    else {
        NSLog(@"Error parsing response: %@", [parseError localizedDescription]);
        return nil;
    }
}

// Handle the response.
- (void)handleResponse:(NSData *)data response:(NSURLResponse *)response error:(NSError *) error {

    // Log the response.
    NSLog(@"Response %@ with error %@.\n", response, error);
    NSString *stringData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"Body: %@.\n", stringData);

    // Store the response.
    self.returnData = [[NSMutableData alloc] init];
    NSMutableData *convertedData = [data mutableCopy];
    [self.returnData appendData:convertedData];
    self.returnResponse = (NSHTTPURLResponse *)response;

    NSInteger status = [self.returnResponse statusCode];

    // Check for "GET sections" success.
    if (status == 200) {
        NSLog(@"Sections retrieved!\n");

        // Get the section data and populate the picker.
        [self getSectionNamesAndIds];
    }

    // Check for "POST pages" success.
    else if (status == 201) {
        NSLog(@"Page created!\n");

        // Get the page object and parse out some properties.
        NSDictionary *pageProperties = [self convertData];
        NSString *selfLink = [pageProperties objectForKey:@"self"];
        NSDictionary *links = [pageProperties objectForKey:@"links"];
        NSString *clientUrl = [[links objectForKey:@"oneNoteClientUrl"] objectForKey:@"href"];
        NSString *webUrl = [[links objectForKey:@"oneNoteWebUrl"] objectForKey:@"href"];
        NSLog(@"Link to new page endpoint: %@\n", selfLink);
        NSLog(@"Link open page in the installed client: %@\n", clientUrl);
        NSLog(@"Link to open page in OneNote Online: %@\n", webUrl);
    }
    else {
        NSLog(@"Status code: %ld. Check the logged response for more information.", (long)status);
    }
}

// Create a simple page.
- (IBAction)createPage:(id)sender {

    // Get the ID of the section that's selected in the picker.
    NSInteger row = [self.sectionPicker selectedRowInComponent:0];
    NSString *selectedSectionName = sectionNamesForPicker[row];
    NSString *selectedSectionId = sectionNamesAndIds[selectedSectionName];

    // Construct the request URI and the request.
    NSString *pagesEndpoint = [NSString stringWithFormat:@"sections/%@/pages", selectedSectionId];
    NSString *fullEndpoint = [serviceRootUrl stringByAppendingString:pagesEndpoint];
    NSString *date = [self formatDate];
    NSString *simpleHtml = [NSString stringWithFormat:@"<html>"
                            "<head>"
                            "<title>A page created from simple HTML from iOS</title>"
                            "<meta name=\"created\" content=\"%@\" />"
                            "</head>"
                            "<body>"
                            "<p>This is some <b>simple</b> <i>formatted</i> text.</p>"
                            "</body>"
                            "</html>", date];

    NSData *presentation = [simpleHtml dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:fullEndpoint]];
    request.HTTPMethod = @"POST";
    request.HTTPBody = presentation;
    [request addValue:@"text/html" forHTTPHeaderField:@"Content-Type"];
    if (self.client)
    {

        // Send the HTTP request.
        [self sendRequest:request];
    }
}

// Format the "created" date. OneNote requires the ISO 8601 format.
- (NSString *)formatDate {
    NSDate *now = [NSDate date];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    NSLocale *enUSPOSIXLocale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
    [dateFormatter setLocale:enUSPOSIXLocale];
    [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"];
    return [dateFormatter stringFromDate:now];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Delegate Methods
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
    return 1;
}

-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    return sectionNamesForPicker.count;
}

-(NSString *)pickerView:(UIPickerView*)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
    return [sectionNamesForPicker objectAtIndex:row];
}
@end

Создание приложения OneNote для ASP.NET MVC

Это веб-приложение использует Библиотеку проверки подлинности Azure Active Directory (ADAL) для .NET. для проверки подлинности рабочих и учебных учетных записей от нескольких клиентов.

Необходимые компоненты

Вот что вам нужно, чтобы следовать этому руководству:

  • Visual Studio 2015. Вы можете использовать бесплатную версию Visual Studio Community.
  • Веб-приложение, зарегистрированное на портале управления Azure, со следующими делегированными разрешениями:
    • Вход и чтение профиля пользователя для Windows Azure Active Directory
    • Просмотр и изменение записных книжек OneNote для OneNote

Примечание

Visual Studio регистрирует веб-приложение для вас во время создания приложения, но вам все равно придется добавлять разрешения для OneNote и генерировать ключ приложения. (Узнайте больше о регистрации приложений).

Создать приложение OneNote с помощью ASP.NET MVC

  1. Создать проект
  2. Добавьте библиотеку ADAL для .NET
  3. Создайте пользовательский интерфейс
  4. Добавьте поддержку проверки подлинности
  5. Вызовите API OneNote

Полный пример кода для ключевых файлов примеров включен в конце руководства.

Создать проект в Visual Studio

  1. В Visual Studio создайте проект Веб-приложение ASP.NET с именем OneNote-WebApp.

  2. Выберите шаблон MVC и убедитесь, что MVC выбран для параметраДобавление папок и основных ссылок.

  3. Выберите Изменить проверку подлинности, а затем выберите Рабочие и учебные учетные записи.

  4. Выберите Облако - Несколько организаций и введите доменное имя вашего клиента разработчика (например, contoso.onmicrosoft.com).

Вы можете сохранить или очистить узел Microsoft Azure в облаке по желанию. Это не требуется для данного руководства. Все остальные настройки необходимо оставить по умолчанию.

Visual Studio регистрирует веб-приложение с помощью Azure для вас, но вам нужно закончить его настройку в портале управления Azure.

  1. В вашем клиентском справочнике на портале выберите Приложения и нажмите OneNote-Веб приложение, чтобы открыть страницу конфигурации.

  2. В разделе Ключи выберите длительность для нового ключа.

  3. В разделе Разрешения на другие приложения добавьте приложение OneNote, а затем добавьте делегированное разрешение Просмотр и изменение записных книжек OneNote. (узнать больше)

  4. Сохраните изменения в приложении и сделайте копию нового ключа до закрытия портала. Она вам скоро понадобится.

Добавьте ADAL для .NET.

Приложение использует Библиотеку проверки подлинности Active Directory (ADAL) для проверки подлинности и авторизации Azure AD. Приложение было создано с использованием версии 2.19.208020213.

  1. В Visual Studio выберите Инструменты> Диспетчер пакетов NuGet> Консоль диспетчера пакетов и выполните следующую команду в консоли.

    Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory
    

Создайте пользовательский интерфейс

Это приложение использует два представления для HomeController: Index.cshtml и Page.cshtml.

  1. Заменить содержимое Views/Home/Index.cshtml следующим кодом. Это добавляет раскрывающийся список для выбора родительского раздела, текстового поля для ввода имени страницы и кнопки.

    @model OneNote_WebApp.Models.SectionsViewModel
    
    @{
        ViewBag.Title = "Index";
    }
    
    <h2>OneNote ASP.NET MVC web application</h2>
    
    @Html.Label("Choose a section to create the page in.")
    
    @using (Html.BeginForm("CreatePageAsync", "Home", new AjaxOptions { UpdateTargetId = "create-page" }))
    {
        <div id="create-page">
            @Html.DropDownListFor(
                m => m.SectionId,
                new SelectList(Model.Sections, "Id", "Name", Model.SectionId))
            @Html.ValidationMessageFor(m => m.SectionId)
            <br />
            <br />
            <table>
                <tr>
                    <td>
                        @Html.Label("Enter a name for the new page.")
                        <br />
                        @Html.TextBox("page-name", null, new { @style = "width=80" })
                    </td>
                </tr>
            </table>
            <button>Create page</button>
        </div>
    }
    
  2. В папке Views/Home создайте новое представление с именем Страница и добавьте следующий код. В этом представлении отображаются свойства для вновь созданной страницы.

    @model OneNote_WebApp.Models.PageViewModel
    
    @{
         ViewBag.Title = "Page";
    }
    
    <h2>Page: @Model.Title</h2>
    
    <table>
        <tr>
            <td>@Html.Label("Self link: ")</td>
            <td>@Model.Self</td>
        </tr>
        <tr>
            <td>@Html.Label("Native client link: ")</td>
            <td><a href="@Model.PageLinks.ClientUrl">@Model.PageLinks.ClientUrl</a></td>
        </tr>
        <tr>
            <td>@Html.Label("Web client link: ")</td>
            <td><a href="@Model.PageLinks.WebUrl">@Model.PageLinks.WebUrl</a></td>
        </tr>
    </table>
    

Добавьте поддержку проверки подлинности

Клиентская библиотека ADAL для .NET обрабатывает процесс проверки подлинности и авторизации. Вам просто нужно предоставить идентификаторы для вашего приложения и добавить пару вызовов.

  1. В корневой файл Web.config добавьте следующие пары ключ/значение в узел appSettings. Обратите внимание, что ClientId и AADInstance уже добавлены Visual Studio.

    <add key="ida:AppKey" value="ENTER-your-app-key-here" />
    <add key="ida:OneNoteResourceId" value="https://onenote.com/" />
    
  2. Замените значение заполнителя для ключа приложения ключом, сгенерированным ранее.

  3. В App_Start / Start.Auth.cs добавьте следующее с помощьювыписки.

    using Microsoft.IdentityModel.Clients.ActiveDirectory;
    
  4. Заменить глобальные переменные в классе Запуск на следующий код. Метод GetAuthorizedClient в HomeController также использует четыре общедоступные переменные.

    public static string ClientId = ConfigurationManager.AppSettings["ida:ClientId"];
    public static string AppKey = ConfigurationManager.AppSettings["ida:AppKey"];
    public static string AADInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
    public static string OneNoteResourceId = ConfigurationManager.AppSettings["ida:OneNoteResourceId"];
    private string Authority = AADInstance + "common"; 
    
  5. В методе ConfigureAuth замените метод app.UseOpenIdConnectAuthentication со следующим кодом. ADAL хранит маркеры и другую информацию в кэше маркера. (Чтобы посмотреть, что кэшируется, добавьте эту строку перед возвратом задачи: var cache = context.TokenCache.ReadItems();)

    app.UseOpenIdConnectAuthentication(
       new OpenIdConnectAuthenticationOptions
       {
           ClientId = ClientId,
           Authority = Authority,
           TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
           {
               ValidateIssuer = false
           },
           Notifications = new OpenIdConnectAuthenticationNotifications()
           {
                AuthorizationCodeReceived = (context) =>
                {
                    var code = context.Code;
                    ClientCredential credential = new ClientCredential(ClientId, AppKey);
                    Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext authContext =
                       new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(Authority);
                    AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
                        code,
                        new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)),
                        credential,
                        OneNoteResourceId
                    );
                    return Task.FromResult(0);
                },
                AuthenticationFailed = (context) =>
                {
                    context.HandleResponse();
                    if (context.Exception.HResult == -2146233088) //IDX10311: Nonce is null
                    {
                        context.OwinContext.Response.Redirect("Home/Index");
                    }
                    return Task.FromResult(0);
                }
            }
        });
    
  6. В Controllers/HomeController.cs добавить следующее с помощью заявлений.

    using Microsoft.IdentityModel.Clients.ActiveDirectory;
    using Microsoft.Owin.Security;
    using Microsoft.Owin.Security.OpenIdConnect;
    using Newtonsoft.Json;
    using System.IO;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Security.Claims;
    using System.Text;
    using System.Threading.Tasks;
    using OneNote_WebApp.Models;
    
  7. В классе HomeController добавьте метод GetAuthorizedClient. Этот метод создает и настраивает HttpClient, используемый для отправки запросов REST службе OneNote. Он также получает маркер доступа и добавляет его клиенту.

    private HttpClient GetAuthorizedClient()
    {
        HttpClient client = new HttpClient();
    
        string userObjectId = ClaimsPrincipal.Current.FindFirst("https://schemas.microsoft.com/identity/claims/objectidentifier").Value;
        string tenantId = ClaimsPrincipal.Current.FindFirst("https://schemas.microsoft.com/identity/claims/tenantid").Value;
        ClientCredential credential = new ClientCredential(Startup.ClientId, Startup.AppKey);
        AuthenticationContext authContext = new AuthenticationContext(Startup.AADInstance + tenantId);
    
        try
        {
            // Call AcquireTokenSilent to get the access token. This first tries to get the token from cache.
            AuthenticationResult authResult = authContext.AcquireTokenSilent(
                Startup.OneNoteResourceId,
                credential,
                new UserIdentifier(userObjectId, UserIdentifierType.UniqueId));
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        }
        catch (AdalSilentTokenAcquisitionException)
        {
            HttpContext.GetOwinContext().Authentication.Challenge(
                new AuthenticationProperties() { RedirectUri = "/" },
                OpenIdConnectAuthenticationDefaults.AuthenticationType);
            return null;
        }
    
        return client;
    }
    

Теперь вы готовы совершать звонки в службу OneNote и анализировать ответ.

Вызовите API OneNote

Когда приложение загружается, оно получает имя и идентификатор 10 последних измененных разделов и заполняет раскрывающийся список именами разделов. Новая страница OneNote создается в выбранном разделе.

  1. В классе HomeController добавьте глобальные переменные для конечных точек OneNote и путь к файлу изображения для добавления на новую страницу.

    public static string OneNoteRoot = "https://www.onenote.com/api/v1.0/me/notes/";
    public static string SectionsEndpoint = "sections?select=name,id&top=10&orderby=lastModifiedTime%20desc";
    public static string PagesEndpoint = "sections/{0}/pages";
    public static string PathToImageFile = @"C:\<local-path>\logo.png";
    
  2. Измените путь заполнителя и имя файла в PathToImageFile, чтобы указать на локальное изображение PNG.

  3. Заменить метод Индекс на следующий код. Это поможет получить разделы, подготовит SectionsViewModel для представления индекса и загрузит представление.

    public async Task<ActionResult> Index()
    {
        SectionsViewModel viewModel = new SectionsViewModel();
        try
        {
            viewModel.Sections = await GetSectionsAsync();
        }
        catch (Exception ex)
        {
            return View("Error", new HandleErrorInfo(new Exception(ex.Message), "Home", "GetSectionsAsync"));
        }
        return View(viewModel);
    }
    
  4. Добавьте метод построения и отправки GetSectionsAsync, отправьте запросРазделы GET запросить и анализируйте ответ.

    [Authorize]
    [HttpGet]   
    public async Task<IEnumerable<Section>> GetSectionsAsync()
    {
        List<Section> sections = new List<Section>();
    
        HttpClient client = GetAuthorizedClient();
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, OneNoteRoot + SectionsEndpoint);
        HttpResponseMessage response = await client.SendAsync(request);
        if (response.IsSuccessStatusCode)
        {
    
            // Parse the JSON response.
            string stringResult = await response.Content.ReadAsStringAsync();
            Dictionary<string, dynamic> result = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(stringResult);
            foreach (var item in result["value"])
            {
                var current = item.ToObject<Dictionary<string, string>>();
                Section section = new Section
                {
                    Name = current["name"],
                    Id = current["id"]
                };
                sections.Add(section);
            }
        }
        else
        {
            throw new Exception("Error getting sections: " + response.StatusCode.ToString());
        }
        return sections;
    }
    
  5. Добавьте метод CreatePageAsync для построения и отправки страницы POST составного запроса и для анализа ответа. Этот запрос создает простую HTML-страницу.

    [Authorize]
    [HttpPost]
    public async Task<ActionResult> CreatePageAsync()
    {
        HttpClient client = GetAuthorizedClient();
    
        // Get user input.
        string selectedSectionId = Request.Form["SectionId"];
        string pageName = Request.Form["page-name"];
        string pagesEndpoint = string.Format("sections/{0}/pages", selectedSectionId);
    
        // Define the page content, which includes an uploaded image.
        const string imagePartName = "imageBlock1";
        string iso8601Date = DateTime.Now.ToString("o");
        string pageHtml = "<html>" +
                          "<head>" +
                          "<title>" + pageName + "</title>" +
                          "<meta name=\"created\" content=\"" + iso8601Date + "\" />" +
                          "</head>" +
                          "<body>" +
                          "<h1>This is a page with an image</h1>" +
                          "<img src=\"name:" + imagePartName +
                          "\" alt=\"No mis monos\" width=\"250\" height=\"200\" />" +
                          "</body>" +
                          "</html>";
    
        HttpResponseMessage response;
    
        // Build the 'POST pages' request.
        var stream = new FileStream(PathToImageFile, FileMode.Open);
        using (var imageContent = new StreamContent(stream))
        {
            try
            {
                imageContent.Headers.ContentType = new MediaTypeHeaderValue("image/png");
                MultipartFormDataContent pageContent = new MultipartFormDataContent
                {
                    {new StringContent(pageHtml, Encoding.UTF8, "text/html"), "Presentation"},
                    {imageContent, imagePartName}
                };
    
                response = await client.PostAsync(OneNoteRoot + pagesEndpoint, pageContent);
                if (!response.IsSuccessStatusCode)
                {
                    throw new Exception(response.StatusCode + ": " + response.ReasonPhrase);
                }
                else
                {
    
                    // Parse the JSON response.
                    string stringResult = await response.Content.ReadAsStringAsync();
                    Dictionary<string, dynamic> pageData = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(stringResult);
                    Dictionary<string, dynamic> linksData = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(pageData["links"].ToString());
                    Links pageLinks = new Links
                    {
                        ClientUrl = new Uri(linksData["oneNoteClientUrl"]["href"].ToString()),
                        WebUrl = new Uri(linksData["oneNoteWebUrl"]["href"].ToString())
                    };
                    PageViewModel pageViewModel = new PageViewModel
                    {
                        Title = pageData["title"],
                        Self = new Uri(pageData["self"]),
                        PageLinks = pageLinks
                    };
                    return View("../home/page", pageViewModel);
                }
            }
            catch (Exception ex)
            {
                return View("Error", new HandleErrorInfo(new Exception(ex.Message), "Home", "CreatePageAsync"));
            }
        }
    }
    
  6. В папке «Модели» добавьте новый класс с именем Resource.cs и используйте следующий код. Это определяет модели домена, которые представляют разделы и страницы OneNote, и модели представления, которые представляют данные OneNote в представлениях Индекс и Страница .

    using System;
    using System.Collections.Generic;
    using System.IO;
    
    namespace OneNote_WebApp.Models
    {
    
        // Common properties of OneNote entities.
        public class Resource
        {
            public string Id { get; set; }
            public string CreatedBy { get; set; }
            public DateTimeOffset CreatedTime { get; set; }
            public string LastModifiedBy { get; set; }
            public DateTimeOffset LastModifiedTime { get; set; }
            public Uri Self { get; set; }
        }
    
        // A OneNote section with some key properties. 
        public class Section : Resource
        {
            public bool IsDefault { get; set; }
            public string Name { get; set; }
            public ICollection<Page> Pages { get; set; }
            public Uri PagesUrl { get; set; }
        }
    
        // A OneNote page with some key properties.
        // This app doesn't use the Page model.
        public class Page : Resource
        {
            public Stream Content { get; set; }
            public Uri ContentUrl { get; set; }
            public Links PageLinks { get; set; }
            public string Title { get; set; }
        }
    
        // The links that open a OneNote page in the installed client or in OneNote Online.
        public class Links
        {
            public Uri ClientUrl { get; set; }
            public Uri WebUrl { get; set; }
        }
    
        // The view model used to populate the section drop-down list.
        public class SectionsViewModel
        {
            public string SectionId { get; set; }
            public IEnumerable<Section> Sections { get; set; }
        }
    
        // The view model used to display properties of the new page.
        public class PageViewModel
        {
            public string Title { get; set; }
            public Uri Self { get; set; }
            public Links PageLinks { get; set; }
        }
    }
    

После того, как вы создали приложение, вы можете запустить его с помощью F5-отладки.

Если вы получите ошибку Не найдено сборки, содержащей OwinStartupAttribute ... добавьте следующий атрибут после с помощью в классе Startup.cs в корневом каталоге. (Узнайте больше об этой ошибке.)

[assembly: OwinStartup(typeof(OneNote_WebApp.Startup))]

Войдите в приложение, используя служебную или школьную учетную запись, в которой есть хотя бы один блокнот, содержащий хотя бы один раздел. В приложении выберите раздел, в котором вы хотите создать страницу, введите имя для новой страницы, а затем выберите Создать страницу. В случае успеха приложение отображает заголовок и имя пользователя, а также ссылки на страницы новой страницы.

Полные примеры кода для ASP.NET MVC

Startup.Auth.cs

using System;
using System.Configuration;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;
using Microsoft.IdentityModel.Clients.ActiveDirectory;

namespace OneNote_WebApp
{
    public partial class Startup
    {

        // Properties used for authorization.
        public static string ClientId = ConfigurationManager.AppSettings["ida:ClientId"];
        public static string AppKey = ConfigurationManager.AppSettings["ida:AppKey"];
        public static string AADInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
        public static string OneNoteResourceId = ConfigurationManager.AppSettings["ida:OneNoteResourceId"];
        private string Authority = AADInstance + "common";

        public void ConfigureAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions { });

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = ClientId,
                    Authority = Authority,
                    TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                    {
                        ValidateIssuer = false
                    },
                    Notifications = new OpenIdConnectAuthenticationNotifications()
                    {
                        AuthorizationCodeReceived = (context) =>
                        {
                            var code = context.Code;
                            ClientCredential credential = new ClientCredential(ClientId, AppKey);
                            Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext authContext =
                                new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(Authority);
                            AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
                                code,
                                new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)),
                                credential,
                                OneNoteResourceId
                            );
                            return Task.FromResult(0);
                        },
                        AuthenticationFailed = (context) =>
                        {
                            context.HandleResponse();
                            if (context.Exception.HResult == -2146233088) //IDX10311: Nonce is null
                            {
                                context.OwinContext.Response.Redirect("Home/Index");
                            }
                            return Task.FromResult(0);
                        }
                    }
                });
        }
    }
}

HomeController

using System;
using System.Collections.Generic;
using System.Web.Mvc;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OpenIdConnect;
using Newtonsoft.Json;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using OneNote_WebApp.Models;

namespace OneNote_WebApp.Controllers
{
    [Authorize]
    public class HomeController : Controller
    {

        // Route segments to OneNote resource endpoints.
        public static string OneNoteRoot = "https://www.onenote.com/api/v1.0/me/notes/";
        public static string SectionsEndpoint = "sections?select=name,id&top=10&orderby=lastModifiedTime%20desc";
        public static string PagesEndpoint = "sections/{0}/pages";

        // Path to the image file to add to the page. 
        // Change this to point to a local PNG file before running the app.
        public static string PathToImageFile = @"C:\<local-path>\logo.png";

        // Get sections, add them to SectionsViewModel, and load the view. 
        public async Task<ActionResult> Index()
        {
            SectionsViewModel viewModel = new SectionsViewModel();
            try
            {
                viewModel.Sections = await GetSectionsAsync();
            }
            catch (Exception ex)
            {
                return View("Error", new HandleErrorInfo(new Exception(ex.Message), "Home", "GetSectionsAsync"));
            }
            return View(viewModel);
        }

        // Create and configure the HttpClient used for requests to the OneNote API. 
        private HttpClient GetAuthorizedClient()
        {
            HttpClient client = new HttpClient();

            string userObjectId = ClaimsPrincipal.Current.FindFirst("https://schemas.microsoft.com/identity/claims/objectidentifier").Value;
            string tenantId = ClaimsPrincipal.Current.FindFirst("https://schemas.microsoft.com/identity/claims/tenantid").Value;
            ClientCredential credential = new ClientCredential(Startup.ClientId, Startup.AppKey);
            AuthenticationContext authContext = new AuthenticationContext(Startup.AADInstance + tenantId);

            try
            {
                // Call AcquireTokenSilent to get the access token. This first tries to get the token from cache.
                AuthenticationResult authResult = authContext.AcquireTokenSilent(
                    Startup.OneNoteResourceId,
                    credential,
                    new UserIdentifier(userObjectId, UserIdentifierType.UniqueId));
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            }
            catch (AdalSilentTokenAcquisitionException)
            {
                HttpContext.GetOwinContext().Authentication.Challenge(
                    new AuthenticationProperties() { RedirectUri = "/" },
                    OpenIdConnectAuthenticationDefaults.AuthenticationType);
                return null;
            }
            return client;
        }

        [Authorize]
        [HttpGet]
        // Build the 'GET sections' request and parse the response. The request gets the 10 most recently modified sections.
        public async Task<IEnumerable<Section>> GetSectionsAsync()
        {
            List<Section> sections = new List<Section>();

            HttpClient client = GetAuthorizedClient();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, OneNoteRoot + SectionsEndpoint);
            HttpResponseMessage response = await client.SendAsync(request);
            if (response.IsSuccessStatusCode)
            {

                // Parse the JSON response.
                string stringResult = await response.Content.ReadAsStringAsync();
                Dictionary<string, dynamic> result = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(stringResult);
                foreach (var item in result["value"])
                {
                    var current = item.ToObject<Dictionary<string, string>>();
                    Section section = new Section
                    {
                        Name = current["name"],
                        Id = current["id"]
                    };
                    sections.Add(section);
                }
            }
            else
            {
                throw new Exception("Error getting sections: " + response.StatusCode.ToString());
            }
            return sections;
        }

        [Authorize]
        [HttpPost]
        // Build the multipart POST request and parse the response. The request creates a page in the selected section.
        public async Task<ActionResult> CreatePageAsync()
        {
            HttpClient client = GetAuthorizedClient();

            // Get user input.
            string selectedSectionId = Request.Form["SectionId"];
            string pageName = Request.Form["page-name"];
            string pagesEndpoint = string.Format("sections/{0}/pages", selectedSectionId);

            // Define the page content, which includes an uploaded image.
            const string imagePartName = "imageBlock1";
            string iso8601Date = DateTime.Now.ToString("o");
            string pageHtml = "<html>" +
                                "<head>" +
                                "<title>" + pageName + "</title>" +
                                "<meta name=\"created\" content=\"" + iso8601Date + "\" />" +
                                "</head>" +
                                "<body>" +
                                "<h1>This is a page with an image</h1>" +
                                "<img src=\"name:" + imagePartName +
                                "\" alt=\"No mis monos\" width=\"250\" height=\"200\" />" +
                                "</body>" +
                                "</html>";

            HttpResponseMessage response;

            // Build the 'POST pages' request.
            var stream = new FileStream(PathToImageFile, FileMode.Open);
            using (var imageContent = new StreamContent(stream))
            {
                try
                {
                    imageContent.Headers.ContentType = new MediaTypeHeaderValue("image/png");
                    MultipartFormDataContent pageContent = new MultipartFormDataContent
                    {
                        {new StringContent(pageHtml, Encoding.UTF8, "text/html"), "Presentation"},
                        {imageContent, imagePartName}
                    };

                    response = await client.PostAsync(OneNoteRoot + pagesEndpoint, pageContent);
                    if (!response.IsSuccessStatusCode)
                    {
                        throw new Exception(response.StatusCode + ": " + response.ReasonPhrase);
                    }
                    else
                    {

                        // Parse the JSON response.
                        string stringResult = await response.Content.ReadAsStringAsync();
                        Dictionary<string, dynamic> pageData = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(stringResult);
                        Dictionary<string, dynamic> linksData = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(pageData["links"].ToString());
                        Links pageLinks = new Links
                        {
                            ClientUrl = new Uri(linksData["oneNoteClientUrl"]["href"].ToString()),
                            WebUrl = new Uri(linksData["oneNoteWebUrl"]["href"].ToString())
                        };
                        PageViewModel pageViewModel = new PageViewModel
                        {
                            Title = pageData["title"],
                            Self = new Uri(pageData["self"]),
                            PageLinks = pageLinks
                        };
                        return View("../home/page", pageViewModel);
                    }
                }
                catch (Exception ex)
                {
                    return View("Error", new HandleErrorInfo(new Exception(ex.Message), "Home", "CreatePageAsync"));
                }
            }
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }
    }
}

Index.cshtml, Page.cshtml, а также Resource.cs показаны в полном объеме в инструкциях.

См. также