【问题标题】:Upload file to OneDrive using ASP.Net Core Console Application使用 ASP.Net Core 控制台应用程序将文件上传到 OneDrive
【发布时间】:2020-07-20 19:15:00
【问题描述】:

我正在尝试使用以下代码将文件上传到 OneDrive。为此,我首先创建了 Azure AD 应用程序,然后创建了 ASP.Net Core 控制台应用程序以使用 (this link) 将文件上传到 OneDrive 当我运行应用程序时,它会在控制台中询问用户名和密码,因此我提供了我的 Azure 用户名和密码,但随后显示错误“MsalServiceException:响应状态代码不指示成功:406(NotAcceptable)”,如图所示。我还在 appsettings.json 文件中给出了应用程序 ID 和租户 ID。 您知道为什么会发生此错误以及如何解决此错误吗?

Error Image Console Image

程序.cs

using System.Collections.Generic;
using System.IO;
using System.Security;
using Microsoft.Identity.Client;
using Microsoft.Graph;
using Microsoft.Extensions.Configuration;
using Helpers;
using System;

namespace OneDriveConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            var config = LoadAppSettings();
            if (config == null)
            {
                Console.WriteLine("Invalid appsettings.json file.");
                return;
            }

            var userName = ReadUsername();
            var userPassword = ReadPassword();

            var client = GetAuthenticatedGraphClient(config, userName, userPassword);

            // request 1 - upload small file to user's onedrive
            var fileName = "smallfile.txt";
            var filePath = Path.Combine(System.IO.Directory.GetCurrentDirectory(), fileName);
            Console.WriteLine("Uploading file: " + fileName);

            FileStream fileStream = new FileStream(filePath, FileMode.Open);
            var uploadedFile = client.Me.Drive.Root
                                          .ItemWithPath("smallfile.txt")
                                          .Content
                                          .Request()
                                          .PutAsync<DriveItem>(fileStream)
                                          .Result;
            Console.WriteLine("File uploaded to: " + uploadedFile.WebUrl);
        }

        private static IConfigurationRoot LoadAppSettings()
        {
            try
            {
                var config = new ConfigurationBuilder()
                                  .SetBasePath(System.IO.Directory.GetCurrentDirectory())
                                  .AddJsonFile("appsettings.json", false, true)
                                  .Build();

                if (string.IsNullOrEmpty(config["applicationId"]) ||
                    string.IsNullOrEmpty(config["tenantId"]))
                {
                    return null;
                }

                return config;
            }
            catch (System.IO.FileNotFoundException)
            {
                return null;
            }
        }

        private static IAuthenticationProvider CreateAuthorizationProvider(IConfigurationRoot config, string userName, SecureString userPassword)
        {
            var clientId = config["applicationId"];
            var authority = $"https://login.microsoftonline.com/{config["tenantId"]}/v2.0";

            List<string> scopes = new List<string>();
            scopes.Add("User.Read");
            scopes.Add("Files.Read");
            scopes.Add("Files.ReadWrite");
            var cca = PublicClientApplicationBuilder.Create(clientId)
                                                    .WithAuthority(authority)
                                                    .Build();
            return MsalAuthenticationProvider.GetInstance(cca, scopes.ToArray(), userName, userPassword);
        }

        private static GraphServiceClient GetAuthenticatedGraphClient(IConfigurationRoot config, string userName, SecureString userPassword)
        {
            var authenticationProvider = CreateAuthorizationProvider(config, userName, userPassword);
            var graphClient = new GraphServiceClient(authenticationProvider);
            return graphClient;
        }

        private static SecureString ReadPassword()
        {
            Console.WriteLine("Enter your password");
            SecureString password = new SecureString();
            while (true)
            {
                ConsoleKeyInfo c = Console.ReadKey(true);
                if (c.Key == ConsoleKey.Enter)
                {
                    break;
                }
                password.AppendChar(c.KeyChar);
                Console.Write("*");
            }
            Console.WriteLine();
            return password;
        }

        private static string ReadUsername()
        {
            string username;
            Console.WriteLine("Enter your username");
            username = Console.ReadLine();
            return username;
        }
    }
}

MsalAuthenticationProvider.cs

using System.Net.Http;
using System.Net.Http.Headers;
using System.Security;
using System.Threading.Tasks;
using Microsoft.Identity.Client;
using Microsoft.Graph;

namespace Helpers
{
    public class MsalAuthenticationProvider : IAuthenticationProvider
    {
        private static MsalAuthenticationProvider _singleton;
        private IPublicClientApplication _clientApplication;
        private string[] _scopes;
        private string _username;
        private SecureString _password;
        private string _userId;

        private MsalAuthenticationProvider(IPublicClientApplication clientApplication, string[] scopes, string username, SecureString password)
        {
            _clientApplication = clientApplication;
            _scopes = scopes;
            _username = username;
            _password = password;
            _userId = null;
        }

        public static MsalAuthenticationProvider GetInstance(IPublicClientApplication clientApplication, string[] scopes, string username, SecureString password)
        {
            if (_singleton == null)
            {
                _singleton = new MsalAuthenticationProvider(clientApplication, scopes, username, password);
            }

            return _singleton;
        }

        public async Task AuthenticateRequestAsync(HttpRequestMessage request)
        {
            var accessToken = await GetTokenAsync();

            request.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
        }

        public async Task<string> GetTokenAsync()
        {
            if (!string.IsNullOrEmpty(_userId))
            {
                try
                {
                    var account = await _clientApplication.GetAccountAsync(_userId);

                    if (account != null)
                    {
                        var silentResult = await _clientApplication.AcquireTokenSilent(_scopes, account).ExecuteAsync();
                        return silentResult.AccessToken;
                    }
                }
                catch (MsalUiRequiredException) { }
            }

            var result = await _clientApplication.AcquireTokenByUsernamePassword(_scopes, _username, _password).ExecuteAsync();
            _userId = result.Account.HomeAccountId.Identifier;
            return result.AccessToken;
        }
    }
}

【问题讨论】:

    标签: c# asp.net-core file-upload onedrive azure-ad-graph-api


    【解决方案1】:

    个人帐户不支持用户名/密码 (ROPC)。请参阅重要 here

    您需要使用 工作或学校帐户(看起来像 xxxxxxx@xxx.onmicrosoft.com)而不是 gmail 或其他第三方邮箱登录。您可以添加用户(导航到 Azure Active Directory -> 用户 -> 新用户 -> 创建用户),然后使用此登录。

    【讨论】:

    • 如果我的回复有帮助,请采纳为答案(点击回复旁边的标记选项将其从灰色切换为填写。),请参阅meta.stackexchange.com/questions/5234/…
    • 使用学校账号登录后。我添加了一个新用户。现在,当我在控制台应用程序中提供用户名和密码时,它显示“租户没有 SPO 许可证”。您知道为什么会发生此错误吗?
    • @AliHaider 这个问题会对你有所帮助。 stackoverflow.com/a/46869065/13308381
    猜你喜欢
    • 1970-01-01
    • 2012-04-17
    • 2021-04-16
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多