【发布时间】:2011-04-07 04:00:33
【问题描述】:
我在这里查看了几乎所有关于 SO 的 WCF Rest PUT/POST 问题,但仍然无法确定为什么我无法 PUT 或 POST 到我的 Web 服务,但能够通过 GET 调用测试 GetTime 方法。
此特定服务将自定义凭据信息(用户名、密码和其他一些信息)交换为令牌。此令牌信息被加密并添加到对其他 Web 服务的后续请求的标头中,这样用户名/密码就不必到处传递。
所有 Web 服务调用仍被视为无状态,但需要此身份验证标头信息而不是用户名/密码才能访问安全服务操作。
合同
[ServiceContract(Namespace = "")]
public interface IUserService
{
[WebInvoke(Method = "PUT", UriTemplate = "users/{username}/session")]
[WebHelp(Comment = "Creates a new session for the specified username")]
[OperationContract]
AuthToken PutSession(string username, CustomCredential credential);
...
[WebInvoke(Method = "GET", UriTemplate = "time")]
[WebHelp(Comment = "Test method; returns the time")]
[RequireAuthToken]
[OperationContract]
DateTime GetTime();
}
服务实现
public class UserService : IUserService
{
#region UserService Members
public AuthToken PutSession(string username, CustomCredential credential)
{
// ...
}
public DateTime GetTime()
{
return DateTime.Now;
}
}
测试代码
[Fact]
public void When_Authenticated_And_Getting_Time_Expect_200_Status()
{
// arrange
using (var client = Get_HttpClient_With_AuthHeaders()) {
// act
var result = client.Get("time");
// assert
Assert.Equal(HttpStatusCode.OK, result.StatusCode);
}
}
前面提到的 GetTime 有效(只是我添加的一个测试方法)。
[Fact]
public void When_PuttingSession_Expect_AuthToken_Is_Returned()
{
// arrange
using (var client = Get_HttpClient_With_No_Auth_Headers()) {
var cred = new CustomCredential("test", "password", 1);
var content = HttpContentExtensions.CreateDataContract<CustomCredential>(cred);
// act
HttpResponseMessage response = client.Put("users/test/session", content);
// assert
response.EnsureStatusIsSuccessful();
Assert.Equal(HttpStatusCode.Created, response.StatusCode);
var authToken = response.Content.ReadAsDataContract<AuthToken>();
Assert.NotNull(authToken);
}
}
上面的 put 返回一个 MethodNotAllowed (405)。
就像另一个测试一样,我向服务添加了一个 Mex 端点,创建了一个新的控制台应用程序并向该服务添加了一个“服务引用”。使用生成的客户端代理代码,我可以做类似的事情......
IUserServiceClient client = new IUserServiceClient();
CustomCredential cred = ...
AuthToken token = client.PutSession("test_username", cred);
这表明...
- Web 服务正确托管在 IIS 中
- 我可以使用 SOAP 客户端代理生成的代码来使用服务
- 我可以通过更友好的 HttpClient / rest 工具包使用 GET 请求
- 我已经在浏览器中测试了这个 get,它可以工作
- 由于某些原因,put 和其他相关方法(发布、删除等)无法通过 rest 工具包工作
不知道是什么原因造成的。
编辑
我还注意到 IIS 必须在托管服务的网站的根目录中创建了这个 web.config,这似乎允许主要的 HTTP 动词。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<security>
<requestFiltering>
<verbs>
<add verb="PUT" allowed="true" />
<add verb="GET" allowed="true" />
<add verb="POST" allowed="true" />
<add verb="DELETE" allowed="true" />
</verbs>
<fileExtensions>
<add fileExtension=".svc" allowed="true" />
</fileExtensions>
</requestFiltering>
</security>
</system.webServer>
</configuration>
我还在 IIS 7 中检查了 *.svc 的处理程序映射,并检查了“所有动词”是否已启用。
【问题讨论】: