Jacobi.Azure.ApiManagement.Policy 2.1.0

dotnet add package Jacobi.Azure.ApiManagement.Policy --version 2.1.0
                    
NuGet\Install-Package Jacobi.Azure.ApiManagement.Policy -Version 2.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Jacobi.Azure.ApiManagement.Policy" Version="2.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Jacobi.Azure.ApiManagement.Policy" Version="2.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Jacobi.Azure.ApiManagement.Policy" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Jacobi.Azure.ApiManagement.Policy --version 2.1.0
                    
#r "nuget: Jacobi.Azure.ApiManagement.Policy, 2.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Jacobi.Azure.ApiManagement.Policy@2.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Jacobi.Azure.ApiManagement.Policy&version=2.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Jacobi.Azure.ApiManagement.Policy&version=2.1.0
                    
Install as a Cake Tool

Azure APIM Policy CSharp

This library allows you to generate Azure API Management Policy XML files based on C# class implementations.

Usage

You implement a class for each Policy Xml file you whish to generate. The method and parameter names are kept the same as the Azure API Management Policy documentation to make it very easy to know what stuff does. See also the list of implemented policies below.

public sealed class MyPolicy : Jacobi.Azure.ApiManagement.Policy.PolicyDocument
{
    protected override void Inbound(IInbound inbound)
    {
      inbound
        .CheckHeader(...)
        .IpFilter(...)
        // other policies
        ;

        base.Inbound(inbound); // generates the <Base/> implicitly.
    }

    protected override void Backend(IBackend backend)
    {
        // add your policies here
        base.Backend(backend);
    }

    protected override void Outbound(IOutbound outbound)
    {
        // add your policies here
        base.Outbound(outbound);
    }

    protected override void OnError(IOnError onError)
    {
        // add your policies here
        base.OnError(onError);
    }
}

Simularly for a policy fragment:

public sealed class MyFragment : Jacobi.Azure.ApiManagement.Policy.PolicyFragment
{
    protected override void Fragment(IPolicyFragment fragment)
    {
      fragment
        .CheckHeader(...)
        .IpFilter(...)
        // other policies
        ;
      
      // no need to call the base
    }
}


When the project is built (successfully) a Policy XML file will be generated for each class - with the same file name (.xml) as the class.

Note that the resulting dotnet assembly is not used in anyway.

## Policy Expressions

Any values that can be an expression (either code or a literal value) is represented by the `PolicyExpression` class.

There are two implementation of this class:

- `PolicyExpression<T>` that is used in the interface method declarations to indicate whet data type is ultimately expected for the value. Although at this point, the return-type of any code is not verified, some validation takes place - it servers more as documentation.
- `PolicyExpression` is the type you typically use when constructing expressions.

An example of specifying a code expression using the `PolicyExpression.FromCode` would be:

```csharp
public sealed class MyPolicy : Jacobi.Azure.ApiManagement.Policy.PolicyDocument
{
    protected override void Inbound(IInbound inbound)
    {
      inbound
        .Choose(choose =>
            choose.When(PolicyExpression.FromCode("""Context.Variables.GetValueOrDefault<bool>("myvar", true)"""),
                actions => actions.SetBody(LiquidTemplate.From(""" body """))))
        base.Inbound(inbound);
    }
}

Note the use of the LiquidTemplate struct. Support for Liquid-templates is very rudementary and serves basically as a way to distinguish between PolicyExpression and LiquidTemplate strings.

Policies Implemented

Policy XML Files Output Folder

By default the generated policy XML files are written to the PolicyXml folder in the project root folder. However this can be easily changed by specifying an override in your .csproj file.

<PropertyGroup>
  <PolicyXmlOutputFolder>$(TargetPath)\MyCustomPolicyXmlFolder</PolicyXmlOutputFolder>
</PropertyGroup>

Replacement tokens (macros) can be used to build a folder path to where the policy xml files will be written. This example creates a new 'MyCustomPolicyXmlFolder' folder in the build-output folder next to the binaries.


TODO

For transparency:

  • Variables: check exists (variable-references in policies are typically created on demand)
  • Variables: Typed - to check the 'structure' of variables
  • PolicyExpression: TypeHint to document expected (result) type of literal or code expression
  • CodeExpression: {{named-value}} in code. Compiler will fail.
  • CodeExpression Compiler: (string)Context.Variables["connectionId"] error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement (suppressed for now)
  • Int32: validate non-negative or use uint.
  • Fragment scope: unclear what policies can (not) go in fragments
  • XslTransform: represent the xslt as something else than a plain string?
  • Keep track of the number of policy uses per document (for instance: cors can only be used once).
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.0 208 11/5/2025
2.0.0 201 11/2/2025
1.0.1 212 10/29/2025