【问题标题】:Is there a more elegant way to build URIs in ServiceStack?有没有更优雅的方式在 ServiceStack 中构建 URI?
【发布时间】:2016-02-10 00:17:32
【问题描述】:

我正在构建一个带有 NServiceBus 的Request/Acknowledge/Poll style REST service,以管理队列处理。我想给客户端一个 URI 来轮询更新。

因此,我想在我的 Web 服务中返回一个 location 标头元素作为确认的一部分。我可以看到可以这样做:

return new HttpResult(response, HttpStatusCode.Accepted)
{
    Location = base.Request.AbsoluteUri.CombineWith(response.Reference)
}

但是对于诸如 http://localhost:54567/approvals/?message=test 这样的 Url,它会创建一条新消息(我知道我应该只使用 POST),位置将返回为:http://localhost:54567/approvals/?message=test/8f0ab1c1a2ca46f8a98b75330fd3ac5c

ServiceStack 请求不公开 Uri 片段,仅公开 AbsouteUri。这意味着我需要访问原始请求。无论是在 IIS 中还是在自托管进程中运行,我都希望它能够正常工作。我能想到的最接近的是以下内容,但看起来很笨拙:

var reference = Guid.NewGuid().ToString("N");
var response = new ApprovalResponse { Reference = reference };

var httpRequest = ((System.Web.HttpRequest)base.Request.OriginalRequest).Url;
var baseUri = new Uri(String.Concat(httpRequest.Scheme, Uri.SchemeDelimiter, httpRequest.Host, ":", httpRequest.Port));
var uri = new Uri(baseUri, string.Format("/approvals/{0}", reference));

return new HttpResult(response, HttpStatusCode.Accepted)
{
    Location = uri.ToString()
};

现在返回:http://localhost:55847/approvals/8f0ab1c1a2ca46f8a98b75330fd3ac5c

有什么建议吗?无论 ServiceStack 是如何托管的,这都能正常工作吗?我有点害怕System.Web.HttpRequest 转换成self hosted process。这段代码安全吗?

【问题讨论】:

    标签: servicestack


    【解决方案1】:

    Reverse Routing

    如果您尝试为 ServiceStack 服务构建 url,您可以使用 RequestDto.ToGetUrl()RequestDto.ToAbsoluteUri() 构建相对和绝对 url,如前面的 question on Reverse Routing 所示。例如:

    [Route("/reqstars/search", "GET")]
    [Route("/reqstars/aged/{Age}")]
    public class SearchReqstars : IReturn<ReqstarsResponse>
    {
        public int? Age { get; set; }
    }
    
    var relativeUrl = new SearchReqstars { Age = 20 }.ToUrl("GET");
    var absoluteUrl = HostContext.Config.WebHostUrl.CombineWith(relativeUrl);
    
    relativeUrl.Print(); //=  /reqstars/aged/20
    absoluteUrl.Print(); //=  http://www.myhost.com/reqstars/aged/20
    

    要为其他第 3 方 API 创建 URL,请查看 Http Utils wiki,例如可以提供帮助的扩展方法,例如:

    var url ="http://api.twitter.com/user_timeline.json?screen_name={0}".Fmt(name);
    if (sinceId != null)
        url = url.AddQueryParam("since_id", sinceId);
    if (maxId != null)
        url = url.AddQueryParam("max_id", maxId);
    
    var tweets = url.GetJsonFromUrl()
        .FromJson<List<Tweet>>();
    

    您还可以使用QueryStringSerializer 来序列化许多不同的集合类型,例如:

    //Typed POCO
    var url = "http://example.org/login?" + QueryStringSerializer.SerializeToString(
       new Login { Username="mythz", Password="password" });
    
    //Anonymous type
    var url = "http://example.org/login?" + QueryStringSerializer.SerializeToString(
       new { Username="mythz", Password="password" });
    
    //string Dictionary
    var url = "http://example.org/login?" + QueryStringSerializer.SerializeToString(
      new Dictionary<string,string> {{"Username","mythz"}, {"Password","password"}});
    

    你也可以序列化内置的NameValueCollection.ToFormUrlEncoded()扩展,例如:

    var url = "http://example.org/login?" + new NameValueCollection { 
        {"Username","mythz"}, {"Password","password"} }.ToFormUrlEncoded();
    

    【讨论】:

    • 感谢这个黛米斯。我尝试了第一个示例,但 EndpointHost.Config.WebHostUrl 为空。我应该在 AppHost 中的服务配置中手动设置该值吗?
    猜你喜欢
    • 1970-01-01
    • 2021-10-29
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    • 2016-01-23
    • 2022-11-13
    • 2021-05-29
    • 2019-01-12
    相关资源
    最近更新 更多