Skip to content
This repository has been archived by the owner on Jun 30, 2022. It is now read-only.

Commit

Permalink
Merge pull request #3829 from southworks/external/feature/southworks/…
Browse files Browse the repository at this point in the history
…deprecation-plan/fix-c#-template-parity

[C#][VA/Skill] Replicate changes of Samples to Templates
  • Loading branch information
lauren-mills authored Jun 21, 2021
2 parents 5509384 + 775f62b commit 60f6ed7
Show file tree
Hide file tree
Showing 18 changed files with 228 additions and 21 deletions.
4 changes: 2 additions & 2 deletions templates/csharp/Skill/Skill/Services/BotServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public BotServices(BotSettings settings, IBotTelemetryClient client)
luisOptions = new LuisRecognizerOptionsV3(dispatchApp)
{
TelemetryClient = telemetryClient,
LogPersonalInformation = true,
LogPersonalInformation = settings.LogPersonalData,
};
set.DispatchService = new LuisRecognizer(luisOptions);
}
Expand All @@ -49,7 +49,7 @@ public BotServices(BotSettings settings, IBotTelemetryClient client)
luisOptions = new LuisRecognizerOptionsV3(luisApp)
{
TelemetryClient = telemetryClient,
LogPersonalInformation = true,
LogPersonalInformation = settings.LogPersonalData,
};
set.LuisServices.Add(model.Id, new LuisRecognizer(luisOptions));
}
Expand Down
1 change: 1 addition & 0 deletions templates/csharp/Skill/Skill/Services/BotSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ namespace $safeprojectname$.Services
{
public class BotSettings : BotSettingsBase
{
public bool LogPersonalData { get; set; }
}
}
3 changes: 0 additions & 3 deletions templates/csharp/Skill/Skill/SkillProjectTemplate.vstemplate
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@
<Folder Name="Adapters" TargetFolderName="Adapters">
<ProjectItem ReplaceParameters="true" TargetFileName="DefaultAdapter.cs">DefaultAdapter.cs</ProjectItem>
</Folder>
<Folder Name="Authentication" TargetFolderName="Authentication">
<ProjectItem ReplaceParameters="true" TargetFileName="AllowedCallersClaimsValidator.cs">AllowedCallersClaimsValidator.cs</ProjectItem>
</Folder>
<Folder Name="Bots" TargetFolderName="Bots">
<ProjectItem ReplaceParameters="true" TargetFileName="DefaultActivityHandler.cs">DefaultActivityHandler.cs</ProjectItem>
</Folder>
Expand Down
15 changes: 12 additions & 3 deletions templates/csharp/Skill/Skill/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ public void ConfigureServices(IServiceCollection services)
});

// Load settings
var settings = new BotSettings();
var settings = new BotSettings()
{
LogPersonalData = Configuration.GetSection("logPersonalInfo")?.Value.ToLower() == "true"
};
Configuration.Bind(settings);
services.AddSingleton(settings);
services.AddSingleton<BotSettingsBase>(settings);
Expand All @@ -85,8 +88,14 @@ public void ConfigureServices(IServiceCollection services)
services.AddSingleton<ITelemetryInitializer, OperationCorrelationTelemetryInitializer>();
services.AddSingleton<ITelemetryInitializer, TelemetryBotIdInitializer>();
services.AddSingleton<TelemetryInitializerMiddleware>();
services.AddSingleton<TelemetryLoggerMiddleware>();

if (settings.LogPersonalData)
{
services.AddSingleton<TelemetryLoggerMiddleware>(s => new TelemetryLoggerMiddleware(s.GetService<IBotTelemetryClient>(), true));
}
else
{
services.AddSingleton<TelemetryLoggerMiddleware>();
}
// Configure bot services
services.AddSingleton<BotServices>();

