dotnet / dotnet/aspnetcore

Cannot run an action filter before ModelStateInvalidFilter

Open
#50,432 2 comments 0 reactions 0 assignees View on GitHub
area-mvc
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 5h
Merged PRs (30d)
276

Description

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe the bug

I'm trying to add an action filter that logs validation errors (because `ModelStateInvalidFilter` only logs the fact that there was a validation error, but not the error details).

I added my filter globally in `MvcOptions.Filters`, but my filter is never called. I assumed this was because it was short-circuited by `ModelStateInvalidFilter`, which has an `Order` of `-2000`. So I implemented `IOrderedFilter` in my filter, with an `Order` of -3000, so that it would run before `ModelStateInvalidFilter`. However, my filter is still not called; in fact, even the `Order` property is never called either.

It looks like a bug to me. Why can't I add a filter that runs before `ModelStateInvalidFilter`?

### Expected Behavior

An action filter with an `IOrderedFilter.Order` lower than `ModelStateInvalidFilter` should run before it.

### Steps To Reproduce

Create the following filter:

```csharp
public class ModelStateErrorFilter : IActionFilter, IOrderedFilter
{
private readonly ILogger _logger;

public ModelStateErrorFilter(ILogger logger)
{
_logger = logger;
}

public void OnActionExecuting(ActionExecutingContext context)
{
if (context.ModelState.IsValid)
return;

var errors = context.ModelState.ToDictionary(
kvp => kvp.Key,
kvp => string.Join(";", kvp.Value?.Errors.Select(e => e.ErrorMessage) ?? Enumerable.Empty()));
_logger.LogInformation("The ModelState for this request has errors: {Errors}", errors);
}

public void OnActionExecuted(ActionExecutedContext context)
{
}

// To execute before ModelStateInvalidFilter, otherwise it would be short-circuited
public int Order => -3000;
}
```

Add it as a global filter:

```csharp
builder.Services.AddControllers(options =>
{
options.Filters.Add();
});
```

Run the app, and send a request with model state errors

### Exceptions (if any)

_No response_

### .NET Version

7.0.400

### Anything else?

A possible workaround is to disable `ModelStateInvalidFilter` with this:
```csharp
.ConfigureApiBehaviorOptions(options => options.SuppressModelStateInvalidFilter = true)
```
and call `ApiBehaviorOptions.InvalidModelStateResponseFactory` myself to set the result.

It's not ideal. I'd rather not reimplement `ModelStateInvalidFilter` myself, and it shouldn't be necessary anyway.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.