diff --git a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/AdapterWithErrorHandler.cs b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/AdapterWithErrorHandler.cs index 4a02d27f7..49ff8c55a 100644 --- a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/AdapterWithErrorHandler.cs +++ b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/AdapterWithErrorHandler.cs @@ -1,23 +1,32 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -// -// Generated with Bot Builder V4 SDK Template for Visual Studio CoreBot v4.6.2 -using Microsoft.Bot.Builder.Integration.AspNet.Core; -using Microsoft.Bot.Builder.TraceExtensions; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Generated with Bot Builder V4 SDK Template for Visual Studio CoreBot v4.6.2 namespace Microsoft.Teams.Samples.HelloWorld.Web { + using Microsoft.Bot.Builder.Integration.AspNet.Core; + using Microsoft.Bot.Builder.TraceExtensions; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.Logging; + + /// + /// A custom BotFrameworkHttpAdapter with error handling capabilities. + /// public class AdapterWithErrorHandler : BotFrameworkHttpAdapter { + /// + /// Initializes a new instance of the class. + /// + /// The configuration for the bot. + /// The logger to use for logging errors. public AdapterWithErrorHandler(IConfiguration configuration, ILogger logger) : base(configuration, logger) { - OnTurnError = async (turnContext, exception) => + this.OnTurnError = async (turnContext, exception) => { // Log any leaked exception from the application. - logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); + logger.LogError(exception, "[OnTurnError] unhandled error : {Message}", exception.Message); // Uncomment below commented line for local debugging. // await turnContext.SendActivityAsync($"Sorry, it looks like something went wrong. Exception Caught: {exception.Message}"); @@ -27,4 +36,4 @@ public AdapterWithErrorHandler(IConfiguration configuration, ILogger +// Copyright (c) Microsoft Corporation. All rights reserved. +// namespace Microsoft.Teams.Samples.HelloWorld.Web { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + using Bogus; + using Microsoft.Bot.Builder; + using Microsoft.Bot.Builder.Teams; + using Microsoft.Bot.Schema; + using Microsoft.Bot.Schema.Teams; + using Newtonsoft.Json.Linq; + + /// + /// A bot that handles messaging extensions for Microsoft Teams. + /// public class MessageExtension : TeamsActivityHandler { + /// + /// Handles incoming message activities. + /// + /// The context object for this turn. + /// A cancellation token for the task. + /// A task that represents the work queued to execute. protected override async Task OnMessageActivityAsync(ITurnContext turnContext, CancellationToken cancellationToken) { turnContext.Activity.RemoveRecipientMention(); @@ -23,9 +36,17 @@ protected override async Task OnMessageActivityAsync(ITurnContext + /// Handles messaging extension queries. + /// + /// The context object for this turn. + /// The query object for the messaging extension. + /// A cancellation token for the task. + /// A task that represents the work queued to execute. + /// Thrown when the command ID is invalid. protected override Task OnTeamsMessagingExtensionQueryAsync(ITurnContext turnContext, MessagingExtensionQuery query, CancellationToken cancellationToken) { - var title = ""; + var title = string.Empty; var titleParam = query.Parameters?.FirstOrDefault(p => p.Name == "cardTitle"); if (titleParam != null) { @@ -51,41 +72,54 @@ protected override Task OnTeamsMessagingExtensionQue { AttachmentLayout = "list", Type = "result", - Attachments = attachments.ToList() + Attachments = attachments.ToList(), }, }; return Task.FromResult(result); + } + /// + /// Handles the selection of an item in a messaging extension. + /// + /// The context object for this turn. + /// The query object for the messaging extension. + /// A cancellation token for the task. + /// A task that represents the work queued to execute. + protected override Task OnTeamsMessagingExtensionSelectItemAsync(ITurnContext turnContext, JObject query, CancellationToken cancellationToken) + { + return Task.FromResult(new MessagingExtensionResponse + { + ComposeExtension = new MessagingExtensionResult + { + AttachmentLayout = "list", + Type = "result", + Attachments = new MessagingExtensionAttachment[] + { + new ThumbnailCard() + .ToAttachment() + .ToMessagingExtensionAttachment(), + }, + }, + }); } + /// + /// Creates a messaging extension attachment with a thumbnail card. + /// + /// The title for the card. + /// A messaging extension attachment. private static MessagingExtensionAttachment GetAttachment(string title) { var card = new ThumbnailCard { Title = !string.IsNullOrWhiteSpace(title) ? title : new Faker().Lorem.Sentence(), Text = new Faker().Lorem.Paragraph(), - Images = new List { new CardImage("http://lorempixel.com/640/480?rand=" + DateTime.Now.Ticks.ToString()) } + Images = new List { new CardImage("http://lorempixel.com/640/480?rand=" + DateTime.Now.Ticks.ToString()) }, }; return card .ToAttachment() .ToMessagingExtensionAttachment(); } - protected override Task OnTeamsMessagingExtensionSelectItemAsync(ITurnContext turnContext, JObject query, CancellationToken cancellationToken) - { - return Task.FromResult(new MessagingExtensionResponse - { - ComposeExtension = new MessagingExtensionResult - { - AttachmentLayout = "list", - Type = "result", - Attachments = new MessagingExtensionAttachment[]{ - new ThumbnailCard() - .ToAttachment() - .ToMessagingExtensionAttachment() - } - }, - }); - } } -} \ No newline at end of file +} diff --git a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Controllers/BotController.cs b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Controllers/BotController.cs index 0dd3b32f6..437037e23 100644 --- a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Controllers/BotController.cs +++ b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Controllers/BotController.cs @@ -1,36 +1,48 @@ +// // Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -// -// Generated with Bot Builder V4 SDK Template for Visual Studio EchoBot v4.6.2 -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Bot.Builder; -using Microsoft.Bot.Builder.Integration.AspNet.Core; +// +// Generated with Bot Builder V4 SDK Template for Visual Studio EchoBot v4.6.2 namespace Microsoft.Teams.Samples.HelloWorld.Web.Controllers { - // This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot - // implementation at runtime. Multiple different IBot implementations running at different endpoints can be - // achieved by specifying a more specific type for the bot constructor argument. + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.Bot.Builder; + using Microsoft.Bot.Builder.Integration.AspNet.Core; + + /// + /// This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot + /// implementation at runtime. Multiple different IBot implementations running at different endpoints can be + /// achieved by specifying a more specific type for the bot constructor argument. + /// [Route("api/messages")] [ApiController] public class BotController : ControllerBase { - private readonly IBotFrameworkHttpAdapter Adapter; - private readonly IBot Bot; + private readonly IBot bot; + private readonly IBotFrameworkHttpAdapter adapter; + /// + /// Initializes a new instance of the class. + /// + /// The bot framework HTTP adapter. + /// The bot instance. public BotController(IBotFrameworkHttpAdapter adapter, IBot bot) { - Adapter = adapter; - Bot = bot; + this.adapter = adapter; + this.bot = bot; } + /// + /// Handles the HTTP POST request. + /// + /// A task that represents the work queued to execute. [HttpPost] public async Task PostAsync() { // Delegate the processing of the HTTP POST to the adapter. // The adapter will invoke the bot. - await Adapter.ProcessAsync(Request, Response, Bot); + await this.adapter.ProcessAsync(this.Request, this.Response, this.bot); } } -} \ No newline at end of file +} diff --git a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Controllers/HomeController.cs b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Controllers/HomeController.cs index 294580eb0..14bc7d9e8 100644 --- a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Controllers/HomeController.cs +++ b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Controllers/HomeController.cs @@ -1,41 +1,65 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// namespace Microsoft.Teams.Samples.HelloWorld.Web.Controllers { + using Microsoft.AspNetCore.Mvc; + + /// + /// HomeController class to handle web requests for the home page and other routes. + /// + [Route("")] public class HomeController : Controller { + /// + /// Handles the default route and returns the Index view. + /// + /// The Index view. [Route("")] public ActionResult Index() { - return View(); + return this.View(); } + /// + /// Handles the /hello route and returns the Index view. + /// + /// The Index view. [Route("hello")] public ActionResult Hello() { - return View("Index"); + return this.View("Index"); } + /// + /// Handles the /first route and returns the First view. + /// + /// The First view. [Route("first")] public ActionResult First() { - return View(); + return this.View(); } + /// + /// Handles the /second route and returns the Second view. + /// + /// The Second view. [Route("second")] public ActionResult Second() { - return View(); + return this.View(); } + /// + /// Handles the /configure route and returns the Configure view. + /// + /// The Configure view. [Route("configure")] public ActionResult Configure() { - return View(); + return this.View(); } } } \ No newline at end of file diff --git a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/GlobalSuppressions.cs b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/GlobalSuppressions.cs new file mode 100644 index 000000000..720b1c955 --- /dev/null +++ b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/GlobalSuppressions.cs @@ -0,0 +1,8 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Major Code Smell", "S125:Sections of code should not be commented out", Justification = "This code needs to be uncommented for local debugging", Scope = "member", Target = "~M:Microsoft.Teams.Samples.HelloWorld.Web.AdapterWithErrorHandler.#ctor(Microsoft.Extensions.Configuration.IConfiguration,Microsoft.Extensions.Logging.ILogger{Microsoft.Bot.Builder.Integration.AspNet.Core.BotFrameworkHttpAdapter})")] +[assembly: SuppressMessage("Minor Code Smell", "S1075:URIs should not be hardcoded", Justification = "This URL will not change later", Scope = "member", Target = "~M:Microsoft.Teams.Samples.HelloWorld.Web.MessageExtension.GetAttachment(System.String)~Microsoft.Bot.Schema.Teams.MessagingExtensionAttachment")] diff --git a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Microsoft.Teams.Samples.HelloWorld.Web.csproj b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Microsoft.Teams.Samples.HelloWorld.Web.csproj index d10ca16f8..74051ce37 100644 --- a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Microsoft.Teams.Samples.HelloWorld.Web.csproj +++ b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Microsoft.Teams.Samples.HelloWorld.Web.csproj @@ -1,26 +1,42 @@  - - net6.0 - latest - + + net6.0 + latest + - - - - - + + + - - - - - - + + + - - - Always - - - \ No newline at end of file + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + Always + + + diff --git a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Program.cs b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Program.cs index 06799403e..d3b240fad 100644 --- a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Program.cs +++ b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Program.cs @@ -1,21 +1,33 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -// -// Generated with Bot Builder V4 SDK Template for Visual Studio EchoBot v4.6.2 -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// namespace Microsoft.Teams.Samples.HelloWorld.Web { - public class Program + using Microsoft.AspNetCore; + using Microsoft.AspNetCore.Hosting; + + /// + /// The main entry point for the application. + /// + public static class Program { + /// + /// The main method which is the entry point of the application. + /// + /// An array of command-line arguments. public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } + /// + /// Creates a new instance of the with pre-configured defaults. + /// + /// An array of command-line arguments. + /// An instance of . public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup(); } -} \ No newline at end of file +} diff --git a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Startup.cs b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Startup.cs index 749bf291c..71c47932c 100644 --- a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Startup.cs +++ b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Startup.cs @@ -1,27 +1,41 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -// -// Generated with Bot Builder V4 SDK Template for Visual Studio EchoBot v4.6.2 -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Bot.Builder; -using Microsoft.Bot.Builder.Integration.AspNet.Core; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Generated with Bot Builder V4 SDK Template for Visual Studio EchoBot v4.6.2 namespace Microsoft.Teams.Samples.HelloWorld.Web { + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Hosting; + using Microsoft.Bot.Builder; + using Microsoft.Bot.Builder.Integration.AspNet.Core; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Hosting; + + /// + /// The Startup class configures services and the app's request pipeline. + /// public class Startup { + /// + /// Initializes a new instance of the class. + /// + /// The configuration to use. public Startup(IConfiguration configuration) { - Configuration = configuration; + this.Configuration = configuration; } + /// + /// Gets the configuration instance. + /// public IConfiguration Configuration { get; } - // This method gets called by the runtime. Use this method to add services to the container. + /// + /// This method gets called by the runtime. Use this method to add services to the container. + /// + /// The collection of service descriptors. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); @@ -34,7 +48,11 @@ public void ConfigureServices(IServiceCollection services) services.AddTransient(); } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + /// + /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + /// + /// The application builder. + /// The web hosting environment. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) @@ -61,7 +79,6 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); - //app.UseHttpsRedirection(); } } -} \ No newline at end of file +} diff --git a/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/stylecop.json b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/stylecop.json new file mode 100644 index 000000000..94e215221 --- /dev/null +++ b/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/stylecop.json @@ -0,0 +1,14 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "companyName": "Microsoft Corporation" + } + } +}