上下文:我建立了一个处理“Profile”对象的REST服务。每个配置文件都需要具有唯一名称。客户端需要进行验证的操作之一是检查是否已经存在具有给定名称的配置文件。
与其构建一个RPC风格的“ProfileExists”方法,我更愿意遵循REST设计原则,并向具有给定名称的配置文件发出HEAD请求,然后根据配置文件是否已经存在返回适当的响应代码(分别为200、404),不需要响应正文。
遵循较新的ServiceStack API惯例,我设置了一个接受Head请求的方法,并使用Fiddler成功测试了两种情况。
问题在客户端。通过ServiceStack的IRestClient接口发出HEAD请求证明很困难。虽然有Get、Post、Put和Delete方法,但没有Head方法。因此,我假设可以使用CustomMethod将HEAD动词显式指定为参数:
然而,底层实现(ServiceClientBase)在验证HttpVerb参数时会抛出异常:
与其构建一个RPC风格的“ProfileExists”方法,我更愿意遵循REST设计原则,并向具有给定名称的配置文件发出HEAD请求,然后根据配置文件是否已经存在返回适当的响应代码(分别为200、404),不需要响应正文。
遵循较新的ServiceStack API惯例,我设置了一个接受Head请求的方法,并使用Fiddler成功测试了两种情况。
public object Head(GetProfile request)
{
ValidateRequest(request);
HttpStatusCode responseCode;
using (var scope = new UnitOfWorkScope())
{
responseCode = _profileService.ProfileExists(request.Name) ? HttpStatusCode.OK : HttpStatusCode.NotFound;
scope.Commit();
}
return new HttpResult { StatusCode = responseCode };
}
问题在客户端。通过ServiceStack的IRestClient接口发出HEAD请求证明很困难。虽然有Get、Post、Put和Delete方法,但没有Head方法。因此,我假设可以使用CustomMethod将HEAD动词显式指定为参数:
public bool ProfileExists(string profileName)
{
try
{
var response = _restClient.CustomMethod<IHttpResult>(HttpMethods.Head, new GetProfile { Name = profileName });
return response.StatusCode == HttpStatusCode.OK;
}
catch (WebServiceException ex)
{
if (ex.StatusCode == 404)
return false;
}
// Return false for any other reason right now.
return false;
}
然而,底层实现(ServiceClientBase)在验证HttpVerb参数时会抛出异常:
if (HttpMethods.AllVerbs.Contains(httpVerb.ToUpper()))
throw new NotSupportedException("Unknown HTTP Method is not supported: " + httpVerb);
集合HttpMethods.AllVerbs包含RFC 2616中所有常见动词以及更多。除非这种行为是一个错误,否则对于任何已知的HTTP动词抛出异常表明CustomMethod作者的意图不包括能够发出已知HTTP动词的请求。
这就引出了我的问题:如何在ServiceStack客户端上发出HEAD请求?