ServiceStack 中的复杂路由

问题描述 投票:0回答:1

我正在尝试使用 ServiceStack 为 BitBucket API 编写包装器。该 API 有相当复杂的 URL,例如:

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; }
}

所以基本上我将这两个参数与整个 Issue 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

c# .net servicestack bitbucket-api
1个回答
1
投票

wiki 上的路由文档提供了有关 ServiceStack 中路由的信息。此外,您在这里尝试执行的方法与ServiceStack 的 Stripe Gateway 相同,它使用属性 DTO 和通用 StripeGateway 客户端 来提供类型化 API 客户端。

您的路线存在一些问题,应以

/
开头,并且组件需要用斜杠分隔,因此:

[Route("repositories/{Accountname}/{RepositorySlug }issues/{local_id}")]

应该是:

[Route("/repositories/{Accountname}/{RepositorySlug}/issues/{local_id}")]

对于像这样的类型化网关有用的另一个自定义选项是使用

[IgnoreDataMember]
来指定仅应在路由上而不是在 POST 的 DTO 中的属性,例如:

[Route("/path/{UseOnlyOnUrl}")]
public class Request
{
    [IgnoreDataMember]
    public string UseOnlyOnUrl { get; set; }

    public string Data { get; set; }
}

检查路由生成的 url 的快速方法是使用

To{Verb}Url()
扩展方法,例如:

new Request().ToGetUrl().Print();
new Request().ToPostUrl().Print();
new Request().ToPutUrl().Print();
new Request().ToDeleteUrl().Print();
new Request().ToUrl("CustomVerb","json").Print();

您可以使用它们来验证每个请求 DTO 在不同的 HTTP 方法中使用时将生成哪些路径。

© www.soinside.com 2019 - 2024. All rights reserved.