2013-10-22 4 views
6

Web API 2用のナゲットパッケージをRC1から5.0.0にアップグレードしました。以前はアクセス可能だったHttpRouteBuilderが内部的に作成されたことがわかりました。それに伴い、HttpRouteBuilderを引数として持つHttpConfiguration.MapHttpAttributeRoutesのオーバーロードはなくなりました。どうして?HttpRouteBuilder - どこに行きましたか、なぜですか?

私はそれを使用していた、そしてそれは私のプロジェクトの主要な問題を解決します。代わりに私は何を使用しますか?

背景: 私は私がすべてのURIに結合余分なパスセグメントを注入することができるようにHttpRouteBuilderから継承したクラスを実装したWeb API 2のルーティング属性使用するサーバーを書いています。デフォルトルートビルダーは// MYSERVER /ユーザー/を更新するための経路を作成することになった場合たとえば、私のルートビルダーは// MYSERVER/{インスタンス} /ユーザー/更新にそのルートを変更します。私はこれを自動的に実行して、何百ものHttpGet、HttpPostなどの属性ごとにそれを固執する必要はありませんでした。それでは、この大きな変化にどのように対応していますか?

+0

あなたは一人ひとりのアクションに指定最小限に抑えるために、 'RoutePrefix'または'コントローラlevel'ルート属性を使用してもらえますか? –

+0

はい、私の大きな問題はサーバーでサードパーティのコントローラを使用できるということです。ルートに必要なセグメントを追加するためにサーバーに任せたくありません。これらのセグメントは、指定したかどうかにかかわらず追加する必要があります。私のルートビルダーは、まだ指定されていない場合にのみ追加するほどスマートでした。 –

+0

Web API(5.2)の次のリリースでは、あなたのシナリオを達成するためのフックを提供しています...実際には、新しいNightlyビルドの使用も試してみることができます。インターフェイスは 'IDirectRouteProvider'と呼ばれます –

答えて

1

私がやっていたものは、インターナショナルが壊したものです。 change set made on August 21st 2013

this issueを修正するために、このAPIの変更を行いました。その問題によれば、機能が削除された唯一の理由は、Web APIをMVCのAPIに近づけることでした。私の意見では特に正当な理由ではありません。私はApiControllerActionSelectorから派生したカスタムIHttpActionSelectorを実装し、私の問題を解決するために

。私はそれが本当に単純なことのためにあまりにも多くのコードですので、私の最終的な解決策にはならないことを願っています。このアプローチはあなたの問題にも有効です。

私のプロジェクトでは、どのルートがどのアセンブリに含まれているかに従って、各ルートを変更する必要があります。簡略化されたコードでは、すべてのルートの先頭に/Apiが付いています(コントローラのRoutePrefixAttributeがある場合)。

実際IHttpActionSelector

public class PrefixWithApiControllerActionSelector : WrappingApiControllerActionSelector { 
    protected override HttpActionDescriptor WrapHttpActionDescriptor(HttpActionDescriptor actionDescriptor) { 
     if (actionDescriptor is ReflectedHttpActionDescriptor) 
      return new PrefixWithApiReflectedHttpActionDescriptor((ReflectedHttpActionDescriptor)actionDescriptor); 
     return actionDescriptor; 
    } 
} 

public abstract class WrappingApiControllerActionSelector : ApiControllerActionSelector { 
    protected abstract HttpActionDescriptor WrapHttpActionDescriptor(HttpActionDescriptor actionDescriptor); 

    public override ILookup<string, HttpActionDescriptor> GetActionMapping(HttpControllerDescriptor controllerDescriptor) { 
     return base.GetActionMapping(controllerDescriptor).SelectMany(grouping => { 
      return grouping.Select(actionDescriptor => new KeyValuePair<string, HttpActionDescriptor>(grouping.Key, WrapHttpActionDescriptor(actionDescriptor))); 
     }).ToLookup(_ => _.Key, _ => _.Value); 
    } 
} 

ルート変更部分:

public class PrefixWithApiHttpRouteInfoProvider : WrappedHttpRouteInfoProvider { 
    public PrefixWithApiHttpRouteInfoProvider(IHttpRouteInfoProvider infoProvider, HttpControllerDescriptor controllerDescriptor) : base(infoProvider, controllerDescriptor) { } 

    public override string Template { 
     get { 
      var parts = new List<string>(); 
      parts.Add("Api"); 

      var prefix = ControllerDescriptor.GetCustomAttributes<RoutePrefixAttribute>().FirstOrDefault(); 
      if (prefix != null && !string.IsNullOrEmpty(prefix.Prefix)) { 
       parts.Add(prefix.Prefix); 
      } 

      if (!string.IsNullOrEmpty(InfoProvider.Template)) { 
       parts.Add(InfoProvider.Template); 
      } 

      var route = "~/" + string.Join("/", parts); 
      if (route.Length > 2 && route.EndsWith("/", StringComparison.Ordinal)) { 
       route = route.Substring(0, route.Length - 1); 
      } 
      return route; 
     } 
    } 
} 