Expand Down
3 changes: 2 additions & 1 deletion templates/csharp/Skill/Skill/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
"containerId": "botstate-collection",
"databaseId": "botstate-db"
},
"properties": {}
"properties": {},
"logPersonalInfo": true
}
14 changes: 13 additions & 1 deletion templates/csharp/VA/VA.Tests/BotTestBase.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
Expand All @@ -16,8 +17,11 @@
using Microsoft.Bot.Solutions.Responses;
using Microsoft.Bot.Solutions.Skills.Dialogs;
using Microsoft.Bot.Solutions.Testing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using $ext_safeprojectname$.Bots;
using $ext_safeprojectname$.Dialogs;
using $ext_safeprojectname$.Models;
Expand Down Expand Up @@ -53,7 +57,7 @@ protected Templates AllResponsesTemplates
[TestInitialize]
public virtual void Initialize()
{
Services = new ServiceCollection();
Services = new ServiceCollection().AddLogging(config => config.AddConsole());
Services.AddSingleton(new BotSettings());
Services.AddSingleton(new BotServices()
{
Expand Down Expand Up @@ -131,6 +135,14 @@ public virtual void Initialize()
Services.AddSingleton<TestAdapter, DefaultTestAdapter>();
Services.AddTransient<IBot, DefaultActivityHandler<MockMainDialog>>();

// Add MicrosoftAPPId to configuration
var configuration = new Mock<IConfiguration>();
var configurationSection = new Mock<IConfigurationSection>();
configurationSection.Setup(a => a.Value).Returns("testvalue");
configuration.Setup(a => a.GetSection("MicrosoftAppId")).Returns(configurationSection.Object);
// Register configuration
Services.AddSingleton(configuration.Object);

TestUserProfileState = new UserProfileState();
TestUserProfileState.Name = "Bot";
}
Expand Down
1 change: 1 addition & 0 deletions templates/csharp/VA/VA.Tests/VA.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="Moq" Version="4.14.1" />
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
<PackageReference Include="RichardSzalay.MockHttp" Version="6.0.0" />
Expand Down
61 changes: 60 additions & 1 deletion templates/csharp/VA/VA/Bots/DefaultActivityHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,26 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Choices;
using Microsoft.Bot.Builder.Integration.AspNet.Core.Skills;
using Microsoft.Bot.Builder.Teams;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Connector.Authentication;
using Microsoft.Bot.Schema;
using Microsoft.Bot.Schema.Teams;
using Microsoft.Bot.Solutions;
using Microsoft.Bot.Solutions.Responses;
using Microsoft.Bot.Solutions.Skills;
using Microsoft.Bot.Solutions.Skills.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using $safeprojectname$.Extensions;
using $safeprojectname$.Models;

namespace $safeprojectname$.Bots
Expand All @@ -27,8 +36,13 @@ public class DefaultActivityHandler<T> : TeamsActivityHandler
private readonly IStatePropertyAccessor<DialogState> _dialogStateAccessor;
private readonly IStatePropertyAccessor<UserProfileState> _userProfileState;
private readonly LocaleTemplateManager _templateManager;
private readonly SkillHttpClient _skillHttpClient;
private readonly SkillsConfiguration _skillsConfig;
private readonly IConfiguration _configuration;
private readonly string _virtualAssistantBotId;
private readonly ILogger _logger;

public DefaultActivityHandler(IServiceProvider serviceProvider, T dialog)
public DefaultActivityHandler(IServiceProvider serviceProvider, ILogger<DefaultActivityHandler<T>> logger, T dialog)
{
_dialog = dialog;
_dialog.TelemetryClient = serviceProvider.GetService<IBotTelemetryClient>();
Expand All @@ -37,6 +51,11 @@ public DefaultActivityHandler(IServiceProvider serviceProvider, T dialog)
_dialogStateAccessor = _conversationState.CreateProperty<DialogState>(nameof(DialogState));
_userProfileState = _userState.CreateProperty<UserProfileState>(nameof(UserProfileState));
_templateManager = serviceProvider.GetService<LocaleTemplateManager>();
_skillHttpClient = serviceProvider.GetService<SkillHttpClient>();
_skillsConfig = serviceProvider.GetService<SkillsConfiguration>();
_configuration = serviceProvider.GetService<IConfiguration>();
_virtualAssistantBotId = _configuration.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey)?.Value;
_logger = logger;
}

public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
Expand Down Expand Up @@ -104,9 +123,49 @@ protected override async Task OnEventActivityAsync(ITurnContext<IEventActivity>
}
}

