Skip to main content

Running Microsoft Playwright in an Azure Function using C#

When you have tried to run MS Playwright using C# in the context of an Azure Function, you probably have run into this message:


The driver it is referring to resides in the .playwright folder that is copied to the build output folder. Now, the output folder structure of an Azure Function project is different from most projects in the sense that there is an extra nested bin folder where the drivers should actually be copied. 

The build target that the Playwright team uses, at the time of writing (version 1.15.4), always copies the folder containing the driver to the root of the output folder. So the fix here is to add an extra build target to your project file, the corrects for the extra nested folder:

  <Target Name="FixPlaywrightCopyAfterBuild" AfterTargets="Build">

    <ItemGroup>

      <_BuildCopyItems Include="$(OutDir).playwright\**" />

    </ItemGroup>

    <Message Text="[Fix] Copying files to the nested bin folder of the azure function... $(OutDir)bin" Importance="high"/>

    <Copy SourceFiles="@(_BuildCopyItems)" DestinationFiles="@(_BuildCopyItems->'$(OutDir)bin\.playwright\%(RecursiveDir)%(Filename)%(Extension)')"/>

  </Target>

This will enable you to run the function. But this only works for the build scenario. When publishing the function to Azure, for instance, the output folder is different again. So we have to correct for that to:

  <Target Name="FixPlaywrightCopyAfterPublish" AfterTargets="Publish">

    <ItemGroup>

      <_BuildCopyItems Include="$(PublishDir).playwright\**" />

    </ItemGroup>

    <Message Text="[Fix] Copying files to the nested bin folder of the azure function for publishing... $(PublishDir)bin" Importance="high"/>

    <Copy SourceFiles="@(_BuildCopyItems)" DestinationFiles="@(_BuildCopyItems->'$(PublishDir)bin\.playwright\%(RecursiveDir)%(Filename)%(Extension)')"/>

  </Target>

Hope it will help people since I noticed more people encountering this issue.


Comments

Popular posts from this blog

Model View Update (MVU) pattern using ASP .NET components and Blazor

A primer on Model View Update (MVU) (UPDATE: The MVU library will be available via  Blazique/Blazique (github.com)  soon. The projects will be removed from Radix with the next major release after the move has been completed). The Model-View-Update (MVU) architecture is a sophisticated blueprint for designing interactive programs, including web applications and games. This architecture is characterized by a unidirectional data flow and is composed of three integral components: the Model, the View, and the Update. The Model is the heart of your application, encapsulating its state. The model preferably should be represented by an immutable data type. The View function is tasked with creating the visual representation of your application. It is a pure function that takes the current model as input and returns a user interface description, such as HTML elements or graphics. The View function refrains from performing any side effects like mut

Type aliases using C# Source Generators and C# 10 generic attributes

When practicing domain-driven design, a reoccurring chore is the creation of value types. These are strongly typed representations of simple types like strings that have a specific meaning, like CustomerId or ProductCode. These could both be strings but we put preferably implement them as strongly typed variations so that we can't for instance mix up multiple string parameters while coding. In some languages, this is something that comes out of the box and is often referred to as type aliasing. C# does not support this. Although in C# you could give another name to a string type with a using statement, it still remains a string (the type does not change).  This task is so common and tedious that it makes it the perfect case for implementing a source generator. Creating a type alias should be as simple as adding an attribute indicating what type should be aliased. It should also work for all kinds of types, like class, record, struct, and record struct. The full source code can be f