有没有更优雅的方法在ServiceStack中构建URI?

时间:2013-04-10 15:33:03

标签: servicestack

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

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

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

但是对于像http://localhost:54567/approvals/?message=test这样创建新消息的网址(我知道我应该只使用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如何托管,这都有效吗?我有点害怕self hosted process中的System.Web.HttpRequest投射。这段代码安全吗?

1 个答案:

答案 0 :(得分:5)

Reverse Routing

如果您正在尝试为ServiceStack服务构建网址,则可以使用RequestDto.ToGetUrl()RequestDto.ToAbsoluteUri()来构建相对网址和绝对网址,如前面的question on Reverse Routing所示。 e.g:

[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

要为其他第三方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();