WCF WebApi的自托管不接受PUT动词

时间:2011-06-18 18:47:44

标签: wcf wcf-web-api

我使用使用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。

编辑:我似乎在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);
}

1 个答案:

答案 0 :(得分:4)

当我更改方法签名以接受HttpRequestMessage请求而不是T本身时,做PUT或POST对我有用。