52

私は最新のものを使用していweb apiます。

3 つの異なるフィルター属性でいくつかのコントローラーに注釈を付けます。

1 [Authorize]
2 [RessourceOwnerAttribute derived from AuthorizationFilterAttribute]
3 [InvalidModelStateAttribute derived from ActionFilterAttribute]

フィルターが上から下に宣言された順序で実行されるかどうかはわかりません。

で実行順序を定義するにはどうすればよいweb api 2.1ですか?

https://aspnetwebstack.codeplex.com/workitem/1065#

http://aspnet.uservoice.com/forums/147201-asp-net-web-api/suggestions/3346720-execution-order-of-mvc4-webapi-action-filters

まだ自分で修正する必要がありますか??

4

3 に答える 3

77

ここで注意すべき点:

  1. フィルターは、アクションに対して次の順序で実行されます。グローバルに定義されたフィルター -> コントローラー固有のフィルター -> アクション固有のフィルター。
  2. 承認フィルター -> アクション フィルター -> 例外フィルター
  3. 現在、あなたが言及しているように見える問題は、同じ種類の複数のフィルターを持つことに関連しています (例: ActionFilterAttributeコントローラーまたはアクションで複数の装飾が施されています。これは、リフレクションに基づく順序を保証しない場合です)。この場合、 のカスタム実装を使用して Web API でそれを行う方法があります System.Web.Http.Filters.IFilterProvider。私は以下を試し、それを確認するためにいくつかのテストを行いました。それはうまくいくようです。試してみて、期待どおりに機能するかどうかを確認できます。

    // Start clean by replacing with filter provider for global configuration.
    // For these globally added filters we need not do any ordering as filters are 
    // executed in the order they are added to the filter collection
    config.Services.Replace(typeof(IFilterProvider), new System.Web.Http.Filters.ConfigurationFilterProvider());
    
    // Custom action filter provider which does ordering
    config.Services.Add(typeof(IFilterProvider), new OrderedFilterProvider());
    

    public class OrderedFilterProvider : IFilterProvider
    {
        public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
        {
            // controller-specific
            IEnumerable<FilterInfo> controllerSpecificFilters = OrderFilters(actionDescriptor.ControllerDescriptor.GetFilters(), FilterScope.Controller);
    
            // action-specific
            IEnumerable<FilterInfo> actionSpecificFilters = OrderFilters(actionDescriptor.GetFilters(), FilterScope.Action);
    
            return controllerSpecificFilters.Concat(actionSpecificFilters);
        }
    
        private IEnumerable<FilterInfo> OrderFilters(IEnumerable<IFilter> filters, FilterScope scope)
        {
            return filters.OfType<IOrderedFilter>()
                            .OrderBy(filter => filter.Order)
                            .Select(instance => new FilterInfo(instance, scope));
        }
    }
    

    //NOTE: Here I am creating base attributes which you would need to inherit from.
    public interface IOrderedFilter : IFilter
    {
        int Order { get; set; }
    }
    
    public class ActionFilterWithOrderAttribute : ActionFilterAttribute, IOrderedFilter
    {
        public int Order { get; set; }
    }
    
    public class AuthorizationFilterWithOrderAttribute : AuthorizationFilterAttribute, IOrderedFilter
    {
        public int Order { get; set; }
    }
    
    public class ExceptionFilterWithOrderAttribute : ExceptionFilterAttribute, IOrderedFilter
    {
        public int Order { get; set; }
    }
    
于 2014-02-07T14:59:32.810 に答える