17

LINQPad で Selfhosted WebAPI を使用しようとすると、クラスのコントローラーが存在しないという同じエラーが発生し続けました。

WebAPI (コントローラー/クラス) 用に個別のアセンブリを作成し、クエリでそれらを参照する必要がありますか?

これが私が使用しているコードです

#region namespaces
using AttributeRouting;
using AttributeRouting.Web.Http;
using AttributeRouting.Web.Http.SelfHost;
using System.Web.Http.SelfHost;
using System.Web.Http.Routing;
using System.Web.Http;
#endregion

public void Main()
{

    var config = new HttpSelfHostConfiguration("http://192.168.0.196:8181/");
    config.Routes.MapHttpAttributeRoutes(cfg =>
    {
        cfg.AddRoutesFromAssembly(Assembly.GetExecutingAssembly());
    });
    config.Routes.Cast<HttpRoute>().Dump();

    AllObjects.Add(new UserQuery.PlayerObject { Type = 1, BaseAddress = "Hej" });

    config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
    using(HttpSelfHostServer server = new HttpSelfHostServer(config))
    {
        server.OpenAsync().Wait();
        Console.WriteLine("Server open, press enter to quit");
        Console.ReadLine();
        server.CloseAsync();
    }

}

public static List<PlayerObject> AllObjects = new List<PlayerObject>();

public class PlayerObject
{
    public uint Type { get; set; }
    public string BaseAddress { get; set; }
}

[RoutePrefix("players")]
public class PlayerObjectController : System.Web.Http.ApiController
{
    [GET("allPlayers")]
    public IEnumerable<PlayerObject> GetAllPlayerObjects()
    {
        var players = (from p in AllObjects
                    where p.Type == 1
                    select p);
        return players.ToList();
    }
}

このコードは、VS2012 の別のコンソール プロジェクトで正常に動作します。

「通常の」WebAPIルーティングが機能しなかったときに、NuGET経由でAttributeRoutingを使い始めました。

ブラウザに表示されたエラーは次のとおりです。No HTTP resource was found that matches the request URI 'http://192.168.0.196:8181/players/allPlayers'.

追加エラー:No type was found that matches the controller named 'PlayerObject'

4

1 に答える 1

18

デフォルトでは、Web API は public でないコントローラーを無視し、LinqPad クラスはpublic にネストされています。scriptcsで同様の問題がありました。

カスタム コントローラー リゾルバーを追加する必要があります。これにより、その制限が回避され、実行中のアセンブリからコントローラーの種類を手動で検出できるようになります。

これは実際には既に修正されています (現在、Web API コントローラーはパブリックではなく可視である必要があるだけです) が、それは 9 月に発生し、セルフ ホストの最新の安定バージョンは 8 月のものです。

したがって、これを追加します。

public class ControllerResolver: DefaultHttpControllerTypeResolver {

    public override ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver) {
        var types = Assembly.GetExecutingAssembly().GetExportedTypes();
        return types.Where(x => typeof(System.Web.Http.Controllers.IHttpController).IsAssignableFrom(x)).ToList();
    }

}

そして、構成に対して登録すれば完了です。

var conf = new HttpSelfHostConfiguration(new Uri(address));
conf.Services.Replace(typeof(IHttpControllerTypeResolver), new ControllerResolver());

これは完全に機能する例です。LinqPad に対してテストしたところです。管理者として LinqPad を実行する必要があることに注意してください。そうしないと、ポートでリッスンできません。

public class TestController: System.Web.Http.ApiController {
    public string Get() {
        return "Hello world!";
    }
}

public class ControllerResolver: DefaultHttpControllerTypeResolver {
    public override ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver) {
        var types = Assembly.GetExecutingAssembly().GetExportedTypes();
        return types.Where(x => typeof(System.Web.Http.Controllers.IHttpController).IsAssignableFrom(x)).ToList();
    }
}

async Task Main() {
    var address = "http://localhost:8080";
    var conf = new HttpSelfHostConfiguration(new Uri(address));
    conf.Services.Replace(typeof(IHttpControllerTypeResolver), new ControllerResolver());

    conf.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );

    var server = new HttpSelfHostServer(conf);
    await server.OpenAsync();

    // keep the query in the 'Running' state
    Util.KeepRunning();
    Util.Cleanup += async delegate {
        // shut down the server when the query's execution is canceled
        // (for example, the Cancel button is clicked)
        await server.CloseAsync();
    };
}
于 2013-04-04T23:55:50.773 に答える