// Invoked when a "task/fetch" event is received to invoke task module.
protected override async Task<TaskModuleResponse> OnTeamsTaskModuleFetchAsync(ITurnContext<IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken)
{
return await this.ProcessTaskModuleInvokeAsync(turnContext, cancellationToken);
}

// Invoked when a 'task/submit' invoke activity is received for task module submit actions.
protected override async Task<TaskModuleResponse> OnTeamsTaskModuleSubmitAsync(ITurnContext<IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken)
{
return await this.ProcessTaskModuleInvokeAsync(turnContext, cancellationToken);
}

protected override async Task OnEndOfConversationActivityAsync(ITurnContext<IEndOfConversationActivity> turnContext, CancellationToken cancellationToken)
{
await _dialog.RunAsync(turnContext, _dialogStateAccessor, cancellationToken);
}

private async Task<TaskModuleResponse> ProcessTaskModuleInvokeAsync(ITurnContext<IInvokeActivity> turnContext, CancellationToken cancellationToken)
{
try
{
// Get Skill From TaskInvoke
var skillId = (turnContext.Activity as Activity).AsInvokeActivity().GetSkillId(_logger);
var skill = _skillsConfig.Skills.Where(s => s.Value.AppId == skillId).FirstOrDefault().Value;

// Forward request to correct skill
var invokeResponse = await _skillHttpClient.PostActivityAsync(_virtualAssistantBotId, skill, _skillsConfig.SkillHostEndpoint, turnContext.Activity as Activity, cancellationToken).ConfigureAwait(false);

// Temporary workaround to get correct invokeresponse
// issue: https://github.com/microsoft/botframework-sdk/issues/5929
var response = new InvokeResponse()
{
Status = invokeResponse.Status,
Body = ((Microsoft.Bot.Builder.InvokeResponse<object>)invokeResponse).Body
};

return response.GetTaskModuleResponse();
}
catch
{
await turnContext.SendActivityAsync(_templateManager.GenerateActivityForLocale("ErrorMessage"));
throw;
}
}
}
}
5 changes: 4 additions & 1 deletion templates/csharp/VA/VA/Dialogs/MainDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class MainDialog : ComponentDialog

private readonly LocaleTemplateManager _templateManager;
private readonly BotServices _services;
private readonly BotSettings _settings;
private readonly OnboardingDialog _onboardingDialog;
private readonly SwitchSkillDialog _switchSkillDialog;
private readonly SkillsConfiguration _skillsConfig;
Expand All @@ -44,6 +45,7 @@ public MainDialog(
IServiceProvider serviceProvider)
: base(nameof(MainDialog))
{
_settings = serviceProvider.GetService<BotSettings>();
_services = serviceProvider.GetService<BotServices>();
_templateManager = serviceProvider.GetService<LocaleTemplateManager>();
_skillsConfig = serviceProvider.GetService<SkillsConfiguration>();
Expand Down Expand Up @@ -189,7 +191,8 @@ protected virtual QnAMakerDialog TryCreateQnADialog(string knowledgebaseId, Cogn
activeLearningCardTitle: _templateManager.GenerateActivityForLocale("QnaMakerAdaptiveLearningCardTitle").Text,
cardNoMatchText: _templateManager.GenerateActivityForLocale("QnaMakerNoMatchText").Text)
{
Id = knowledgebaseId
Id = knowledgebaseId,
LogPersonalInformation = _settings.LogPersonalData
};
}
else
Expand Down
39 changes: 39 additions & 0 deletions templates/csharp/VA/VA/Extensions/InvokeActivityExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using AdaptiveExpressions;
using Microsoft.Bot.Schema;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using $safeprojectname$.Models;

