# Feature Request: Add Fallback Policy Resolver to CORS Options
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Is your feature request related to a problem? Please describe the problem.
_No response_
### Describe the solution you'd like
# Feature Request: Add Fallback Policy Resolver to CORS Options
## Is your feature request related to a problem?
Currently, ASP.NET Core CORS middleware only supports predefined policies registered via `CorsOptions`. When a policy name is not found in the policy map, the middleware returns `null` and the request is not processed with CORS headers.
This limitation makes it difficult to implement:
- **Dynamic policy loading** from databases or external configuration sources
- **Multi-tenant applications** where each tenant has different CORS policies
- **Route-based policy resolution** where policies are determined by request path patterns
- **Fallback mechanisms** when named policies are not found
## Describe the solution you'd like
Add a `PolicyResolver` callback property to `CorsOptions` that allows custom policy resolution logic when a named policy is not found in the predefined policy map.
### Proposed API
```csharp
public class CorsOptions
{
private readonly IDictionary _policyMap = new Dictionary();
// Existing properties...
public string DefaultPolicyName { get; set; } = "__DefaultCorsPolicy";
///
/// Gets or sets a callback that resolves CORS policies when they are not found in the policy map.
/// This enables dynamic policy loading, multi-tenant scenarios, and custom fallback logic.
///
///
/// The callback receives the HttpContext and policy name, allowing context-aware policy resolution.
/// Return null if no policy should be applied.
///
public Func PolicyResolver { get; set; } = (_, _) => null;
// Existing methods...
}
```
### Implementation in CorsPolicyProvider
```csharp
public class CorsPolicyProvider : ICorsPolicyProvider
{
private readonly CorsOptions _options;
public CorsPolicyProvider(IOptions options)
{
_options = options.Value;
}
public Task GetPolicyAsync(HttpContext context, string? policyName)
{
var name = policyName ?? _options.DefaultPolicyName;
// Try to get from predefined policies first
if (_options.GetPolicy(name) is CorsPolicy policy)
{
return Task.FromResult(policy);
}
// Fallback to custom resolver
var resolvedPolicy = _options.PolicyResolver?.Invoke(context, policyName);
return Task.FromResult(resolvedPolicy);
}
}
```
## Use Cases
### 1. Multi-Tenant Application
```csharp
services.AddCors(options =>
{
options.PolicyResolver = (context, policyName) =>
{
var tenantId = context.Request.Headers["X-Tenant-ID"].FirstOrDefault();
if (string.IsNullOrEmpty(tenantId))
return null;
// Load tenant-specific policy from database
var tenantPolicy = _tenantPolicyService.GetPolicyForTenant(tenantId);
return tenantPolicy;
};
});
```
### 2. Dynamic Policy Loading from Database
```csharp
services.AddCors(options =>
{
options.PolicyResolver = (context, policyName) =>
{
if (string.IsNullOrEmpty(policyName))
return null;
// Load policy from database or cache
var policy = _policyRepository.GetByName(policyName);
return policy;
};
});
```
### 3. Route-Based Policy Resolution
```csharp
services.AddCors(options =>
{
options.PolicyResolver = (context, policyName) =>
{
var path = context.Request.Path.Value;
if (path?.StartsWith("/api/public") == true)
{
return new CorsPolicyBuilder()
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.Build();
}
if (path?.StartsWith("/api/internal") == true)
{
return new CorsPolicyBuilder()
.WithOrigins("https://internal.company.com")
.AllowAnyMethod()
.AllowAnyHeader()
.Build();
}
return null;
};
});
```
## Benefits
1. **Backward Compatible**: Existing code continues to work without changes
2. **Flexible**: Supports various dynamic policy resolution scenarios
3. **Performance**: Only invoked when predefined policies are not found
4. **Context-Aware**: Access to `HttpContext` enables request-based decisions
5. **Simple API**: Single callback property, easy to understand and use
## Alternatives Considered
### Alternative 1: Custom ICorsPolicyProvider
Users can already implement custom `ICorsPolicyProvider`, but this requires:
- More boilerplate code
- Replacing the entire provider implementation
- Losing the built-in policy map functionality
### Alternative 2: Middleware-Level Customization
Implementing custom middleware, but this:
- Duplicates CORS logic
- Harder to maintain
- Loses integration with `[EnableCors]` attribute
## Additional Context
This feature is inspired by similar extensibility patterns in ASP.NET Core:
- `AuthorizationOptions.FallbackPolicy`
- `RouteOptions.ConstraintMap` with custom constraint resolvers
- `JsonOptions` with custom converters
The proposed API follows the same design principles of providing extensibility points while maintaining backward compatibility.
---
**Would you be willing to contribute this feature?** Yes, I can submit a PR if this proposal is accepted.
### Additional context
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.