public abstract class WrappedHttpRouteInfoProvider : IHttpRouteInfoProvider { 
    private readonly IHttpRouteInfoProvider _infoProvider; 
    private readonly HttpControllerDescriptor _controllerDescriptor; 

    protected WrappedHttpRouteInfoProvider(IHttpRouteInfoProvider infoProvider, HttpControllerDescriptor controllerDescriptor) { 
     _infoProvider = infoProvider; 
     _controllerDescriptor = controllerDescriptor; 
    } 

    public virtual string Name { 
     get { return InfoProvider.Name; } 
    } 

    public virtual string Template { 
     get { return _infoProvider.Template; } 
    } 

    public virtual int Order { 
     get { return InfoProvider.Order; } 
    } 

    protected HttpControllerDescriptor ControllerDescriptor { 
     get { return _controllerDescriptor; } 
    } 

    protected IHttpRouteInfoProvider InfoProvider { 
     get { return _infoProvider; } 
    } 
} 

のりを:

public class PrefixWithApiReflectedHttpActionDescriptor : WrappedReflectedHttpActionDescriptor { 
    public PrefixWithApiReflectedHttpActionDescriptor(ReflectedHttpActionDescriptor descriptor) : base(descriptor) {} 

    public override Collection<T> GetCustomAttributes<T>(bool inherit) { 
     if (typeof(T) == typeof(IHttpRouteInfoProvider)) { 
      var attributes = Descriptor.GetCustomAttributes<T>(inherit).Cast<IHttpRouteInfoProvider>().Select(_ => new PrefixWithApiHttpRouteInfoProvider(_, Descriptor.ControllerDescriptor)); 
      return new Collection<T>(attributes.Cast<T>().ToList()); 
     } 
     return Descriptor.GetCustomAttributes<T>(inherit); 
    } 

    public override Collection<T> GetCustomAttributes<T>() { 
     if (typeof(T) == typeof(IHttpRouteInfoProvider)) { 
      var attributes = Descriptor.GetCustomAttributes<T>().Cast<IHttpRouteInfoProvider>().Select(_ => new PrefixWithApiHttpRouteInfoProvider(_, Descriptor.ControllerDescriptor)); 
      return new Collection<T>(attributes.Cast<T>().ToList()); 
     } 
     return Descriptor.GetCustomAttributes<T>(); 
    } 
} 

public abstract class WrappedReflectedHttpActionDescriptor : ReflectedHttpActionDescriptor { 
    private readonly ReflectedHttpActionDescriptor _descriptor; 

    protected WrappedReflectedHttpActionDescriptor(ReflectedHttpActionDescriptor descriptor) : base(descriptor.ControllerDescriptor, descriptor.MethodInfo) { 
     _descriptor = descriptor; 
    } 

    public override HttpActionBinding ActionBinding { 
     get { return Descriptor.ActionBinding; } 
     set { Descriptor.ActionBinding = value; } 
    } 

    public override Collection<T> GetCustomAttributes<T>(bool inherit) { 
     return Descriptor.GetCustomAttributes<T>(inherit); 
    } 

    public override Collection<T> GetCustomAttributes<T>() { 
     return Descriptor.GetCustomAttributes<T>(); 
    } 

    public override Collection<System.Web.Http.Filters.FilterInfo> GetFilterPipeline() { 
     return Descriptor.GetFilterPipeline(); 
    } 

    public override Collection<System.Web.Http.Filters.IFilter> GetFilters() { 
     return Descriptor.GetFilters(); 
    } 

    public override System.Collections.Concurrent.ConcurrentDictionary<object, object> Properties { 
     get { return Descriptor.Properties; } 
    } 

    public override IActionResultConverter ResultConverter { 
     get { return Descriptor.ResultConverter; } 
    } 

    public override Collection<HttpMethod> SupportedHttpMethods { 
     get { return Descriptor.SupportedHttpMethods; } 
    } 

    public override Collection<HttpParameterDescriptor> GetParameters() { 
     return Descriptor.GetParameters(); 
    } 

    public override Task<object> ExecuteAsync(HttpControllerContext controllerContext, IDictionary<string, object> arguments, CancellationToken cancellationToken) { 
     return Descriptor.ExecuteAsync(controllerContext, arguments, cancellationToken); 
    } 

    public override string ActionName { 
     get { return Descriptor.ActionName; } 
    } 

    public override Type ReturnType { 
     get { return Descriptor.ReturnType; } 
    } 

    protected ReflectedHttpActionDescriptor Descriptor { 
     get { return _descriptor; } 
    } 
} 

だけPrefixWithApiControllerActionSelectorIHttpActionSelectorサービスを置き換え、この機能を使用するには設定で。

あなたは、物事をやってあなたのソリューションを投稿してくださいのクリーンな方法を見つけた場合は!

関連する問題