Skip to content

Api Check

Javier Calvarro Nelson edited this page Mar 9, 2018 · 8 revisions

Api check documentation

For instructions on how to run API Check in Korebuild look at KoreBuild

Basics

API Check detects breaking changes in public APIs by generating and storing an API listing of the base version of an assembly that later on gets compared with the API listing of the version of the assembly in development.

Usage:  .\Microsoft.AspNetCore.BuildTools.ApiCheck.exe [command]
Commands:
  compare
  generate
.\Microsoft.AspNetCore.BuildTools.ApiCheck.exe generate [options]

Options:
  -a|--assembly                   Path to the assembly to generate the ApiListing for
  -p|--project                    Path to the project.assets.json file
  -f|--framework                  The moniker for the framework the assembly to analyze was compiled against.
  -epi|--exclude-public-internal  Exclude types on the .Internal namespace from the generated report
  -o|--out                        Output path for the generated ApiListing file
  -h|--help                       Show help information

Note: If your project uses KoreBuild you can also generate baselines automatically by setting the APICHECK_GENERATE_BASELINE environment variable to 1 and running build.cmd.

Usage: .\Microsoft.AspNetCore.BuildTools.ApiCheck.exe compare [options]

Options:
  -b|--api-listing                Path to the API listing file to use as reference.
  -e|--exclusions                 Path to the exclusions file for the ApiListing
  -a|--assembly                   Path to the assembly to generate the ApiListing for
  -p|--project                    Path to the project.assets.json file
  -f|--framework                  The moniker for the framework the assembly to analyze was compiled against.
  -epi|--exclude-public-internal  Exclude types on the .Internal namespace from the generated report
  -h|--help                       Show help information

Understanding Breaking Changes

If you want to understand why/if something is a breaking change, the dotnet team has a good reference here

Adding exceptions

When a breaking change is desired, a breakingchanges file can be used. This file contains a list of desired/known breaking changes in JSON format where each entry is a JSON object with the following properties:

  • TypeId
  • MemberId
  • Kind

Type id corresponds to the signature of the type with fully qualified type names and T0, T1, and so on for generic parameters. Member id corresponds to the signature of the member with fully qualified type names and T0, T1, and so on for generic parameters. Kind indicates the type of change, it can be one of two values Addition or Removal.

All modifications are considered Removal since earlier type or member is no longer present.

Below is an example of a breaking change entry.

[
  {
        "TypeId": "public static class Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions",
        "MemberId": "public static Microsoft.EntityFrameworkCore.Query.IIncludableQueryable<T0, T2> ThenInclude<T0, T1, T2>(this Microsoft.EntityFrameworkCore.Query.IIncludableQueryable<T0, System.Collections.Generic.ICollection<T1>> source, System.Linq.Expressions.Expression<System.Func<T1, T2>> navigationPropertyPath) where T0 : class",
        "Kind": "Removal"
  }
]

If your project uses KoreBuild then following conventions are used to find files to compare API.

File name starts with

  • baseline - Json file for API listing of earlier version.
  • breakingchanges - Json file to specify desired breaking changes.

Above file names are appended by type of framework as following

  • Full framework - append by netframework
  • .NET core framework - append by netcore

Example:

  • File name for baseline on full framework - baseline.netframework.json
  • File name for breaking changes on .NET core framework - breakingchanges.netcore.json

For removing an existing property, both the getter and the setter need to be added to the exceptions file. For instance, to remove public IViewEngine ViewEngine { get; set; }:

[
    {
        "TypeId": "public class Microsoft.AspNetCore.Mvc.ViewComponentResult : Microsoft.AspNetCore.Mvc.ActionResult",
        "MemberId": "public Microsoft.AspNetCore.Mvc.ViewEngines.IViewEngine get_ViewEngine()",
        "Kind": "Removal"
    },
     {
        "TypeId": "public class Microsoft.AspNetCore.Mvc.ViewComponentResult : Microsoft.AspNetCore.Mvc.ActionResult",
        "MemberId": "public System.Void set_ViewEngine(Microsoft.AspNetCore.Mvc.ViewEngines.IViewEngine value)",
        "Kind": "Removal"
    }
]