ServiceStack:请求中的属性如果type是abstract,则DTO变为null

时间:2014-01-31 17:11:01

标签: c# json .net-4.0 servicestack servicestack-bsd

我有一个基于ServiceStack 3的客户端 - 服务器架构。我正在尝试创建一个服务,其请求DTO包含一个抽象类型的属性,有两个不同的具体类来实现它。抽象类型可以是抽象类或接口;但是,在任何一种情况下,服务器都会在属性中接收一个空对象。

有三个程序集和相应的名称空间:客户端和服务器都引用了TestClientServerCommonLib

即分布在三个集合中:

namespace CommonLib.Services
{
    public class GetThing : IReturn<GetThingResponse> // request DTO
    {
        public IThisOrThat Context { get; set; }
    }

    public class GetThingResponse
    {
        public Dictionary<int, string> Result { get; private set; }

        public GetThingResponse(Dictionary<int, string> result) // response DTO
        {
            Result = result;
        }
    }
}

namespace CommonLib
{
    public interface IThisOrThat { }

    public class This : IThisOrThat { } // and so forth
}

namespace Server.Services
{
    public class GetThing Service : IService
    {
        public object Get(GetThing request)
        {
            var foo = request.Context; // this is null
        }
    }
}

namespace TestClient
{
    class Program
    {
        public const string WSURL = "http://localhost:61435/";

        static void Main(string[] args)
        {
            using (var client = new JsonServiceClient(WSURL))
            {
                var result = client.Get(new GetThing
                                   {
                                       Context = new CommonLib.This("context info")
                                   });
            }
}

如果我将Context中的GetThing属性更改为This类型而不是IThisOrThat,则可行。将其保留为接口,或将IThisOrThat更改为抽象类,会导致数据以null传输。

我假设这是一个序列化问题。我已经尝试将接口更改为抽象类并使用适当的KnownType属性进行装饰,但ServiceStack的序列化器似乎没有从中受益。有没有办法完成这件事?

2 个答案:

答案 0 :(得分:2)

您需要在客户端启用JsConfig.IncludeTypeInfo = true;,因此序列化程序会在请求中包含类型信息。这将添加一个带有类型定义的额外属性(__type),以便服务知道将其键入的内容。

它当前失败,因为默认情况下请求不提供类型信息以将对象反序列化为实现接口的类。这是一个previously raised的问题。

问题是当JSON客户端发出请求时,它将序列化实现IThisOrThat的类,例如This类。但当它到达另一端时,ServiceStack.Text不知道将对象反序列化的内容。类型信息丢失,因此它不知道它是什么类型的IThisOrThat。因此,如果请求中没有额外的__type信息属性,则会发生这种情况:

情景:

interface ISomething
{
    string Name;
}

class MySomething : ISomething
{
    public string Name { get; set; }
    public int Age { get; set; }
}

class MySomethingElse : ISomething
{
    public string Name { get; set; }
    public int Size { get; set; }
}

然后使用类型化对象

从JsonServiceClient进行调用
client.Get(new MySomething { Name: "Duck", Age: 20 });

发送的JSON将是{ "Name":"Duck", "Age":20 }解串器现在选择的类型?它可能是MySomethingMySomethingElse,甚至是其他ISomething,它还不知道。因为它无法决定结果只是null

通常,界面和DTO不会混合see here

答案 1 :(得分:2)

我有类似的问题,并意识到我没有{得到;组;应用于响应DTO,因此我的对象的结果始终为null ...

认为这些信息也可以帮助任何人搜索...