This guide explains how to discover all API endpoints from an IIS server's API application pool using PowerShell reflection without external tools.
Get-IISApplication | Where-Object {$_.Path -like "*api*"} | Select Path, PhysicalPath
What it does:
Get-IISApplication
- Retrieves all IIS applications configured on the serverWhere-Object {$_.Path -like "api"}
- Filters applications whose path contains "api" Select Path, PhysicalPath
- Shows both the virtual path (like "/api") and physical disk path (like "C:\inetpub\wwwroot\api")Purpose: Locates where your API application files are stored on disk.
Get-ChildItem *.dll | Select Name
What it does:
Get-ChildItem *.dll
- Lists all .dll files in the current directory (bin folder)Select Name
- Shows only the filename of each DLLPurpose: Identifies which assemblies contain your API code. Look for files named like
or
.
$assembly = [System.Reflection.Assembly]::LoadFile("<full_path_to_api_dll>")
What it does:
[System.Reflection.Assembly]::LoadFile()
- .NET reflection method that loads a compiled assembly into memory
- Replace with complete path like "C:\inetpub\wwwroot\api\bin\YourApi.dll"$assembly
- Stores the loaded assembly object for further inspectionPurpose: Loads your API's compiled code so we can examine its structure programmatically.
$assembly.GetTypes() | Where-Object {$_.Name -like "*Controller*"} | ForEach-Object {
Write-Host $_.Name
$_.GetMethods() | Where-Object {$_.IsPublic} | Select-Object Name
}
What it does:
$assembly.GetTypes()
- Gets all classes/types defined in the assemblyWhere-Object {$_.Name -like "Controller"}
- Filters to classes with "Controller" in the nameForEach-Object
- Loops through each controller classWrite-Host $_.Name
- Prints the controller class name$_.GetMethods()
- Gets all methods (functions) in that controllerWhere-Object {$_.IsPublic}
- Filters to only public methods (API endpoints are public)Select-Object Name
- Shows method namesPurpose: Discovers all API controller classes and their public methods, which represent your API endpoints.
$controllers = $assembly.GetTypes() | Where-Object {$_.BaseType.Name -eq "ApiController"}
$controllers | ForEach-Object {
$controller = $_
$controller.GetMethods() | Where-Object {$_.IsPublic -and $_.DeclaringType -eq $controller} |
ForEach-Object { "$($controller.Name): $($_.Name)" }
}
What it does:
Where-Object {$_.BaseType.Name -eq "ApiController"}
- Finds classes that inherit from ApiController (Web API 2) or ControllerBase (Web API Core)$_.DeclaringType -eq $controller
- Ensures we only get methods defined in this controller (not inherited ones)"$($controller.Name): $($_.Name)"
- Formats output as "ControllerName: MethodName"Purpose: Creates a clean list showing which controller contains which endpoint methods.
$controllers | ForEach-Object {
$controller = $_
$controller.GetMethods() | ForEach-Object {
$method = $_
$attributes = $method.GetCustomAttributes($true)
$routeAttr = $attributes | Where-Object {$_.GetType().Name -like "*Route*"}
if($routeAttr) {
"$($controller.Name.Replace('Controller','')): $($method.Name) -> $($routeAttr.Template)"
}
}
}
What it does:
$method.GetCustomAttributes($true)
- Gets all attributes applied to the method (like [HttpGet], [Route])Where-Object {$_.GetType().Name -like "Route"}
- Finds routing attributes$routeAttr.Template
- Extracts the actual route template (like "api/users/{id}")Replace('Controller','')
- Removes "Controller" suffix for cleaner outputPurpose: Shows the actual HTTP routes/URLs for each endpoint, not just method names.
After running these commands, you'll see output like:
UsersController: GetUsers
UsersController: GetUser
UsersController: CreateUser
UsersController: UpdateUser
UsersController: DeleteUser
ProductsController: GetProducts
ProductsController: GetProduct
Look for DLLs named:
.Api.dll
.WebApi.dll
.Services.dll
Api.dll
WebApi.dll
If no controllers found:
Where-Object {$_.BaseType.Name -eq "ControllerBase"}
for .NET Core APIs$assembly.GetTypes() | Select Name
If assembly won't load: