14

Web APIルートalaのglobal.asax.cs内にカスタムルートハンドラー(IRouteHandlerから派生)を正常に登録できます。

        routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "{client}/api/1.0/{controller}/{action}/{id}",
            defaults: new{id = UrlParameter.Optional}
        ).RouteHandler = new SingleActionAPIRouteHandler();

ただし、統合テスト用のAPIのメモリ内ホストをセットアップしようとすると、これを行う方法が見つからないようです。HttpConfiguration.Routes.MapRouteを呼び出すと、返されたIHttpRouteにハンドラーを設定できません。

これを別の方法で行う必要がありますか(たとえば、カスタムHttpControllerSelectorを使用して)?どちらの場合も同じようにやりたいのは明らかです。

ありがとう、マット

編集:

したがって、私がやったことは、基本的に以下のアドバイスに従うことでしたが、次のようにHttpControllerDispatcherクラスをオーバーライドするだけでした。

public class CustomHttpControllerDispatcher : HttpControllerDispatcher
{
    public CustomHttpControllerDispatcher(HttpConfiguration configuration) : base(configuration)
    {
    }
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // My stuff here

        return base.SendAsync(request, cancellationToken);
    }
}
4

1 に答える 1

13

あなたは非常に正しいです。セルフ ホストは IHttpRoute を返し、HttpMessageHandler をパラメーターとして受け取ります。ルート ハンドラを特定する組み込みの方法はないようです。

更新:もう少し明確にするために

ほとんどの場合、HttpControllerSelector を使用してカスタムのものを実装する必要があります... 例を次に示します。http://netmvc.blogspot.co.uk/

以下は、何らかの理由で HttpControllerSelector が要件を満たしていない場合のちょっとした実験です...

しかし、ご覧のとおり、 にMapHttpRouteはオーバーロードがあるHttpMessageHandlerため、これを試すことができます...ハンドラーが NULL の場合、デフォルトで IHttpController になりますが、独自に実装し、これを使用して正しいコントローラーに転送することができます... MVC フレームワークは[HttpControllerDispatcher] hereを使用しているように見えるので、いくつかのコードを借りて、独自のコントローラー/ルート選択コードをここにも配置できます。ルートとセレクターにアクセスでき、自分で交換できます。

この CustomHttpControllerDispatcher コードはデモ専用です...行を探します

//コントローラーを選択するためにここで何かカスタムを行います

そして、おそらくそれで遊んでください...

ルート例:

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: null,
            handler: new CustomHttpControllerDispatcher(config)
        );

CustomHttpControllerDispatcher の例:

public class CustomHttpControllerDispatcher : HttpMessageHandler
{
        private IHttpControllerSelector _controllerSelector;
        private readonly HttpConfiguration _configuration;

        public CustomHttpControllerDispatcher(HttpConfiguration configuration)
        {
            _configuration = configuration;
        }

        public HttpConfiguration Configuration
        {
            get { return _configuration; }
        }

        private IHttpControllerSelector ControllerSelector
        {
            get
            {
                if (_controllerSelector == null)
                {
                    _controllerSelector = _configuration.Services.GetHttpControllerSelector();
                }
                return _controllerSelector;
            }
        }

        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
                return SendAsyncInternal(request, cancellationToken);
        }

        private Task<HttpResponseMessage> SendAsyncInternal(HttpRequestMessage request, CancellationToken cancellationToken)
        {

            IHttpRouteData routeData = request.GetRouteData();
            Contract.Assert(routeData != null);

            //DO SOMETHING CUSTOM HERE TO PICK YOUR CONTROLLER
            HttpControllerDescriptor httpControllerDescriptor = ControllerSelector.SelectController(request);
            IHttpController httpController = httpControllerDescriptor.CreateController(request);

            // Create context
            HttpControllerContext controllerContext = new HttpControllerContext(_configuration, routeData, request);
            controllerContext.Controller = httpController;
            controllerContext.ControllerDescriptor = httpControllerDescriptor;

            return httpController.ExecuteAsync(controllerContext, cancellationToken);
        }
}
于 2012-09-13T13:25:08.067 に答える