0 Comments

If you’re using ASP.NET Core 3.1.1 and are seeing HTTP Error 500 when deploying your application into Azure App Service, there’s a high change that the issue is caused by a known issue:

If your project has a package reference that transtively references certain assemblies in the Microsoft.AspNetCore.App shared framework
that are also available as NuGet packages and executes on a runtime other than 64-bit Windows, you will receive a runtime exception at the time the assembly is loaded with a message like:

Could not load file or assembly 'Microsoft.AspNetCore.DataProtection.Abstractions, Version=3.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The located assembly's manifest definition does not match the assembly reference. (0x80131040)

 

Solution is to switch to 64 bit Azure App Service or to manually reference the problematic package.

Debugging this can be a pain as Azure App Service’s diagnostic tools think that everything is running smoothly and IIS’ stdout only reports that application has successfully started. What can help is wrapping the CreateWebHostBuilder inside a try-catch. Here’s an example which uses nLog:

        public static void Main(string[] args)
        {
            var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            var isDev = string.Equals(environment, "development", StringComparison.InvariantCultureIgnoreCase);
            var configFileName = isDev ? "nlog.Development.config" : "nlog.config";

            var logger = NLogBuilder.ConfigureNLog(configFileName).GetCurrentClassLogger();

            logger.Info("Starting application. {Environment}, {LoggingConfigurationFileName}", environment, configFileName);

            try
            {
                CreateWebHostBuilder(args).Build().Run();
            }
            catch (Exception e)
            {
                logger.Error(e, "Failed to start application", e);
            }
            finally
            {
                NLog.LogManager.Shutdown();
            }
        }

0 Comments

When Adaptive Cards for .NET is used to render a HTML card, the card renderer automatically adds few classes into the actions. Here’s an example where an adaptive card is rendered in ASP.NET Core using the defaults:

image

We can see that the actions automatically get classes like ac-pushButton and ac-action-openUrl. CSS can be used to customize these classes. But if you’re using something like Bootstrap, it’s quite likely that you want to use classes like btn and btn-primary. This post shows how to use Bootstrap’s btn-classes with Adaptive Cards’ HTML renderer in ASP.NET Core.

Modifying the HTML renderer

You can modify the adaptive cards’ HTML renderer to inject the classes you like. The modifications happen through AdaptiveCardRenderer.ActionTransformers.Register. The modifications can be registered for example in the Configure-method of the application:

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddLocalization();
            services.AddDistributedMemoryCache();
            services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(20); });

            AdaptiveCardRenderer.ActionTransformers.Register<AdaptiveOpenUrlAction>((action, tag, context) =>
            {
                tag.AddClass("btn");
                tag.AddClass("btn-primary");
            });

The example above adds “btn” and “btn-primary” classes into each OpenUrl action:

image

Conditional classes

Classes can be added conditionally, based on the card’s schema. Here’s an example where action’s style is used to define the applied CSS classes:

            AdaptiveCardRenderer.ActionTransformers.Register<AdaptiveOpenUrlAction>((action, tag, context) =>
            {
                tag.AddClass("btn");

                if (string.Equals(action.Style, "destructive", StringComparison.InvariantCultureIgnoreCase))
                {
                    tag.AddClass("btn-danger");
                }
                else
                {
                    tag.AddClass("btn-primary");
                }
            });

image

As we can see, btn-danger is applied to the button on the right side.

image

Custom attributes

Register-method can be used for more than just adding custom classes. AddAttribute can be used to add new custom attributes to the button:

            AdaptiveCardRenderer.ActionTransformers.Register<AdaptiveOpenUrlAction>((action, tag, context) =>
            {
                tag.Attr("id", AdaptiveCardRenderer.GenerateRandomId());
                tag.Attr("data-ac-url", action.Url);
            });

Note

Register-method can be called only once per element type. If you have multiple calls to Register<AdaptiveOpenUrl>, the last one wins:

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddLocalization();
            services.AddDistributedMemoryCache();
            services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(20); });

            AdaptiveCardRenderer.ActionTransformers.Register<AdaptiveOpenUrlAction>((action, tag, context) =>
            {
                tag.AddClass("btn");
                tag.AddClass("btn-primary");
            });
            
            AdaptiveCardRenderer.ActionTransformers.Register<AdaptiveOpenUrlAction>((action, tag, context) =>
            {
                tag.AddClass("btn");
                tag.AddClass("btn-danger");
            });

image

0 Comments

Attach to dotnet.exe extension for Visual Studio 2017 & 2019 now has a new version 1.0.0.1. As the version number indicates, only a small thing has changed: The extension manifest had problems with its dependencies, causing issues when trying to install the extension to VS 2019 Preview.

The new version is now available for download from the project’s repository: https://github.com/mikoskinen/AttachToDotnet/tree/master/releases/1.0.0.1

Unfortunately the extension is still not available through the Visual Studio’s extension marketplace, but I hope to have it there in the following week.

Background

Just a quick recap and reasoning for the extension: There’s usually many dotnet.exe processes. Attaching Visual Studio’s debugger to the correct one can be hard. This extensions aims to solve the issue by displaying the actual .DLL of the dotnet.exe process.

0 Comments

I’ve released a new open source extension for Visual Studio 2017&2019 which aims to make it easier to attach and to reattach the Visual Studio debugger to the correct dotnet.exe process:

With the default “Attach to process” –feature in Visual Studio it’s often hard to know what is the correct dotnet.exe to debug. Without the extension the visibility to dotnet.exe process is often this:

The extension aims to solve this issue by parsing the actual application from the process’ command line. In addition to displaying and attaching to a particular project, the extension provides “Reattach to dotnet.exe” command. This functionality works even if the process id changes (as it does when using dotnet watch).

Default shortcuts: 

  • Reattach: CTRL + Shift + Del
  • Attach: Shift + Del

Note: For now the extension has been mainly tested with ASP.NET Core 2.0 based applications. Later versions of ASP.NET Core and .NET Core may change things so it’s possible that the extension displays these processes incorrectly.

The extension is not yetavailable from Visual Studio Marketplace but I hope to see it there shortly. But you can download and install it from here: https://github.com/mikoskinen/AttachToDotnet/tree/master/releases/1.0.0.0

The source code for the extension is available through Github: https://github.com/mikoskinen/AttachToDotnet

0 Comments

Your Blazor Components can implement interfaces even if you’re not using code-behind files. Given that a basic components looks like the following:

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

@functions {

}

It’s not directly obvious how the implementation happens. But for that, we have the “@implements” directive:

@page "/"
@implements IMainPage

We can do the actual implementation in the functions-block:

@functions {
    public void UpdateText()
    {
        // Implementation logic
    }
}

Here’s a full example:

@page "/"
@implements IMainPage

<h1>Hello, world!</h1>

Welcome to your new app.

@functions {
    public void UpdateText()
    {
        // Implementation logic
    }
}