替换旧系统&;使用ServiceStack+自定义序列化创建新的服务器代码

本文关键字:创建 序列化 代码 服务器 自定义 ServiceStack+ 系统 amp 使用 替换 | 更新日期: 2023-09-27 18:27:50

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

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

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

替换旧系统&;使用ServiceStack+自定义序列化创建新的服务器代码

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

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

请求筛选器的问题是,它发生在反序列化到请求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标头:Accept:application/v-xml。

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

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

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

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

通过ServiceStack返回非null(即任何处理程序)。