Added ConfigureAwait and refactored the service communications class

This commit is contained in:
Isaiah Williams 2018-04-05 14:07:29 +00:00
Родитель 3ff892ac83
Коммит 0c7291dbba
46 изменённых файлов: 761 добавлений и 552 удалений

Просмотреть файл

@ -43,6 +43,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Images", "Images", "{B55A74
docs\Images\qnaservice03.png = docs\Images\qnaservice03.png
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bot.Services", "src\Bot.Services\Bot.Services.csproj", "{DD1B3FF6-0FAC-41F6-843C-183676F55AD4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bot.Models", "src\Bot.Models\Bot.Models.csproj", "{72CF9064-499F-456D-B879-E1335B2BD6CA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -53,6 +57,14 @@ Global
{A8BA1066-5695-4D71-ABB4-65E5A5E0C3D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A8BA1066-5695-4D71-ABB4-65E5A5E0C3D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A8BA1066-5695-4D71-ABB4-65E5A5E0C3D4}.Release|Any CPU.Build.0 = Release|Any CPU
{DD1B3FF6-0FAC-41F6-843C-183676F55AD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DD1B3FF6-0FAC-41F6-843C-183676F55AD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DD1B3FF6-0FAC-41F6-843C-183676F55AD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DD1B3FF6-0FAC-41F6-843C-183676F55AD4}.Release|Any CPU.Build.0 = Release|Any CPU
{72CF9064-499F-456D-B879-E1335B2BD6CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{72CF9064-499F-456D-B879-E1335B2BD6CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{72CF9064-499F-456D-B879-E1335B2BD6CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{72CF9064-499F-456D-B879-E1335B2BD6CA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -60,6 +72,8 @@ Global
GlobalSection(NestedProjects) = preSolution
{A8BA1066-5695-4D71-ABB4-65E5A5E0C3D4} = {07FC2994-6ECD-42BC-9CF3-77CE505216AA}
{B55A743C-BA04-491F-9C64-E7339C30684F} = {BAD9B155-1FCF-4735-A8EC-D8ECCDAB9136}
{DD1B3FF6-0FAC-41F6-843C-183676F55AD4} = {07FC2994-6ECD-42BC-9CF3-77CE505216AA}
{72CF9064-499F-456D-B879-E1335B2BD6CA} = {07FC2994-6ECD-42BC-9CF3-77CE505216AA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D966732D-8A63-4571-81B5-ED6624F0B40E}

Просмотреть файл

@ -1,7 +1,6 @@
# Adding New Intents
The [Language Understanding Intelligent Service (LUIS)](http://luis.ai) provides the ability to process conversational information
and extract an intent from that information. This ability enables us to map sentences received to a particular function defined with in the
[_ActionDialog_](https://github.com/Microsoft/Partner-Center-Bot/blob/master/src/Bot/Dialogs/ActionDialog.cs) class. As an example if an authenticated
The [Language Understanding Intelligent Service (LUIS)](http://luis.ai) provides the ability to process conversational information and extract an intent from that information. This ability enables us to map sentences received to a particular function defined within the
[_ActionDialog_](https://github.com/Microsoft/Partner-Center-Bot/blob/master/src/Bot/Dialogs/ActionDialog.cs) class. As an example, if an authenticated
user sends _list customers_ this will be processed by LUIS and eventually mapped to the [_ExecuteAsync_](https://github.com/Microsoft/Partner-Center-Bot/blob/master/src/Bot/Intents/ListCustomersIntent.cs#L61)
function defined in the [_ListCustomerIntnent_](https://github.com/Microsoft/Partner-Center-Bot/blob/master/src/Bot/Intents/ListCustomersIntent.cs) class.
@ -17,18 +16,18 @@ The following logic is utilized to properly route the intent to the appropriate
```csharp
key = result.TopScoringIntent.Intent.ToCamelCase();
principal = await context.GetCustomerPrincipalAsync(this.service);
principal = await context.GetCustomerPrincipalAsync(this.service).ConfigureAwait(false);
if (principal == null)
{
await this.HelpAsync(context);
await this.HelpAsync(context).ConfigureAwait(false);
return;
}
if (principal.AvailableIntents.ContainsKey(key))
{
await principal.AvailableIntents[key]
.ExecuteAsync(context, message, result, this.service);
.ExecuteAsync(context, message, result, this.service).ConfigureAwait(false);
}
else
{
@ -37,8 +36,7 @@ else
```
First the code will verify that the user has successfully authenticated. This is accomplished by extracting the [_CustomerPrincipal_](https://github.com/Microsoft/Partner-Center-Bot/blob/master/src/Bot/Security/CustomerPrincipal.cs)
from the private conversation data. If that object is not present in the private conversation data that means the user has not authenticated. Second the code will verify the intent exists in the dictionary of available intents for the
authenticated user. The dictionary of availalbe intents is generated in the [_GetCustomerPrincipalAsync_](https://github.com/Microsoft/Partner-Center-Bot/blob/master/src/Bot/Controllers/OAuthCallbackController.cs#L191) function
from the private conversation data. If that object is not present in the private conversation data that means the user has not authenticated. Second, the code will verify the intent exists in the dictionary of available intents for the authenticated user. The dictionary of available intents is generated in the [_GetCustomerPrincipalAsync_](https://github.com/Microsoft/Partner-Center-Bot/blob/master/src/Bot/Controllers/OAuthCallbackController.cs#L191) function
defined in the [_OAuthCallbackController_](https://github.com/Microsoft/Partner-Center-Bot/blob/master/src/Bot/Controllers/OAuthCallbackController.cs#L191) class.
```csharp
@ -52,10 +50,10 @@ AvailableIntents = (from intent in this.Service.Intent.Intents
This LINQ statement will create a dictionary that contains a reference to classes that implement the [_IIntent_](https://github.com/Microsoft/Partner-Center-Bot/blob/master/src/Bot/Intents/IIntent.cs) interface where the user has the appropriate privileges.
## Creating A New Intent
New intents will need to be defined within the LUIS application and then through code. Perform the following tasksto create a new intent within LUIS
New intents will need to be defined within the LUIS application and then through code. Perform the following tasks to create a new intent within LUIS
1. Login into the [LUIS portal](http://luis.ai) and import the [_Partner-Center-Bot_](https://github.com/Microsoft/Partner-Center-Bot/blob/master/Partner-Center-Bot.json) application if you have not already
2. Select the _Partner-Center-Bot_ application and then click the _Intents_ link found on the left hand size of the dashboard
1. Login to the [LUIS portal](http://luis.ai) and import the [_Partner-Center-Bot_](https://github.com/Microsoft/Partner-Center-Bot/blob/master/Partner-Center-Bot.json) application if you have not already
2. Select the _Partner-Center-Bot_ application and then click the _Intents_ link found on the left-hand side of the dashboard
3. Click the _Add Intent_ button and then specify an appropriate name and then click _Save_
![Add a new intent](Images/luis01.png)
@ -64,9 +62,8 @@ New intents will need to be defined within the LUIS application and then through
![Adding utterances to an intent](Images/luis02.png)
If you would like to learn more about the various configurations then check out [_Add Intents_](https://github.com/Microsoft/Cognitive-Documentation/blob/master/Content/en-us/LUIS/Add-intents.md) from the LUIS documentation. Next you will need add a new class to the [_Intent_](https://github.com/Microsoft/Partner-Center-Bot/tree/master/src/Bot/Intents) directory that implements the
[_IIntent_](https://github.com/Microsoft/Partner-Center-Bot/blob/master/src/Bot/Intents/IIntent.cs) interface. By doing this all of the required functions and properties will
be defined. The following code is a sample of what the new intent should look like.
If you would like to learn more about the various configurations then check out [_Add Intents_](https://github.com/Microsoft/Cognitive-Documentation/blob/master/Content/en-us/LUIS/Add-intents.md) from the LUIS documentation. Next, you will need to add a new class to the [_Intent_](https://github.com/Microsoft/Partner-Center-Bot/tree/master/src/Bot/Intents) directory that implements the
[_IIntent_](https://github.com/Microsoft/Partner-Center-Bot/blob/master/src/Bot/Intents/IIntent.cs) interface. By doing this all of the required functions and properties will be defined. The following code is a sample of what the new intent should look like.
```csharp
// -----------------------------------------------------------------------
@ -145,11 +142,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
correlationId = Guid.NewGuid();
response = context.MakeMessage();
principal = await context.GetCustomerPrincipalAsync(service);
principal = await context.GetCustomerPrincipalAsync(service).ConfigureAwait(false);
response.Text = "This is sample intent.";
await context.PostAsync(response);
await context.PostAsync(response).ConfigureAwait(false);
// Capture the request for the customer summary for analysis.
eventProperties = new Dictionary<string, string>

Просмотреть файл

@ -35,7 +35,7 @@ The bot requires an Azure AD application that grants privileges to Azure AD and
3. Click _+ Add_ to start the new application wizard
4. Specify an appropriate name for the bot, select _Web app / API_ for the application, an appropriate value for the sign-on URL, and then click _Create_
5. Click _Required permissions_ found on the settings blade for the the application and then click _+ Add_
5. Click _Required permissions_ found on the settings blade for the application and then click _+ Add_
6. Add the _Microsoft Graph_ API and grant it the _Read directory data_ application permission
7. Add the _Partner Center API_ and grant it the _Access Partner Center PPE_ delegated permission
@ -93,10 +93,6 @@ The following table provides details for the appropriate value for each of the p
| Application Id | Identifier for the application created in the Azure AD Application section |
| Application Secret | Secret key create in the step 9 of the Azure AD application section |
| Application Tenant Id | Identifier for the tenant where the application from the Azure AD Application was created |
| Key Vault App Cert Thumbprint | Thumbprint of the certificated created in the Azure Key Vault section |
| Key Vault App Id | Identifier for the Azure AD application created in the Azure Key Vault section |
| Key Vault Name | Name for the Key Vault. This name should not contain any special characters or spaces |
| Key Vault Tenant Id | Identifier for the tenant where the instance of Azure Key Vault is being created |
| LUIS App Id | Identifier for the LUIS application created in the *Create a New LUIS Application* section |
| LUIS App Key | Key for the LUIS application created in the *Create a New LUIS Application* section |
| Microsoft App Id | Identifier of the application created in the *Register With the Bot Framework* section |
@ -106,26 +102,3 @@ The following table provides details for the appropriate value for each of the p
| Partner Center Application Tenat Id | Account ID value obtained from the Partner Center Azure AD Application section |
| QnA Knowledgebase Id | Identifier for the knowledgebase created in the *Create a New Instance of the QnA Service* section |
| QnA Subscription Key | Subscription key for the knowledgebase created in the *Create a New Instance of the QnA Service* section |
## Configure Azure Key Vault Access Policy
Now that the instance of Azure Key Vault has been provisioned you can add the access policy that will
enable the Azure AD application the ability to create, delete, and read secrets. Perform the following
to create the access policy
1. Open PowerShell and install the [Azure AD PowerShell cmdlets](https://docs.microsoft.com/en-us/powershell/azure/install-adv2?view=azureadps-2.0)
if you necessary
2. Update the following cmdlets and then invoke them
```powershell
Connect-AzureAD
Login-AzureRmAccount
## Update these variable before invoking the rest of the cmdlets
# The value for the AppId should be the application identifier for the Azure AD application created for Key Vault
$spn = Get-AzureADServicePrincipal | ? {$_.AppId -eq 'b6b84568-6c01-4981-a80f-09da9a20bbed'}
$resourceGroupName = "ResourceGroupName"
$vaultName = "VaultName"
Set-AzureRmKeyVaultAccessPolicy -VaultName $vaultName -ObjectId $spn.Id -PermissionsToSecrets delete,get,set -ResourceGroupName $resourceGroupName
```

Просмотреть файл

@ -1,14 +1,12 @@
# Pre-consent
Azure Active Directory utilizes a consent framework that is based on a user or an administrator giving consent to an application
that asks to be registered in their directory, which may involve accessing directory data. This framework presents two primary
Azure Active Directory utilizes a consent framework that is based on a user or an administrator giving consent to an application that asks to be registered in their directory, which may involve accessing directory data. This framework presents two primary
problems for Cloud Solution Provider (CSP) partners
1. Getting all customers to consent to an application can prove to be difficult task.
1. Getting all customers to consent to an application can prove to be a difficult task.
2. There might be a need to perform an operation against a newly provisioned tenant before access has been granted to the customer.
Which means the customer will not be able to consent to the application.
In order to overcome these issues CSP partners can configure an for pre-consent. This configuration takes advantage of the
delegated administrative permissions that are granted to CSP partner over a customer associated with their reseller. Perform
In order to overcome these issues, CSP partners can configure an for pre-consent. This configuration takes advantage of the delegated administrative permissions that are granted to CSP partner over a customer associated with their reseller. Perform
the following steps to configure the application that will be used to access the Partner Center API for pre-consent
1. Install Azure AD PowerShell Module (instruction available [here](https://docs.microsoft.com/en-us/powershell/azuread/)).

Просмотреть файл

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Microsoft.Store.PartnerCenter.Bot.Models</AssemblyName>
<RootNamespace>Microsoft.Store.PartnerCenter.Bot.Models</RootNamespace>
</PropertyGroup>
</Project>

Просмотреть файл

@ -1,17 +1,14 @@
// -----------------------------------------------------------------------
// <copyright file="HealthEvent.cs" company="Microsoft">
// <copyright file="OfficeHealthEvent.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Logic.Office
namespace Microsoft.Store.PartnerCenter.Bot.Models
{
using System;
using System;
/// <summary>
/// Represents a health event obtained from Office 365 Service Communications API.
/// </summary>
public class HealthEvent
public class OfficeHealthEvent
{
/// <summary>
/// Gets or sets the identifier.

Просмотреть файл

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{DD1B3FF6-0FAC-41F6-843C-183676F55AD4}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Microsoft.Store.PartnerCenter.Bot.Services</RootNamespace>
<AssemblyName>Microsoft.Store.PartnerCenter.Bot.Services</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.19.2.6005, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.19.2.6005, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Rest.ClientRuntime, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Rest.ClientRuntime.2.3.11\lib\net452\Microsoft.Rest.ClientRuntime.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="IServiceCommuncations.cs" />
<Compile Include="ODataResponse.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServiceCommunications.cs" />
<Compile Include="ServiceCredentials.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Bot.Models\Bot.Models.csproj">
<Project>{72cf9064-499f-456d-b879-e1335b2bd6ca}</Project>
<Name>Bot.Models</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,30 @@
// -----------------------------------------------------------------------
// <copyright file="IServiceCommunications.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Services
{
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Rest;
using Models;
public interface IServiceCommuncations
{
/// <summary>
/// Gets or sets the credentials used when accessing resources.
/// </summary>
ServiceClientCredentials Credentials { get; }
/// <summary>
/// Gets or sets the address of the resource being accessed.
/// </summary>
Uri Endpoint { get; }
Task<List<OfficeHealthEvent>> GetHealthEventsAsync(string customerId, CancellationToken cancellationToken = default(CancellationToken));
}
}

Просмотреть файл

@ -0,0 +1,15 @@
// -----------------------------------------------------------------------
// <copyright file="ODataResponse.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Services
{
using System.Collections.Generic;
internal class ODataResponse<T> where T: class
{
public List<T> Value { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Bot.Services")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Bot.Services")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("dd1b3ff6-0fac-41f6-843c-183676f55ad4")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -0,0 +1,75 @@
// -----------------------------------------------------------------------
// <copyright file="ServiceCommunications.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Services
{
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Models;
using Newtonsoft.Json;
using Rest;
public class ServiceCommunications : ServiceClient<ServiceCommunications>, IServiceCommuncations
{
/// <summary>
/// Initializes a new instance of the <see cref="ServiceCommunications" /> class.
/// </summary>
/// <param name="credentials">Credentials used when accessing resources.</param>
/// <param name="handlers">List of handlers from top to bottom (outer handler is the first in the list)</param>
public ServiceCommunications(ServiceClientCredentials credentials, params DelegatingHandler[] handlers) : base(handlers)
{
Credentials = credentials;
}
/// <summary>
/// Initializes a new instance of the <see cref="ServiceCommunications" /> class.
/// </summary>
/// <param name="endpoint">Address of the resource being accessed.</param>
/// <param name="credentials">Credentials used when accessing resources.</param>
/// <param name="handlers">List of handlers from top to bottom (outer handler is the first in the list)</param>
public ServiceCommunications(Uri endpoint, ServiceClientCredentials credentials, params DelegatingHandler[] handlers) : base(handlers)
{
Credentials = credentials;
Endpoint = endpoint;
}
/// <summary>
/// Gets or sets the credentials used when accessing resources.
/// </summary>
public ServiceClientCredentials Credentials { get; private set; }
/// <summary>
/// Gets or sets the address of the resource being accessed.
/// </summary>
public Uri Endpoint { get; private set; }
public async Task<List<OfficeHealthEvent>> GetHealthEventsAsync(string customerId, CancellationToken cancellationToken = default(CancellationToken))
{
HttpResponseMessage response = null;
string content;
try
{
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(Endpoint, $"/api/v1.0/{customerId}/ServiceComms/CurrentStatus")))
{
await Credentials.ProcessHttpRequestAsync(request, cancellationToken).ConfigureAwait(false);
response = await HttpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return JsonConvert.DeserializeObject<ODataResponse<OfficeHealthEvent>>(content).Value;
}
}
finally
{
response = null;
}
}
}
}

Просмотреть файл

@ -0,0 +1,126 @@
// -----------------------------------------------------------------------
// <copyright file="ServiceCredentials.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Services
{
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using IdentityModel.Clients.ActiveDirectory;
using Rest;
public sealed class ServiceCredentials : ServiceClientCredentials
{
/// <summary>
/// The authentication scheme utilized by the request.
/// </summary>
private const string AuthenticationScheme = "Bearer";
/// <summary>
/// Initializes a new instance of the <see cref="ServiceCredentials" /> class.
/// </summary>
/// <param name="clientId">
/// The client identifer to be used when requesting an access token.
/// </param>
/// <param name="clientSecret">
/// The client secret to be used when requesting an access token.
/// </param>
/// <param name="resource">
/// Identifier of the target resource that is the recipient of the requested token.
/// </param>
/// <param name="tenantId">
/// The tenant identifier to be used when requesting an access token.
/// </param>
public ServiceCredentials(string clientId, string clientSecret, string resource, string tenantId)
{
ClientId = clientId;
ClientSecret = clientSecret;
Resource = resource;
TenantId = tenantId;
}
/// <summary>
/// Gets or sets the client identifier.
/// </summary>
public string ClientId { get; set; }
/// <summary>
/// Gets or sets the client secret.
/// </summary>
public string ClientSecret { get; set; }
/// <summary>
/// Gets or sets the identity of the target resource that is the recipient of the requested token.
/// </summary>
public string Resource { get; set; }
/// <summary>
/// Gets or sets the tenant identifier.
/// </summary>
public string TenantId { get; set; }
/// <summary>
/// Applies the credentials to the HTTP request.
/// </summary>
/// <param name="request">
/// The HTTP request message
/// </param>
/// <param name="cancellationToken">
/// The cancellation token to monitor.
/// </param>
/// <returns>
/// An instance of the <see cref="Task"/> class that represents the asynchronous operation.
/// </returns>
public override async Task ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
AuthenticationContext authContext;
AuthenticationResult authResult;
try
{
authContext = new AuthenticationContext($"https://login.microsoftonline.com/{TenantId}");
authResult = await authContext.AcquireTokenAsync(
Resource,
new ClientCredential(
ClientId,
ClientSecret)).ConfigureAwait(false);
request.Headers.Authorization = new AuthenticationHeaderValue(AuthenticationScheme, authResult.AccessToken);
}
finally
{
authContext = null;
authResult = null;
}
}
public async Task<string> GetTokenAsync()
{
AuthenticationContext authContext;
AuthenticationResult authResult;
try
{
authContext = new AuthenticationContext($"https://login.microsoftonline.com/{TenantId}");
authResult = await authContext.AcquireTokenAsync(
Resource,
new ClientCredential(
ClientId,
ClientSecret)).ConfigureAwait(false);
return authResult.AccessToken;
}
finally
{
authContext = null;
authResult = null;
}
}
}
}

Просмотреть файл

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.19.2" targetFramework="net461" />
<package id="Microsoft.Rest.ClientRuntime" version="2.3.11" targetFramework="net461" />
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
</packages>

Просмотреть файл

@ -1,5 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\Text.Analyzers.2.6.0\build\Text.Analyzers.props" Condition="Exists('..\..\packages\Text.Analyzers.2.6.0\build\Text.Analyzers.props')" />
<Import Project="..\..\packages\Microsoft.NetFramework.Analyzers.2.6.0\build\Microsoft.NetFramework.Analyzers.props" Condition="Exists('..\..\packages\Microsoft.NetFramework.Analyzers.2.6.0\build\Microsoft.NetFramework.Analyzers.props')" />
<Import Project="..\..\packages\Microsoft.NetCore.Analyzers.2.6.0\build\Microsoft.NetCore.Analyzers.props" Condition="Exists('..\..\packages\Microsoft.NetCore.Analyzers.2.6.0\build\Microsoft.NetCore.Analyzers.props')" />
<Import Project="..\..\packages\Microsoft.CodeQuality.Analyzers.2.6.0\build\Microsoft.CodeQuality.Analyzers.props" Condition="Exists('..\..\packages\Microsoft.CodeQuality.Analyzers.2.6.0\build\Microsoft.CodeQuality.Analyzers.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -161,8 +165,8 @@
<Reference Include="Microsoft.Store.PartnerCenter.Models, Version=1.7.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Store.PartnerCenter.1.7.1\lib\Net45\Microsoft.Store.PartnerCenter.Models.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAzure.Storage, Version=9.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\WindowsAzure.Storage.9.1.0\lib\net45\Microsoft.WindowsAzure.Storage.dll</HintPath>
<Reference Include="Microsoft.WindowsAzure.Storage, Version=9.1.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\WindowsAzure.Storage.9.1.1\lib\net45\Microsoft.WindowsAzure.Storage.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
@ -223,10 +227,6 @@
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Content Include="Content\Images\azure-logo.png" />
<Content Include="Content\Images\dynamics-logo.png" />
<Content Include="Content\Images\microsoft-logo.png" />
<Content Include="Content\Images\office-logo.png" />
<Content Include="default.htm" />
<Content Include="Global.asax" />
<Content Include="Web.config">
@ -246,7 +246,6 @@
<Compile Include="Providers\ConfigurationProvider.cs" />
<Compile Include="Providers\IConfigurationProvider.cs" />
<Compile Include="Controllers\BaseApiController.cs" />
<Compile Include="Controllers\ImageController.cs" />
<Compile Include="Controllers\MessagesController.cs" />
<Compile Include="Controllers\OAuthCallbackController.cs" />
<Compile Include="Dialogs\ActionDialog.cs" />
@ -268,12 +267,7 @@
<Compile Include="Intents\SelectCustomerIntent.cs" />
<Compile Include="Intents\SelectSubscriptionIntent.cs" />
<Compile Include="Logic\AiExceptionLogger.cs" />
<Compile Include="Logic\CommunicationException.cs" />
<Compile Include="Logic\IPartnerOperations.cs" />
<Compile Include="Logic\Office\HealthEvent.cs" />
<Compile Include="Logic\Office\IServiceCommunications.cs" />
<Compile Include="Logic\Office\ODataResponse.cs" />
<Compile Include="Logic\Office\ServiceCommunications.cs" />
<Compile Include="Logic\OperationContext.cs" />
<Compile Include="Logic\PartnerOperations.cs" />
<Compile Include="Models\ApplicationCredential.cs" />
@ -286,7 +280,7 @@
<Compile Include="Providers\KeyVaultProvider.cs" />
<Compile Include="Providers\RedisCacheprovider.cs" />
<Compile Include="Security\AuthenticationProvider.cs" />
<Compile Include="Security\CustomBotAuthentication.cs" />
<Compile Include="Security\CustomBotAuthenticationAttribute.cs" />
<Compile Include="Security\CustomerPrincipal.cs" />
<Compile Include="Security\Permissions.cs" />
<Compile Include="Security\UserRoles.cs" />
@ -326,7 +320,16 @@
<ItemGroup>
<WCFMetadata Include="Connected Services\" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Analyzer Include="..\..\packages\Microsoft.CodeQuality.Analyzers.2.6.0\analyzers\dotnet\cs\Microsoft.CodeQuality.Analyzers.dll" />
<Analyzer Include="..\..\packages\Microsoft.CodeQuality.Analyzers.2.6.0\analyzers\dotnet\cs\Microsoft.CodeQuality.CSharp.Analyzers.dll" />
<Analyzer Include="..\..\packages\Microsoft.NetCore.Analyzers.2.6.0\analyzers\dotnet\cs\Microsoft.NetCore.Analyzers.dll" />
<Analyzer Include="..\..\packages\Microsoft.NetCore.Analyzers.2.6.0\analyzers\dotnet\cs\Microsoft.NetCore.CSharp.Analyzers.dll" />
<Analyzer Include="..\..\packages\Microsoft.NetFramework.Analyzers.2.6.0\analyzers\dotnet\cs\Microsoft.NetFramework.Analyzers.dll" />
<Analyzer Include="..\..\packages\Microsoft.NetFramework.Analyzers.2.6.0\analyzers\dotnet\cs\Microsoft.NetFramework.CSharp.Analyzers.dll" />
<Analyzer Include="..\..\packages\Text.Analyzers.2.6.0\analyzers\dotnet\cs\Text.Analyzers.dll" />
<Analyzer Include="..\..\packages\Text.Analyzers.2.6.0\analyzers\dotnet\cs\Text.CSharp.Analyzers.dll" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.es.resx" />
<EmbeddedResource Include="Resources.fr.resx" />
@ -336,6 +339,16 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Bot.Models\Bot.Models.csproj">
<Project>{72cf9064-499f-456d-b879-e1335b2bd6ca}</Project>
<Name>Bot.Models</Name>
</ProjectReference>
<ProjectReference Include="..\Bot.Services\Bot.Services.csproj">
<Project>{dd1b3ff6-0fac-41f6-843c-183676f55ad4}</Project>
<Name>Bot.Services</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
@ -372,6 +385,10 @@
<Error Condition="!Exists('..\..\packages\Microsoft.Azure.Services.AppAuthentication.1.1.0-preview\build\Microsoft.Azure.Services.AppAuthentication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Azure.Services.AppAuthentication.1.1.0-preview\build\Microsoft.Azure.Services.AppAuthentication.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Azure.DocumentDB.1.21.1\build\Microsoft.Azure.DocumentDB.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Azure.DocumentDB.1.21.1\build\Microsoft.Azure.DocumentDB.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.ApplicationInsights.SnapshotCollector.1.2.1\build\Microsoft.ApplicationInsights.SnapshotCollector.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.ApplicationInsights.SnapshotCollector.1.2.1\build\Microsoft.ApplicationInsights.SnapshotCollector.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.CodeQuality.Analyzers.2.6.0\build\Microsoft.CodeQuality.Analyzers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.CodeQuality.Analyzers.2.6.0\build\Microsoft.CodeQuality.Analyzers.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.NetCore.Analyzers.2.6.0\build\Microsoft.NetCore.Analyzers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.NetCore.Analyzers.2.6.0\build\Microsoft.NetCore.Analyzers.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.NetFramework.Analyzers.2.6.0\build\Microsoft.NetFramework.Analyzers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.NetFramework.Analyzers.2.6.0\build\Microsoft.NetFramework.Analyzers.props'))" />
<Error Condition="!Exists('..\..\packages\Text.Analyzers.2.6.0\build\Text.Analyzers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Text.Analyzers.2.6.0\build\Text.Analyzers.props'))" />
</Target>
<Import Project="..\..\packages\Microsoft.Azure.DocumentDB.1.21.1\build\Microsoft.Azure.DocumentDB.targets" Condition="Exists('..\..\packages\Microsoft.Azure.DocumentDB.1.21.1\build\Microsoft.Azure.DocumentDB.targets')" />
<Import Project="..\..\packages\Microsoft.ApplicationInsights.SnapshotCollector.1.2.1\build\Microsoft.ApplicationInsights.SnapshotCollector.targets" Condition="Exists('..\..\packages\Microsoft.ApplicationInsights.SnapshotCollector.1.2.1\build\Microsoft.ApplicationInsights.SnapshotCollector.targets')" />

Двоичные данные
src/Bot/Content/Images/azure-logo.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.2 KiB

Двоичные данные
src/Bot/Content/Images/dynamics-logo.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 5.1 KiB

Двоичные данные
src/Bot/Content/Images/microsoft-logo.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.3 KiB

Двоичные данные
src/Bot/Content/Images/office-logo.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 4.1 KiB

Просмотреть файл

@ -1,78 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ImageController.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Controllers
{
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web.Http;
using Logic;
using Providers;
/// <summary>
/// Provides the ability to dynamically generate images.
/// </summary>
[RoutePrefix("api/images")]
public class ImageController : BaseApiController
{
/// <summary>
/// Initializes a new instance of the <see cref="ImageController"/> class.
/// </summary>
/// <param name="provider">Provides access to core services.</param>
public ImageController(IBotProvider provider) : base(provider)
{
}
/// <summary>
/// Dynamically generates an image.
/// </summary>
/// <param name="value">A <see cref="string>"/> that will be used to generate the image.</param>
/// <returns>A dynamically generated image.</returns>
[HttpGet]
[Route("dynamic")]
public HttpResponseMessage GetImage(string value)
{
HttpResponseMessage response;
using (Bitmap bmp = new Bitmap(65, 65, PixelFormat.Format32bppArgb))
{
bmp.MakeTransparent();
using (Brush brush = new SolidBrush(Color.FromArgb(255, 0, 127, 255)))
{
using (Graphics graphic = Graphics.FromImage(bmp))
{
graphic.SmoothingMode = SmoothingMode.AntiAlias;
graphic.FillEllipse(brush, 0, 0, 24, 24);
graphic.DrawString(value.Substring(0, 1).ToUpper(), new Font("Calibri (Body)", 16, FontStyle.Bold), Brushes.White, 0, 0);
using (MemoryStream stream = new MemoryStream())
{
bmp.Save(stream, ImageFormat.Png);
stream.Position = 0;
response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(stream.ToArray())
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
response.Content.Headers.ContentLength = stream.Length;
return response;
}
}
}
}
}
}
}

Просмотреть файл

@ -67,13 +67,13 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
Provider.Configuration.MicrosoftAppId,
Provider.Configuration.MicrosoftAppPassword.ToUnsecureString()));
await client.Conversations.ReplyToActivityAsync(activity.CreateReply(Resources.Welcome));
await client.Conversations.ReplyToActivityAsync(activity.CreateReply(Resources.Welcome)).ConfigureAwait(false);
}
}
if (activity.Type == ActivityTypes.Message)
{
await Conversation.SendAsync(activity, () => new ActionDialog(Provider));
await Conversation.SendAsync(activity, () => new ActionDialog(Provider)).ConfigureAwait(false);
}
// Capture the request for the customer summary for analysis.

Просмотреть файл

@ -94,7 +94,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
using (ILifetimeScope scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
botData = scope.Resolve<IBotData>();
await botData.LoadAsync(cancellationToken);
await botData.LoadAsync(cancellationToken).ConfigureAwait(false);
if (!Validate(botData, stateData))
{
@ -103,12 +103,14 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
new InvalidOperationException(Resources.InvalidAuthenticationException));
}
principal = await GetCustomerPrincipalAsync(code);
principal = await GetCustomerPrincipalAsync(
new Uri($"{Request.RequestUri.Scheme}://{Request.RequestUri.Host}:{Request.RequestUri.Port}/{BotConstants.CallbackPath}"),
code).ConfigureAwait(false);
if (principal == null)
{
message.Text = Resources.NoRelationshipException;
await Conversation.ResumeAsync(conversationReference, message, cancellationToken);
await Conversation.ResumeAsync(conversationReference, message, cancellationToken).ConfigureAwait(false);
return Request.CreateErrorResponse(
HttpStatusCode.BadRequest,
@ -117,8 +119,8 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
botData.PrivateConversationData.SetValue(BotConstants.CustomerPrincipalKey, principal);
await botData.FlushAsync(cancellationToken);
await Conversation.ResumeAsync(conversationReference, message, cancellationToken);
await botData.FlushAsync(cancellationToken).ConfigureAwait(false);
await Conversation.ResumeAsync(conversationReference, message, cancellationToken).ConfigureAwait(false);
// Capture the request for the customer summary for analysis.
eventProperties = new Dictionary<string, string>
@ -164,41 +166,38 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
/// <summary>
/// Obtain an instance of <see cref="CustomerPrincipal"/> that represents the authenticated user.
/// </summary>
/// <param name="redirectUri">Address to return to upon receiving a response from the authority.</param>
/// <param name="code">The authorization code that was requested.</param>
/// <returns>An instance of <see cref="CustomerPrincipal"/> that represents the authenticated user.</returns>
/// <exception cref="ArgumentException">
/// <paramref name="code"/> is empty or null.
/// </exception>
private async Task<CustomerPrincipal> GetCustomerPrincipalAsync(string code)
private async Task<CustomerPrincipal> GetCustomerPrincipalAsync(Uri redirectUri, string code)
{
AuthenticationResult authResult;
CustomerPrincipal principal;
IGraphClient client;
List<RoleModel> roles;
Uri redirectUri;
code.AssertNotEmpty(nameof(code));
try
{
redirectUri =
new Uri($"{HttpContext.Current.Request.Url.Scheme}://{HttpContext.Current.Request.Url.Host}:{HttpContext.Current.Request.Url.Port}/{BotConstants.CallbackPath}");
authResult = await Provider.AccessToken.AcquireTokenByAuthorizationCodeAsync(
$"{Provider.Configuration.ActiveDirectoryEndpoint}/{BotConstants.AuthorityEndpoint}",
code,
new ApplicationCredential
{
ApplicationId = Provider.Configuration.ApplicationId,
ApplicationSecret = Provider.Configuration.ApplicationSecret,
ApplicationId = Provider.Configuration.ApplicationId,
ApplicationSecret = Provider.Configuration.ApplicationSecret,
UseCache = true
},
redirectUri,
Provider.Configuration.GraphEndpoint);
Provider.Configuration.GraphEndpoint).ConfigureAwait(false);
client = new GraphClient(Provider, authResult.TenantId);
roles = await client.GetDirectoryRolesAsync(authResult.UserInfo.UniqueId);
roles = await client.GetDirectoryRolesAsync(authResult.UserInfo.UniqueId).ConfigureAwait(false);
principal = new CustomerPrincipal
{
@ -219,7 +218,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
authResult.TenantId,
StringComparison.CurrentCultureIgnoreCase))
{
await Provider.PartnerOperations.GetCustomerAsync(principal, authResult.TenantId);
await Provider.PartnerOperations.GetCustomerAsync(principal, authResult.TenantId).ConfigureAwait(false);
}
return principal;
@ -236,6 +235,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
finally
{
authResult = null;
client = null;
roles = null;
}
}
@ -251,7 +251,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
/// or
/// <paramref name="stateData"/> is null.
/// </exception>
private bool Validate(IBotData botData, IDictionary<string, string> stateData)
private static bool Validate(IBotData botData, IDictionary<string, string> stateData)
{
string uniqueId;

Просмотреть файл

@ -64,7 +64,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
{
message = context.MakeMessage();
principal = await context.GetCustomerPrincipalAsync(provider);
principal = await context.GetCustomerPrincipalAsync(provider).ConfigureAwait(false);
if (principal == null)
{
@ -81,7 +81,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
message.Text = builder.ToString();
}
await context.PostAsync(message);
await context.PostAsync(message).ConfigureAwait(false);
context.Wait(MessageReceived);
}
finally
@ -113,22 +113,22 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
{
key = result.TopScoringIntent.Intent.ToCamelCase();
principal = await context.GetCustomerPrincipalAsync(provider);
principal = await context.GetCustomerPrincipalAsync(provider).ConfigureAwait(false);
if (principal == null)
{
await HelpAsync(context);
await HelpAsync(context).ConfigureAwait(false);
return;
}
if (principal.AvailableIntents.ContainsKey(key))
{
await principal.AvailableIntents[key]
.ExecuteAsync(context, message, result, provider);
.ExecuteAsync(context, message, result, provider).ConfigureAwait(false);
}
else
{
await HelpAsync(context);
await HelpAsync(context).ConfigureAwait(false);
}
}
finally
@ -157,15 +157,15 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
new AuthDialog(provider, message),
ResumeAfterAuth,
message,
CancellationToken.None);
CancellationToken.None).ConfigureAwait(false);
}
else if (message.Text.Equals(Resources.Help, StringComparison.CurrentCultureIgnoreCase))
{
await HelpAsync(context);
await HelpAsync(context).ConfigureAwait(false);
}
else
{
await base.MessageReceived(context, item);
await base.MessageReceived(context, item).ConfigureAwait(false);
}
}
finally
@ -191,9 +191,9 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
result.AssertNotNull(nameof(result));
string message = await result;
await context.PostAsync(message);
await context.PostAsync(message).ConfigureAwait(false);
await HelpAsync(context);
await HelpAsync(context).ConfigureAwait(false);
}
}
}

Просмотреть файл

@ -64,7 +64,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
public async Task StartAsync(IDialogContext context)
{
context.AssertNotNull(nameof(context));
await AuthenticateAsync(context);
await AuthenticateAsync(context).ConfigureAwait(false);
}
/// <summary>
@ -123,14 +123,14 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
provider.Configuration.GraphEndpoint,
provider.Configuration.ApplicationId,
redirectUri,
state);
state).ConfigureAwait(false);
message = context.MakeMessage();
message.Attachments.Add(SigninCard.Create(
Resources.SigninCardText, Resources.LoginCaptial, authUrl).ToAttachment());
await context.PostAsync(message);
await context.PostAsync(message).ConfigureAwait(false);
context.Wait(MessageReceivedAsync);
}
finally

Просмотреть файл

@ -84,7 +84,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
if (!string.IsNullOrEmpty(message?.Text))
{
result = await QnAService.QueryServiceAsync(message.Text);
result = await QnAService.QueryServiceAsync(message.Text).ConfigureAwait(false);
}
message = context.MakeMessage();

Просмотреть файл

@ -6,7 +6,7 @@
namespace Microsoft.Store.PartnerCenter.Bot.Extensions
{
using Logic.Office;
using Models;
using Microsoft.Bot.Connector;
public static class HealthEventExtensions
@ -16,7 +16,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Extensions
/// </summary>
/// <param name="healthEvent">An instance of <see cref="HealthEvent"/> to be transformed.</param>
/// <returns>An instance of <see cref="Attachment"/> that represents the health event.</returns>
public static Attachment ToAttachment(this HealthEvent healthEvent)
public static Attachment ToAttachment(this OfficeHealthEvent healthEvent)
{
HeroCard card = new HeroCard
{

Просмотреть файл

@ -7,7 +7,7 @@
namespace Microsoft.Store.PartnerCenter.Bot.Extensions
{
using System.Collections.Generic;
using System.Web;
using System.Globalization;
using Microsoft.Bot.Connector;
using PartnerCenter.Models.Subscriptions;
@ -20,21 +20,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Extensions
/// <returns>An instance <see cref="Attachment"/> that represents the subscription.</returns>
public static Attachment ToAttachment(this Subscription subscription)
{
string imageUrl;
string offerName = subscription.OfferName.ToLower();
if (offerName.Contains("azure") || offerName.Contains("active directory"))
{
imageUrl = $"{HttpContext.Current.Request.Url.Scheme}://{HttpContext.Current.Request.Url.Host}:{HttpContext.Current.Request.Url.Port}/content/images/azure-logo.png";
}
else if (offerName.Contains("office") || offerName.Contains("365"))
{
imageUrl = $"{HttpContext.Current.Request.Url.Scheme}://{HttpContext.Current.Request.Url.Host}:{HttpContext.Current.Request.Url.Port}/content/images/office-logo.png";
}
else
{
imageUrl = $"{HttpContext.Current.Request.Url.Scheme}://{HttpContext.Current.Request.Url.Host}:{HttpContext.Current.Request.Url.Port}/content/images/microsoft-logo.png";
}
string offerName = subscription.OfferName.ToLower(CultureInfo.CurrentCulture);
HeroCard card = new HeroCard
{
@ -47,13 +33,6 @@ namespace Microsoft.Store.PartnerCenter.Bot.Extensions
Value = $"select subscription {subscription.Id}"
}
},
Images = new List<CardImage>
{
new CardImage
{
Url = imageUrl
}
},
Subtitle = subscription.Id,
Title = subscription.FriendlyName
};

Просмотреть файл

@ -10,14 +10,13 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Extensions;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Luis.Models;
using Microsoft.Bot.Connector;
using PartnerCenter.Models.Customers;
using Security;
using Providers;
using Security;
/// <summary>
/// Processes the request to list customers.
@ -76,9 +75,9 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
{
startTime = DateTime.Now;
principal = await context.GetCustomerPrincipalAsync(provider);
principal = await context.GetCustomerPrincipalAsync(provider).ConfigureAwait(false);
customers = await provider.PartnerOperations.GetCustomersAsync(principal);
customers = await provider.PartnerOperations.GetCustomersAsync(principal).ConfigureAwait(false);
response = context.MakeMessage();
response.AttachmentLayout = AttachmentLayoutTypes.Carousel;
@ -94,18 +93,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
Value = $"select customer {c.Id}"
}
},
Images = new List<CardImage>
{
new CardImage
{
Url = $"{HttpContext.Current.Request.Url.Scheme}://{HttpContext.Current.Request.Url.Host}:{HttpContext.Current.Request.Url.Port}/api/images/dynamic?value={HttpUtility.UrlEncode(c.CompanyProfile.CompanyName)}"
}
},
Subtitle = c.CompanyProfile.Domain,
Title = c.CompanyProfile.CompanyName
}).ToAttachment()).ToList();
await context.PostAsync(response);
await context.PostAsync(response).ConfigureAwait(false);
// Capture the request for the customer summary for analysis.
eventProperties = new Dictionary<string, string>

Просмотреть файл

@ -76,24 +76,24 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
{
startTime = DateTime.Now;
principal = await context.GetCustomerPrincipalAsync(provider);
principal = await context.GetCustomerPrincipalAsync(provider).ConfigureAwait(false);
if (principal.CustomerId.Equals(provider.Configuration.PartnerCenterAccountId))
{
customer = await provider.PartnerOperations.GetCustomerAsync(principal);
customer = await provider.PartnerOperations.GetCustomerAsync(principal).ConfigureAwait(false);
response = context.MakeMessage();
response.Text = string.Format(Resources.SubscriptionRequestMessage, customer.CompanyProfile.CompanyName);
await context.PostAsync(response);
await context.PostAsync(response).ConfigureAwait(false);
}
subscriptions = await provider.PartnerOperations.GetSubscriptionsAsync(principal);
subscriptions = await provider.PartnerOperations.GetSubscriptionsAsync(principal).ConfigureAwait(false);
response = context.MakeMessage();
response.AttachmentLayout = AttachmentLayoutTypes.Carousel;
response.Attachments = subscriptions.Select(s => s.ToAttachment()).ToList();
await context.PostAsync(response);
await context.PostAsync(response).ConfigureAwait(false);
// Track the event measurements for analysis.
eventMetrics = new Dictionary<string, double>

Просмотреть файл

@ -12,10 +12,10 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
using System.Threading.Tasks;
using Extensions;
using IdentityModel.Clients.ActiveDirectory;
using Logic.Office;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Luis.Models;
using Microsoft.Bot.Connector;
using Services;
using Models;
using Providers;
using Security;
@ -60,13 +60,13 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
/// </exception>
public async Task ExecuteAsync(IDialogContext context, IAwaitable<IMessageActivity> message, LuisResult result, IBotProvider provider)
{
AuthenticationResult authResult;
CustomerPrincipal principal;
DateTime startTime;
Dictionary<string, double> eventMetrics;
Dictionary<string, string> eventProperties;
IMessageActivity response;
List<HealthEvent> healthEvents;
List<OfficeHealthEvent> healthEvents;
ServiceCommunications serviceComm;
string authority;
string customerId;
@ -79,7 +79,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
{
startTime = DateTime.Now;
principal = await context.GetCustomerPrincipalAsync(provider);
principal = await context.GetCustomerPrincipalAsync(provider).ConfigureAwait(false);
if (principal.CustomerId.Equals(provider.Configuration.PartnerCenterAccountId, StringComparison.CurrentCultureIgnoreCase))
{
@ -94,25 +94,21 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
customerId = principal.CustomerId;
}
authResult = await provider.AccessToken.GetAccessTokenAsync(
$"{provider.Configuration.ActiveDirectoryEndpoint}/{principal.Operation.CustomerId}",
provider.Configuration.OfficeManagementEndpoint,
new ApplicationCredential
{
ApplicationId = provider.Configuration.ApplicationId,
ApplicationSecret = provider.Configuration.ApplicationSecret,
UseCache = true
});
serviceComm = new ServiceCommunications(
new Uri(provider.Configuration.OfficeManagementEndpoint),
new ServiceCredentials(
provider.Configuration.ApplicationId,
provider.Configuration.ApplicationSecret.ToUnsecureString(),
provider.Configuration.OfficeManagementEndpoint,
principal.Operation.CustomerId));
healthEvents = await provider.ServiceCommunications.GetCurrentStatusAsync(
customerId,
authResult.AccessToken);
healthEvents = await serviceComm.GetHealthEventsAsync(principal.Operation.CustomerId).ConfigureAwait(false);
response = context.MakeMessage();
response.AttachmentLayout = AttachmentLayoutTypes.Carousel;
response.Attachments = healthEvents.Select(e => e.ToAttachment()).ToList();
await context.PostAsync(response);
await context.PostAsync(response).ConfigureAwait(false);
// Track the event measurements for analysis.
eventMetrics = new Dictionary<string, double>
@ -139,7 +135,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
provider.Telemetry.TrackException(ex);
await context.PostAsync(response);
await context.PostAsync(response).ConfigureAwait(false);
}
finally
{
@ -147,6 +143,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
eventProperties = null;
principal = null;
response = null;
serviceComm = null;
}
}
}

Просмотреть файл

@ -71,7 +71,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
new QuestionDialog(provider),
ResumeAfterQnA,
messageActivity,
CancellationToken.None);
CancellationToken.None).ConfigureAwait(false);
}
finally
{
@ -92,7 +92,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
try
{
messageActivity = await result;
await context.PostAsync(messageActivity);
await context.PostAsync(messageActivity).ConfigureAwait(false);
}
finally
{

Просмотреть файл

@ -77,7 +77,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
startTime = DateTime.Now;
response = context.MakeMessage();
principal = await context.GetCustomerPrincipalAsync(provider);
principal = await context.GetCustomerPrincipalAsync(provider).ConfigureAwait(false);
if (result.TryFindEntity("identifier", out indentifierEntity))
{
@ -93,11 +93,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
}
else
{
customer = await provider.PartnerOperations.GetCustomerAsync(principal, customerId);
customer = await provider.PartnerOperations.GetCustomerAsync(principal, customerId).ConfigureAwait(false);
response.Text = $"{Resources.CustomerContext} {customer.CompanyProfile.CompanyName}";
}
await context.PostAsync(response);
await context.PostAsync(response).ConfigureAwait(false);
// Capture the request for the customer summary for analysis.
eventProperties = new Dictionary<string, string>

Просмотреть файл

@ -77,14 +77,14 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
startTime = DateTime.Now;
response = context.MakeMessage();
principal = await context.GetCustomerPrincipalAsync(provider);
principal = await context.GetCustomerPrincipalAsync(provider).ConfigureAwait(false);
if (result.TryFindEntity("identifier", out indentifierEntity))
{
subscriptionId = indentifierEntity.Entity.Replace(" ", string.Empty);
principal.Operation.SubscriptionId = subscriptionId;
subscription = await provider.PartnerOperations.GetSubscriptionAsync(principal);
subscription = await provider.PartnerOperations.GetSubscriptionAsync(principal).ConfigureAwait(false);
if (subscription == null)
{
@ -105,7 +105,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
response.Text = $"{Resources.SubscriptionContext} {subscriptionId}";
}
await context.PostAsync(response);
await context.PostAsync(response).ConfigureAwait(false);
// Track the event measurements for analysis.
eventMetrics = new Dictionary<string, double>

Просмотреть файл

@ -1,105 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="CommunicationException.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Logic
{
using System;
using System.Net;
using System.Runtime.Serialization;
/// <summary>
/// User defined exception type that is thrown when an error is encountered communication with the Partner Center API.
/// </summary>
/// <seealso cref="Exception" />
/// <seealso cref="ISerializable" />
[Serializable]
public class CommunicationException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="CommunicationException"/> class.
/// </summary>
public CommunicationException()
{
HttpStatusCode = HttpStatusCode.InternalServerError;
}
/// <summary>
/// Initializes a new instance of the <see cref="CommunicationException"/> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public CommunicationException(string message) : base(message)
{
HttpStatusCode = HttpStatusCode.BadRequest;
}
/// <summary>
/// Initializes a new instance of the <see cref="CommunicationException" /> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
/// <param name="httpStatusCode">The HTTP status code that was encountered with the error.</param>
public CommunicationException(string message, HttpStatusCode httpStatusCode) : base(message)
{
HttpStatusCode = httpStatusCode;
}
/// <summary>
/// Initializes a new instance of the <see cref="CommunicationException"/> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
public CommunicationException(string message, Exception innerException) : base(message, innerException)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="CommunicationException" /> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
/// <param name="httpStatusCode">The HTTP status code that was encountered with the error.</param>
public CommunicationException(string message, Exception innerException, HttpStatusCode httpStatusCode)
: base(message, innerException)
{
HttpStatusCode = httpStatusCode;
}
/// <summary>
/// Initializes a new instance of the <see cref="CommunicationException"/> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
protected CommunicationException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
/// <summary>
/// Gets or sets the HTTP status code associated with the exception.
/// </summary>
public HttpStatusCode HttpStatusCode { get; protected set; }
/// <summary>
/// When overridden in a derived class, sets the <see cref="T:System.Runtime.Serialization.SerializationInfo" /> with information about the exception.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="*AllFiles*" PathDiscovery="*AllFiles*" />
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="SerializationFormatter" />
/// </PermissionSet>
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
{
throw new ArgumentNullException(nameof(info));
}
info.AddValue("HttpStatusCode", (int)HttpStatusCode);
base.GetObjectData(info, context);
}
}
}

Просмотреть файл

@ -102,7 +102,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
{
startTime = DateTime.Now;
directoryGroups = await client.Users[objectId].MemberOf.Request().GetAsync();
directoryGroups = await client.Users[objectId].MemberOf.Request().GetAsync().ConfigureAwait(false);
roles = new List<RoleModel>();
do
@ -118,7 +118,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
}));
}
if (customerId.Equals(provider.Configuration.PartnerCenterAccountId))
if (customerId.Equals(provider.Configuration.PartnerCenterAccountId, StringComparison.InvariantCultureIgnoreCase))
{
groups = directoryGroups.CurrentPage.OfType<Group>().Where(
g => g.DisplayName.Equals("AdminAgents") || g.DisplayName.Equals("HelpdeskAgents") || g.DisplayName.Equals("SalesAgent")).ToList();
@ -137,7 +137,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
if (morePages)
{
directoryGroups = await directoryGroups.NextPageRequest.GetAsync();
directoryGroups = await directoryGroups.NextPageRequest.GetAsync().ConfigureAwait(false);
}
}
while (morePages);

Просмотреть файл

@ -1,25 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IServiceCommunications.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Logic.Office
{
using System.Collections.Generic;
using System.Threading.Tasks;
/// <summary>
/// Represents the ability to interact with Office 365 Service Communications API.
/// </summary>
public interface IServiceCommunications
{
/// <summary>
/// Gets the current status information for the specified customer.
/// </summary>
/// <param name="customerId">Identifier for the customer.</param>
/// <param name="token">Access token to be utilized in the request.</param>
/// <returns>A list of <see cref="HealthEvent"/> objects that represent the current health events for the specified customer.</returns>
Task<List<HealthEvent>> GetCurrentStatusAsync(string customerId, string token);
}
}

Просмотреть файл

@ -1,22 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ODataResponse.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Logic.Office
{
using System.Collections.Generic;
/// <summary>
/// Represents a response from an OData endpoint.
/// </summary>
/// <typeparam name="T">Type returned from the API.</typeparam>
internal class ODataResponse<T>
{
/// <summary>
/// Gets or sets the value returned from the API.
/// </summary>
public List<T> Value { get; set; }
}
}

Просмотреть файл

@ -1,104 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ServiceCommunications.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Logic.Office
{
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Extensions;
using Newtonsoft.Json;
using Providers;
/// <summary>
/// Provides the ability to interact with Office 365 Service Communications API.
/// </summary>
public class ServiceCommunications : IServiceCommunications
{
/// <summary>
/// Provides access to core services.
/// </summary>
private readonly IBotProvider provider;
/// <summary>
/// Initializes a new instance of the <see cref="ServiceCommunications" /> class.
/// </summary>
/// <param name="provider">Provides access to core services.</param>
/// <exception cref="ArgumentNullException">
/// <paramref name="provider"/> is null.
/// </exception>
public ServiceCommunications(IBotProvider provider)
{
provider.AssertNotNull(nameof(provider));
this.provider = provider;
}
/// <summary>
/// Gets the current status information for the specified customer.
/// </summary>
/// <param name="customerId">Identifier for the customer.</param>
/// <param name="token">Access token to be utilized in the request.</param>
/// <returns>A list of <see cref="HealthEvent"/> objects that represent the current health events for the specified customer.</returns>
public async Task<List<HealthEvent>> GetCurrentStatusAsync(string customerId, string token)
{
DateTime startTime;
Dictionary<string, double> eventMetrics;
Dictionary<string, string> eventProperties;
HttpResponseMessage response;
ODataResponse<HealthEvent> odataResponse;
string content;
string requestUri;
try
{
startTime = DateTime.Now;
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
requestUri = $"{provider.Configuration.OfficeManagementEndpoint}/api/v1.0/{customerId}/ServiceComms/CurrentStatus";
response = await client.GetAsync(requestUri);
content = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new CommunicationException(content, response.StatusCode);
}
odataResponse = JsonConvert.DeserializeObject<ODataResponse<HealthEvent>>(content);
// Track the event measurements for analysis.
eventMetrics = new Dictionary<string, double>
{
{ "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds },
{ "NumberOfHealthEvents", odataResponse.Value.Count }
};
// Capture the request for the customer summary for analysis.
eventProperties = new Dictionary<string, string>
{
{ "CustomerId", customerId },
{ "RequestUri", requestUri }
};
provider.Telemetry.TrackEvent("GetCurrentStatusAsync", eventProperties, eventMetrics);
return odataResponse.Value;
}
}
finally
{
eventMetrics = null;
eventProperties = null;
response = null;
}
}
}
}

Просмотреть файл

@ -92,7 +92,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
{
startTime = DateTime.Now;
correlationId = Guid.NewGuid();
operations = await GetAppOperationsAsync(correlationId);
operations = await GetAppOperationsAsync(correlationId).ConfigureAwait(false);
rules = await operations.CountryValidationRules.ByCountry(countryCode).GetAsync().ConfigureAwait(false);
@ -159,7 +159,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
{
startTime = DateTime.Now;
correlationId = Guid.NewGuid();
operations = await GetAppOperationsAsync(correlationId);
operations = await GetAppOperationsAsync(correlationId).ConfigureAwait(false);
if (principal.CustomerId.Equals(provider.Configuration.PartnerCenterAccountId))
{
@ -223,7 +223,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
{
startTime = DateTime.Now;
correlationId = Guid.NewGuid();
operations = await GetAppOperationsAsync(correlationId);
operations = await GetAppOperationsAsync(correlationId).ConfigureAwait(false);
customers = new List<Customer>();
@ -299,7 +299,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
startTime = DateTime.Now;
correlationId = Guid.NewGuid();
operations = await GetAppOperationsAsync(correlationId);
operations = await GetAppOperationsAsync(correlationId).ConfigureAwait(false);
profile = await operations.Profiles.LegalBusinessProfile.GetAsync().ConfigureAwait(false);
@ -357,7 +357,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
{
startTime = DateTime.Now;
correlationId = Guid.NewGuid();
operations = await GetAppOperationsAsync(correlationId);
operations = await GetAppOperationsAsync(correlationId).ConfigureAwait(false);
try
{
@ -421,16 +421,17 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
{
startTime = DateTime.Now;
correlationId = Guid.NewGuid();
operations = await GetAppOperationsAsync(correlationId);
operations = await GetAppOperationsAsync(correlationId).ConfigureAwait(false);
if (principal.CustomerId.Equals(provider.Configuration.PartnerCenterAccountId))
{
principal.AssertValidCustomerContext(Resources.InvalidCustomerContextException);
subscriptions = await operations.Customers.ById(principal.Operation.CustomerId).Subscriptions.GetAsync();
subscriptions = await operations.Customers
.ById(principal.Operation.CustomerId).Subscriptions.GetAsync().ConfigureAwait(false);
}
else
{
subscriptions = await operations.Customers.ById(principal.CustomerId).Subscriptions.GetAsync();
subscriptions = await operations.Customers.ById(principal.CustomerId).Subscriptions.GetAsync().ConfigureAwait(false);
}
// Track the event measurements for analysis.
@ -514,7 +515,8 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
provider.Configuration.PartnerCenterApplicationSecret.ToUnsecureString(),
provider.Configuration.PartnerCenterAccountId).ConfigureAwait(false);
await provider.Cache.StoreAsync(CacheDatabaseType.Authentication, PartnerCenterCacheKey, credentials).ConfigureAwait(false);
await provider.Cache
.StoreAsync(CacheDatabaseType.Authentication, PartnerCenterCacheKey, credentials).ConfigureAwait(false);
return credentials;
}

Просмотреть файл

@ -235,7 +235,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Providers
clientId,
redirectUri,
UserIdentifier.AnyUser,
extraQueryParameters);
extraQueryParameters).ConfigureAwait(false);
return authUri.ToString();
}

Просмотреть файл

@ -10,7 +10,6 @@ namespace Microsoft.Store.PartnerCenter.Bot.Providers
using System.Threading.Tasks;
using Intents;
using Logic;
using Logic.Office;
using Telemetry;
/// <summary>
@ -54,12 +53,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Providers
/// Provides the ability to perform various partner operations.
/// </summary>
private static IPartnerOperations partnerOperations;
/// <summary>
/// Provides the ability to communicate with the Office 365 Service Communications API.
/// </summary>
private static IServiceCommunications serviceCommunications;
/// <summary>
/// Provides the ability to track telemetry data.
/// </summary>
@ -105,11 +99,6 @@ namespace Microsoft.Store.PartnerCenter.Bot.Providers
/// </summary>
public IPartnerOperations PartnerOperations => partnerOperations ?? (partnerOperations = new PartnerOperations(this));
/// <summary>
/// Gets the ability to communicate with the Office 365 Service Communications API.
/// </summary>
public IServiceCommunications ServiceCommunications => serviceCommunications ?? (serviceCommunications = new ServiceCommunications(this));
/// <summary>
/// Gets the telemetry service reference.
/// </summary>
@ -152,7 +141,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Providers
intent.Initialize();
await Configuration.InitializeAsync().ConfigureAwait(false);
await localization.InitializeAsync().ConfigureAwait(false);
await localization.InitializeAsync().ConfigureAwait(false);
}
}
}

Просмотреть файл

@ -9,7 +9,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Providers
using System.Threading.Tasks;
using Intents;
using Logic;
using Logic.Office;
using Services;
using Telemetry;
/// <summary>
@ -52,11 +52,6 @@ namespace Microsoft.Store.PartnerCenter.Bot.Providers
/// </summary>
IPartnerOperations PartnerOperations { get; }
/// <summary>
/// Gets a reference t the service communications service.
/// </summary>
IServiceCommunications ServiceCommunications { get; }
/// <summary>
/// Gets the telemetry service reference.
/// </summary>

Просмотреть файл

@ -51,7 +51,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Providers
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
public async Task ClearAsync(CacheDatabaseType database)
{
await Task.FromResult(0);
await Task.FromResult(0).ConfigureAwait(false);
}
/// <summary>
@ -65,8 +65,8 @@ namespace Microsoft.Store.PartnerCenter.Bot.Providers
/// </exception>
public async Task DeleteAsync(CacheDatabaseType database, string key = null)
{
IDatabase cache = await GetCacheReferenceAsync(database);
await cache.KeyDeleteAsync(key);
IDatabase cache = await GetCacheReferenceAsync(database).ConfigureAwait(false);
await cache.KeyDeleteAsync(key).ConfigureAwait(false);
}
/// <summary>
@ -107,8 +107,8 @@ namespace Microsoft.Store.PartnerCenter.Bot.Providers
{
key.AssertNotEmpty(nameof(key));
IDatabase cache = await GetCacheReferenceAsync(database);
RedisValue value = await cache.StringGetAsync(key);
IDatabase cache = await GetCacheReferenceAsync(database).ConfigureAwait(false);
RedisValue value = await cache.StringGetAsync(key).ConfigureAwait(false);
return value.HasValue ? DecompressEntity<TEntity>(value) : null;
}
@ -134,10 +134,10 @@ namespace Microsoft.Store.PartnerCenter.Bot.Providers
key.AssertNotEmpty(nameof(key));
entity.AssertNotNull(nameof(entity));
IDatabase cache = await GetCacheReferenceAsync(database);
IDatabase cache = await GetCacheReferenceAsync(database).ConfigureAwait(false);
await cache.StringSetAsync(
key, CompressEntity(entity), expiration);
key, CompressEntity(entity), expiration).ConfigureAwait(false);
}
/// <summary>
@ -287,7 +287,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Providers
if (connection == null)
{
connection = await ConnectionMultiplexer.ConnectAsync(
provider.Configuration.RedisCacheConnectionString.ToUnsecureString());
provider.Configuration.RedisCacheConnectionString.ToUnsecureString()).ConfigureAwait(false);
}
return connection.GetDatabase((int)database);

