Промежуточное ПО работает на уровне ASP.NET Core и может реагировать на каждый запрос, поступающий в приложение.
С другой стороны, фильтры MVC запускаются только для запросов, поступающих в MVC.
Так, например, если бы я хотел обеспечить выполнение всех запросов через HTTPS, мне пришлось бы использовать для этого промежуточное ПО. Если бы я сделал фильтр MVC, который делал бы это, пользователи все равно могли бы запрашивать, например, статические файлы по HTTP.
Но с другой стороны, что-то, что регистрирует длительность запросов в контроллерах MVC, может абсолютно быть фильтром действий.