#c# #azure #oauth-2.0 #odata #microsoft-dynamics
Вопрос:
Я ищу простой способ подключения к хранилищу данных Azure Odata (в частности, Dynamics365 для финансов и операций) в консольном приложении .NET (без браузера) и получения odata json. Я искал по всем документам MS и, наконец, нашел это:
public OAuthMessageHandler(string serviceUrl, string clientId, string redirectUrl, string username, string password, HttpMessageHandler innerHandler): base(innerHandler) {
AuthenticationParameters ap = AuthenticationParameters.CreateFromResourceUrlAsync(new Uri(serviceUrl "/data/")).Resu<
AuthenticationContext authContext = new AuthenticationContext(ap.Authority, false);
AuthenticationResult authResu<
if (username != string.Empty amp;amp; password != string.Empty) {
UserCredential cred = new UserCredential(username, password);
authResult = authContext.AcquireToken(serviceUrl, clientId, cred);
} else {
authResult = authContext.AcquireToken(serviceUrl, clientId, new Uri(redirectUrl), PromptBehavior.Auto);
}
authHeader = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
}
try/catch ниже находится внутри статического метода моего консольного приложения main
и вызывает функцию выше:
try {
messageHandler = new OAuthMessageHandler(serviceUrl, clientId, string.Empty, userName, password, new HttpClientHandler());
using(HttpClient client = new HttpClient(messageHandler)) {
client.BaseAddress = new Uri(serviceUrl);
client.Timeout = new TimeSpan(0, 2, 0); //2 minutes
client.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
client.DefaultRequestHeaders.Add("OData-Version", "4.0");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.GetAsync("api/data/v9.0/WhoAmI", HttpCompletionOption.ResponseHeadersRead).Resu<
if (response.IsSuccessStatusCode) {
//Get the response content and parse it.
JObject body = JObject.Parse(response.Content.ReadAsStringAsync().Result);
Guid userId = (Guid) body["UserId"];
Console.WriteLine("Your system user ID is: {0}", userId);
} else {
throw new Exception(response.ReasonPhrase);
}
}
} catch (Exception ex) {
DisplayException(ex);
}
ВАЖНО: Я могу успешно подключиться к D365 Famp;O в браузере с помощью имени пользователя и пароля, которые у меня есть. И я передаю их в функцию выше. У меня также есть действительный идентификатор клиента. Я знаю, что все это действительно, потому что у меня есть стороннее приложение, которое с помощью usn, pwd, идентификатора клиента и URL-адреса авторизации я могу подключаться и взаимодействовать с Famp;O и его odata. Но я пытаюсь как можно проще воспроизвести это взаимодействие в своем консольном приложении .NET.
Я начал с этого подхода, но в итоге отклонился и смешал примеры и подходы из других документов, чтобы все это скомпилировать.
Вот мои особенности, как можно меньше запутанные:
D365 Famp;O URL: https://mycustomer2492efd6bdevaos.cloudax.dynamics.com/
Odata URL: https://mycustomer2492efd6bdevaos.cloudax.dynamics.com/data/InventItemPrices
Client Id: c0bzae2e-5233-4465-a2f2-ceb87aa52c3f (I changed some chars)
Authorization URL: https://login.windows.net/mycustomer.com
И у меня есть имя пользователя и пароль. Мне не нужен перенаправитель, поэтому я оставил его как пустую строку. Мне также не нужен секрет клиента. (Если бы у меня был секрет клиента, все это было бы намного проще, потому что я нашел более простые примеры кода c# для работы с этим.)
Когда я вызываю функцию выше, я получаю эту ошибку:
Недопустимый формат заголовка аутентификации — Имя параметра: authenticateHeader
Исключение создается в этой строке:
AuthenticationParameters ap = AuthenticationParameters.CreateFromResourceUrlAsync(new Uri(serviceUrl "/data/")).Resu<
Я не женат на подходе, который я использую, это просто все, что я нашел, что на самом деле компилируется и пытается работать. Я был бы очень признателен за автономную функцию с как можно меньшим количеством зависимостей для подключения к моей odata и удаления json по мере необходимости.
Комментарии:
1. Есть ли причина, по которой вам нужно использовать конечную точку OData поверх SDK?
2. blockingHD: Вовсе нет. Предпочел бы не использовать SDK. Было бы здорово использовать необработанный c# без каких-либо зависимостей, кроме стандартной .NET.
3. URI должен выглядеть следующим образом: «частная статическая строка serviceUrl = yourorg.crm.dynamics.com ‘
4. jdweng: нет, это не crm. Это Famp;O.
Ответ №1:
Наконец-то я нашел ответ:
string d365RootURL = "https://someenvironmentos.cloudax.dynamics.com";
string authorizationURL = "https://login.windows.net/something.com";
var usn = "serviceAcctUsn";
var pwd = "serviceAcctPwd";
var clientID = "c0bcae....6aa52c3f";
string d365OdataURL = d365RootURL "/data/";
string odataQuery = "SomeEntity?ItemNumber eq '999";
UserCredential creds = new UserPasswordCredential(usn, pwd);
var authContext = new AuthenticationContext(authorizationURL, false);
var authTask = authContext.AcquireTokenAsync(d365RootURL, clientID, creds);
try {
authTask.Wait();
} catch (Exception ex) {
}
AuthenticationResult authenticationResult = authTask.Resu<
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
httpClient.DefaultRequestHeaders.Add("OData-Version", "4.0");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authenticationResult.AccessToken);
httpClient.BaseAddress = new Uri(d365OdataURL);
var response = httpClient.GetAsync(odataQuery).Resu<
Ответ №2:
URI должен выглядеть следующим образом :
private static string serviceUrl = "https://yourorg.crm.dynamics.com";
Комментарии:
1. Нет, это не CRM. Это D365 Финансы и операции, как упоминалось в оригинальном посте.