Просмотреть файл

@ -1,5 +1,5 @@
// -----------------------------------------------------------------------
// <copyright file="CustomBotAuthentication.cs" company="Microsoft">
// <copyright file="CustomBotAuthenticationAttribute.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
@ -14,13 +14,13 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
using Extensions;
using Microsoft.Bot.Connector;
using Providers;
/// <summary>
/// Provides custom authentication for the bot itself.
/// </summary>
/// <seealso cref="BotAuthentication" />
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomBotAuthentication : BotAuthentication
public sealed class CustomBotAuthenticationAttribute : BotAuthentication
{
/// <summary>
/// Occurs before the action method is invoked.

Просмотреть файл

@ -44,9 +44,217 @@
</system.web>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Linq.Parallel" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Timer" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encoding.Extensions" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encoding" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Globalization" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.RegularExpressions" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.InteropServices.RuntimeInformation" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Primitives" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Sockets" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Linq.Queryable" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Xml.ReaderWriter" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.Debug" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Resources.ResourceManager" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.SecureString" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Algorithms" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Overlapped" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression" publicKeyToken="B77A5C561934E089" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.Contracts" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Extensions" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Numerics" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ComponentModel.EventBasedAsync" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Concurrent" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.Tracing" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Dynamic.Runtime" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Primitives" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Principal" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ComponentModel" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Linq" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Extensions" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Xml.XmlSerializer" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Globalization.Extensions" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.NetworkInformation" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Xml.XDocument" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Serialization.Json" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ObjectModel" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Linq.Expressions" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Parallel" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Serialization.Primitives" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="CC7B13FFCD2DDD51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.Tools" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Requests" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Data.Common" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Serialization.Xml" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.3.0" newVersion="4.1.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.2" newVersion="4.1.1.2" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral" />
@ -114,7 +322,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.WindowsAzure.Storage" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.1.0.0" newVersion="9.1.0.0" />
<bindingRedirect oldVersion="0.0.0.0-9.1.1.0" newVersion="9.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bot.Builder.History" publicKeyToken="31bf3856ad364e35" culture="neutral" />
@ -162,4 +370,4 @@
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
</configuration>

Просмотреть файл

@ -27,6 +27,8 @@
<package id="Microsoft.Bot.Builder.CognitiveServices" version="1.1.2" targetFramework="net461" />
<package id="Microsoft.Bot.Builder.History" version="3.14.1.1" targetFramework="net461" />
<package id="Microsoft.Bot.Connector" version="3.14.1.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.FxCopAnalyzers" version="2.6.0" targetFramework="net461" developmentDependency="true" />
<package id="Microsoft.CodeQuality.Analyzers" version="2.6.0" targetFramework="net461" developmentDependency="true" />
<package id="Microsoft.Graph" version="1.8.1" targetFramework="net461" />
<package id="Microsoft.Graph.Core" version="1.8.1" targetFramework="net461" />
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.19.2" targetFramework="net461" />
@ -35,6 +37,8 @@
<package id="Microsoft.IdentityModel.Protocols" version="5.2.1" targetFramework="net461" />
<package id="Microsoft.IdentityModel.Protocols.OpenIdConnect" version="5.2.1" targetFramework="net461" />
<package id="Microsoft.IdentityModel.Tokens" version="5.2.1" targetFramework="net461" />
<package id="Microsoft.NetCore.Analyzers" version="2.6.0" targetFramework="net461" developmentDependency="true" />
<package id="Microsoft.NetFramework.Analyzers" version="2.6.0" targetFramework="net461" developmentDependency="true" />
<package id="Microsoft.Rest.ClientRuntime" version="2.3.11" targetFramework="net461" />
<package id="Microsoft.Rest.ClientRuntime.Azure" version="3.3.12" targetFramework="net461" />
<package id="Microsoft.Store.PartnerCenter" version="1.7.1" targetFramework="net461" />
@ -47,5 +51,6 @@
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.X509Certificates" version="4.3.2" targetFramework="net461" />
<package id="WindowsAzure.Storage" version="9.1.0" targetFramework="net461" />
<package id="Text.Analyzers" version="2.6.0" targetFramework="net461" developmentDependency="true" />
<package id="WindowsAzure.Storage" version="9.1.1" targetFramework="net461" />
</packages>