2

PUT 動詞を使用するWCF WebAPIを使用して、HTTP 駆動型 API をまとめました。IIS Express でホストされている MVC3 プロジェクト内でホストされている場合、すべてが設計どおりに機能します。

ただし、単体テストを行うときは、自分のリソースに対してだけでなく、トランスポートの側面をテストしたい場合があります。単体テストが 405 - MethodNotAllowed で失敗します。ここでも、IIS でホストされているのとまったく同じサービスが機能します (構成ファイルで PUT 動詞と DELETE 動詞を有効にしました)。

テストで使用したように、これらの動詞も受け入れるように「自己ホスト型」サービスを取得するにはどうすればよいですか?

ほぼ同じ「get」テストが機能するため、次の概念に問題があるとは思いません..うまくいけば...

[Test]
public void PutNewMachine()
{
    // Create new record to add
    var machine = new Machine
                      {
                          ID = 1,
                          Name = "One",
                          Description = "Machine #1",
                          Location = 1
                      };

    using (var client = new HttpClient())
    {
        using (var request = new HttpRequestMessage(
                                         HttpMethod.Put, 
                                         HOST + "/1"))
        {
            request.Content = new ObjectContent<Machine>(machine);

            using (var response = client.Send(request))
            {
                Assert.AreEqual(
                    HttpStatusCode.Created,
                    response.StatusCode,
                    "New record put should have been acknowledged "
                                    + "with a status code of 'Created'");
            }
        }
    }
}

テストのセットアップでは、次の Autofac コードを使用してエンドポイントを準備しています (これも「Get」で機能します)。

var builder = new ContainerBuilder();
builder
    .Register(c => new FakeDatabase())
    .As<IDatabase>()
    .SingleInstance();
builder
    .Register(c => new GenericRepository<Machine>(c.Resolve<IDatabase>()))
    .As<IResourceRepository<Machine>>();
builder
    .Register(c => new MachineService(c.Resolve<IResourceRepository<Machine>>()))
    .As<MachineService>();
Container = builder.Build();
Scope = Container.BeginLifetimeScope();

host = new HttpServiceHost(typeof(MachineService), HOST);
host.AddDependencyInjectionBehavior<MachineService>(Container);
host.Open();

私のサービスは、次のインターフェースで定義されています。

[ServiceContract]
public interface IResourceService<in TKey, TResource>
{
    [WebGet(UriTemplate = "{key}")]
    TResource Get(TKey key);

    [WebInvoke(Method = "PUT", UriTemplate = "{key}")]
    TResource Put(TKey key, TResource resource);

    [WebInvoke(Method = "POST")]
    TResource Post(TResource resource);

    [WebInvoke(Method = "DELETE", UriTemplate = "{key}")]
    void Delete(TKey key);
}

したがって、たとえば、MachineService がある場合、インターフェイスを実装します (両方ともclass MachineService : IResourceService<string, Machine>試用... : IResourceService<int, Machine>済み - Get = OK、Put = Nothing.

EDIT : InternalServerError と MethodNotAllowed エラーの間でバウンスしているようです - セルフホスティングを使用している場合のみ。ユーザーとして、ポートを開く権限があることを確認しました (Win7 + 非管理者) が、その結果とポートの選択は、Get に対して予測可能な機能のようです。「投稿」にも同様の問題があるようです!:-(

EDIT2 : インターフェイスが変更され、動作するようになりました!

[ServiceContract]
public interface IResourceService<in TKey, TResource>
{
    [WebGet(UriTemplate = "{key}")]
    TResource Get(TKey key);

    [WebInvoke(Method = "PUT", UriTemplate = "{key}")]
    TResource Put(HttpRequestMessage<TResource> resourceRequest, TKey key);

    [WebInvoke(Method = "POST", UriTemplate = "{key}")]
    TResource Post(HttpRequestMessage<TResource> resourceRequest, TKey key);

    [WebInvoke(Method = "DELETE", UriTemplate = "{key}")]
    void Delete(TKey key);
}
4

1 に答える 1

4

T 自体の代わりに HttpRequestMessage リクエストを受け入れるようにメソッド シグネチャを変更すると、PUT または POST を実行するとうまくいきます。

于 2011-06-19T06:58:54.657 に答える