namespace $safeprojectname$.Extensions
{
/// <summary>
/// Extension class for getting SkillId from Activity.
/// </summary>
public static class InvokeActivityExtensions
{
// Fetches skillId from CardAction data if present
public static string GetSkillId(this IInvokeActivity activity, ILogger logger)
{
if (activity == null)
{
logger.Log(LogLevel.Error, "activity is null from TaskModule");
throw new ArgumentNullException(nameof(activity));
}

if (activity.Value == null)
{
logger.Log(LogLevel.Error, "activity.Value is null from TaskModule");
throw new ArgumentException("activity.Value is null.", nameof(activity));
}

// GetSkillId from Activity Value
var data = JObject.Parse(activity.Value.ToString()).SelectToken("data.data")?.ToObject<SkillCardActionData>();
return data.SkillId ?? throw new ArgumentException("SkillId in TaskModule is null", nameof(SkillCardActionData));
}
}
}
57 changes: 57 additions & 0 deletions templates/csharp/VA/VA/Extensions/InvokeResponseExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema.Teams;
using Newtonsoft.Json.Linq;

namespace $safeprojectname$.Extensions
{
/// <summary>
/// InvokeResposneHandler class for returning TaskModuleResponse from InvokeResponse
/// </summary>
public static class InvokeResponseExtensions
{
// Converts "InvokeResponse" sent by SkillHttpClient to "TaskModuleResponse"
public static TaskModuleResponse GetTaskModuleResponse(this InvokeResponse invokeResponse)
{
if (invokeResponse == null)
{
throw new ArgumentNullException(nameof(invokeResponse));
}

if (invokeResponse.Body != null)
{
return new TaskModuleResponse()
{
Task = GetTask(invokeResponse.Body),
};
}

return null;
}

private static TaskModuleResponseBase GetTask(object invokeResponseBody)
{
var responseBody = JObject.FromObject(invokeResponseBody);
var task = responseBody.GetValue("task");
string taskType = task.SelectToken("type")?.Value<string>();

return taskType switch
{
"continue" => new TaskModuleContinueResponse()
{
Type = taskType,
Value = task.SelectToken("value").ToObject<TaskModuleTaskInfo>(),
},
"message" => new TaskModuleMessageResponse()
{
Type = taskType,
Value = task.SelectToken("value").ToString(),
},
_ => null,
};
}
}
}
20 changes: 20 additions & 0 deletions templates/csharp/VA/VA/Models/SkillCardActionData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Newtonsoft.Json;

namespace $safeprojectname$.Models
{
/// <summary>
/// Skill Card action data should contain skillName parameter
/// This class is used to deserialize it and get skillName.
/// </summary>
/// <value>
/// SkillName.
/// </value>
public class SkillCardActionData
{
[JsonProperty("SkillId")]
public string SkillId { get; set; }
}
}
4 changes: 2 additions & 2 deletions templates/csharp/VA/VA/Services/BotServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public BotServices(BotSettings settings, IBotTelemetryClient client)
luisOptions = new LuisRecognizerOptionsV3(dispatchApp)
{
TelemetryClient = telemetryClient,
LogPersonalInformation = true,
LogPersonalInformation = settings.LogPersonalData,
};
set.DispatchService = new LuisRecognizer(luisOptions);
}
Expand All @@ -49,7 +49,7 @@ public BotServices(BotSettings settings, IBotTelemetryClient client)
luisOptions = new LuisRecognizerOptionsV3(luisApp)
{
TelemetryClient = telemetryClient,
LogPersonalInformation = true,
LogPersonalInformation = settings.LogPersonalData,
};
set.LuisServices.Add(model.Id, new LuisRecognizer(luisOptions));
}
Expand Down
Loading

0 comments on commit 60f6ed7

Please sign in to comment.