Skip to main content

Overview

Microsoft.PackageManagement.Search.Web is a small, focused shared library that provides the reusable ASP.NET Core infrastructure for NuGet search service web applications. It contains no controllers, no business logic, and no Azure Search integration of its own. Instead, it supplies three pieces of infrastructure:
  1. Host construction — a pre-configured IHostBuilder that strips out noisy environment variables and wires in Autofac as the DI container.
  2. Startup helpers — Azure Key Vault secret injection into configuration, standard ASP.NET Core middleware pipeline setup (routing, CORS, HSTS, security headers), and a utility for building Application Insights operation names.
  3. Exception filtering — an MVC ExceptionFilterAttribute that maps domain exceptions from NuGet.Services.AzureSearch to appropriate HTTP status codes.
The library targets net6.0 and is published as a versioned NuGet package alongside the rest of the NuGetGallery jobs packages.

Role in the System

Consumed by SearchService.Core

NuGet.Services.SearchService.Core is the primary consumer. Its Program.cs calls HostBuilderHelper.CreateHostBuilder and its Startup.cs calls StartupHelper methods.

Sits above AzureSearch

Depends on NuGet.Services.AzureSearch for AzureSearchException, InvalidSearchRequestException, and ErrorResponse types used in the exception filter.

Enables multi-host deployment

By encapsulating host bootstrap logic in a shared library, additional search-flavored web applications can reuse the same secure configuration and middleware setup without duplicating Key Vault wiring.

Security boundary

All incoming environment variables are filtered to only the APPSETTING_ prefix. Key Vault secrets are injected at startup; foreground request threads are forbidden from triggering uncached secret reads to avoid deadlocks.

Key Files and Classes

FileClassPurpose
HostBuilderHelper.csHostBuilderHelperStatic factory that creates the IHostBuilder. Removes all default EnvironmentVariablesConfigurationSource entries and replaces them with a single source scoped to the APPSETTING_ prefix. Registers Autofac as the service provider factory.
StartupHelper.csStartupHelperStatic helpers called from a host’s Startup class. Provides GetSecretInjectedConfiguration (Key Vault injection + refresh), Configure (middleware pipeline), and GetOperationName<T> (Application Insights telemetry naming).
StartupHelper.csRefreshableConfigurationPlain data holder pairing an IRefreshableSecretReaderFactory with the fully injected IConfigurationRoot.
Support/ApiExceptionFilterAttribute.csApiExceptionFilterAttributeMVC ExceptionFilterAttribute. Maps AzureSearchException → HTTP 503 and InvalidSearchRequestException → HTTP 400. All other exceptions propagate normally.

Dependencies

NuGet Package References

PackageRole
Microsoft.ApplicationInsights.AspNetCoreApplication Insights telemetry integration
Microsoft.AspNetCore.HttpLifted transitive dependency — pinned for Component Governance compliance
System.Drawing.CommonLifted transitive dependency — pinned for Component Governance compliance

Framework Reference

ReferenceNotes
Microsoft.AspNetCore.AppFull ASP.NET Core framework reference; brings in MVC, routing, CORS, HSTS, and hosting APIs

Internal Project References

ProjectPurpose
NuGet.Services.AzureSearchProvides AzureSearchException, InvalidSearchRequestException, and ErrorResponse consumed by the exception filter

Startup Flow

Program.Main
  └─ HostBuilderHelper.CreateHostBuilder(args)
       ├─ Removes all EnvironmentVariablesConfigurationSource entries
       ├─ Adds APPSETTING_-prefixed environment variable source
       └─ Registers AutofacServiceProviderFactory
            └─ Startup.ConfigureServices(services)
                 ├─ StartupHelper.GetSecretInjectedConfiguration(config)
                 │    ├─ Pre-warms Key Vault secret cache (.Wait())
                 │    └─ Locks out uncached reads (BlockUncachedReads = true)
                 └─ Registers ApiExceptionFilterAttribute on MVC pipeline
                      └─ Startup.Configure(app, env)
                           └─ StartupHelper.Configure(app, env, corsPolicy)
                                ├─ UseRouting, UseCors, UseHsts
                                ├─ Adds X-Content-Type-Options: nosniff header
                                └─ MapControllers

Notable Patterns and Implementation Details

Environment variable filtering is intentional. HostBuilderHelper removes all default EnvironmentVariablesConfigurationSource registrations and replaces them with a single source scoped to the APPSETTING_ prefix. This matches the Azure App Service configuration convention and avoids accidentally ingesting hundreds of system-level variables.
Synchronous .Wait() in GetSecretInjectedConfiguration. During application startup, Key Vault secrets are pre-warmed into the refresh cache by calling .Wait(). This blocks the startup thread. The code acknowledges this is “not great” but necessary because the DI container is not yet active. After startup, BlockUncachedReads = true is set so request threads must only hit the already-warm cache.
CORS is caller-controlled. StartupHelper.Configure accepts an optional Action<CorsPolicyBuilder> parameter. If null, no CORS middleware is added at all. The consuming host passes an open-origin policy — this keeps the CORS policy out of the shared library.
GetOperationName<T> standardises Application Insights naming. Rather than letting ASP.NET Core generate variable operation name strings, consuming startup code pre-registers known operation names via KnownOperationNameEnricher. This makes dashboards and alerts more predictable.
Target framework mismatch. This library targets net6.0 while its primary consumer NuGet.Services.SearchService.Core targets net8.0. The library runs fine under the .NET forward-compatibility model, but has not been updated to match the host’s TFM.