我正在尝试使用ServiceStack为BitBucket api编写包装器。 api有相当复杂的网址,例如:
bitbucket.org/api/1.0/repositories/{accountname}/{repo_slug}/issues/{issue_id}/
此路由用于从ID获取问题。该问题是repo_slug存储库的一部分,它是accountname用户的存储库的一部分。这两个参数不是问题的一部分。那么我该如何为此写一条路线呢?我试过这个:
[Route("/repositories/{Accountname}/{RepositorySlug}/issues/{local_id}")]
public class GetIssue : IReturn<Issue>{
public string AccountName { get; set; }
public string RepositorySlug { get; set; }
// issue object properties from here on
public string status { get; set; }
public string priority { get; set; }
public string title { get; set; }
public User reported_by { get; set; }
public string utc_last_updated { get; set; }
public int comment_count { get; set; }
public Metadata metadata { get; set; }
public string content { get; set; }
public string created_on { get; set; }
public int local_id { get; set; }
public int follower_count { get; set; }
public string utc_created_on { get; set; }
public string resource_uri { get; set; }
public bool is_spam { get; set; }
}
所以基本上我将这两个参数与整个问题DTO结合起来。这适用于GET请求,但是当我尝试PUT更新的问题时,我从bitbucket收到错误。
然后我继续尝试伪造被称为的路径:
[Route("/repositories/a/a/issues/{Id}")]
public class GetIssue : IReturn<Issue>{
public int Id { get; set; }
}
我只是在这里使用ID,为了简洁,但这里将是整个DTO。然后,当我提出请求时,我伪造了我从这条路线获得的网址:
public Issue GetIssue(int issueId){
_url = "repositories/" + _accountName + "/" + _repository + "/issues/" + issueId;
return _sharpBucket.Get(new GetIssue{ Id = issueId}, _url);
}
这是从上面调用的get方法。
public T Get<T>(IReturn<T> request, string url = null){
return Send(request,
HttpMethods.Get,
overrideUrl: url,
sendRequestBody: false);
}
从上面调用的发送:
private T Send<T>(IReturn<T> request, string method, string overrideUrl = null, bool sendRequestBody = true){
var relativeUrl = overrideUrl ?? request.ToUrl(method);
var body = sendRequestBody ? QueryStringSerializer.SerializeToString(request)
: null;
var json = Send(relativeUrl, method, body);
var response = json.FromJson<T>();
return response;
}
public T Send<T>(IReturn<T> request){
var method = request is IPost<T> ?
HttpMethods.Post
: request is IPut<T> ?
HttpMethods.Put
: request is IDelete<T> ?
HttpMethods.Delete :
HttpMethods.Get;
return Send(request, method, sendRequestBody: false);
}
这种方式有效。有没有更好的办法?我想我一定错过了什么。我看到了类似的主题here,但它没有提供解决方案。
更新:
似乎这在v3版本中有漏洞。坚持我的“假装”网址方法。罪魁祸首似乎是UrlExtensions类的GetQueryProperties方法:http://www.diffchecker.com/u1nyqpcw
答案 0 :(得分:1)
Routing docs on the wiki提供有关ServiceStack中路由的信息。此外,您尝试在此处执行的方法与ServiceStack's Stripe Gateway使用属性DTO和generic StripeGateway client提供类型化API客户端的方法相同。
您的路线存在一些问题,应该以{{1}}开头,并且组件需要用斜杠分隔:
/
应改为:
[Route("repositories/{Accountname}/{RepositorySlug }issues/{local_id}")]
对此类型网关有用的另一个自定义选项是使用[Route("/repositories/{Accountname}/{RepositorySlug}/issues/{local_id}")]
来指定仅应在路径上而不在POST的DTO中的属性,例如:
[IgnoreDataMember]
检查路由生成的URL的快速方法是使用[Route("/path/{UseOnlyOnUrl}")]
public class Request
{
[IgnoreDataMember]
public string UseOnlyOnUrl { get; set; }
public string Data { get; set; }
}
扩展方法,例如:
To{Verb}Url()
您可以使用这些来验证每个Request DTO在不同的HTTP方法中使用时将生成哪些路径。