4

我们有一个遗留的服务器代码,我们想放弃它并使用 ServiceStack 开发新的。现有客户端不是用 .Net 编写的。我们根本不打算在客户端使用 .Net。

客户端和服务器之间的数据正在使用 XML 和 JSON 进行交换 - 目前 JSON 仅用作响应的返回格式(仅用于某些可用服务)。XML 格式是在几年前创建服务器解决方案的第一个版本时定义的。我们不想改变它。

我们如何使用 ServiceStack 构建新的 RESTful Web 服务,将数据序列化和反序列化为过去设计的格式(请注意,客户端不会用 C#/.Net 编写)。我们需要同时控制:序列化和反序列化。是否可以使用 DTO 并且仍然可以控制这些对象如何序列化/反序列化?

4

1 回答 1

5

通过请求/响应过滤器添加自定义逻辑

请参阅请求和响应过滤器以了解如何在调用服务之前和之后添加自定义逻辑。最好通过Request / Response FilterAttributes添加这些过滤器,因为它允许您仅标记需要应用这些过滤器的服务。

请求过滤器的问题是它在反序列化为请求 DTO 之后发生,这为时已晚,无法添加自定义反序列化逻辑。为了解决这个问题,您可以在 AppHost 中注册一个自定义请求活页夹:

base.RegisterRequestBinder<MyRequest>(httpReq => ... requestDto);

这使您可以访问 IHttpRequest 对象并让您自己添加自定义反序列化逻辑。另一种选择是告诉 ServiceStack 不要尝试反序列化请求本身,而是注入 HttpRequest InputStream 以便您可以自己反序列化请求:

public class Hello : IRequiresRequestStream {
    Stream RequestStream { get; set; }
}

这两个示例都在 ServiceStack 的序列化和反序列化wiki 页面上进行了解释。

注册您自己的自定义媒体类型

另一个能够返回强类型 DTO 但更改某些请求的输出的选项可以通过添加新的自定义媒体类型来完成,如Northwind VCard 自定义媒体类型示例中所述,例如:

public static void Register(IAppHost appHost)
{
    appHost.ContentTypeFilters.Register( "text/x-vcard", SerializeToStream,  DeserializeFromStream);
}

...    

public static void SerializeToStream(IRequestContext requestContext, object response, Stream stream)
{
    var customerDetailsResponse = response as CustomerDetailsResponse;
    using (var sw = new StreamWriter(stream))
    {
        if (customerDetailsResponse != null)
        {
            WriteCustomer(sw, customerDetailsResponse.Customer);
        }
        var customers = response as CustomersResponse;
        if (customers != null)
        {
            customers.Customers.ForEach(x => WriteCustomer(sw, x));
        }
    }
}

如果您可以将自定义 XML 响应挂载到不同的内容类型(例如application/v-xml)下,这是一个不错的选择,这样它就不会与现有的 XML 格式/端点冲突。使用 HTTP 客户端上方的 ContentType 可以使用?format=v-xml或使用 HTTP Header: Accept: application/v-xml调用此自定义实现。

如果您想覆盖内置的 XML ContentType,您仍然可以,但如果它不是您必须支持的旧格式之一,我建议您回退到 SerializeStream 和 DeserializeStream 方法的原始 XmlSerializer 实现。

绕过 ServiceStack 并使用您自己的自定义 IHttpHandler 执行

另一种选择是完全绕过 ServiceStack,而是在您自己的自定义 IHttpRequest 处理程序中处理请求,方法是在您的 AppHost 的 ServiceStack 配置中注册它:

 SetConfig(new EndpointHostConfig { 
    RawHttpHandlers = {
      httpReq => return IsLegacyMatch(httpReq) ? new LegacyXmlHandler() : null 
    }
 });

返回非空值(即任何处理程序)绕过 ServiceStack。

于 2012-03-13T19:51:59.273 回答