简体   繁体   English

ServiceStack:如果类型为抽象,则请求DTO中的属性为null

[英]ServiceStack: Property in request DTO becomes null if type is abstract

I have a ServiceStack 3-based client-server architecture. 我有一个基于ServiceStack 3的客户端-服务器体系结构。 I'm trying to create a service whose request DTO contains a property with an abstract type, with two different concrete classes implementing it. 我正在尝试创建一个服务,该服务的请求DTO包含具有抽象类型的属性,并通过两个不同的具体类来实现它。 The abstract type could be either an abstract class or an interface; 抽象类型可以是抽象类或接口。 however, in either case, the server receives a null object in the property. 但是,无论哪种情况,服务器都会在属性中收到一个空对象。

There's three assemblies and corresponding namespaces: TestClient , Server , and CommonLib referenced by both client and server. 客户机和服务器都引用了三个程序集和相应的名称空间: TestClientServerCommonLib

That is, spread across the three assemblies: 也就是说,分布在三个程序集中:

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")
                                   });
            }
}

If I change the Context property in GetThing to be of type This instead of IThisOrThat , this works. 如果我将GetThingContext属性更改为This而不是IThisOrThat类型,则可以使用。 Leaving it as the interface, or changing IThisOrThat to be an abstract class, results in the data being transmitted as null . 将其保留为接口,或者将IThisOrThat更改为抽象类,将导致数据以null形式传输。

I'm assuming this is a serialization problem. 我假设这是一个序列化问题。 I've tried changing the interface to an abstract class and decorating that with appropriate KnownType attributes, but ServiceStack's serializer doesn't appear to benefit from this. 我尝试将接口更改为抽象类,并使用适当的KnownType属性对其进行装饰,但是ServiceStack的序列化程序似乎并未从中受益。 Is there any trick to get this done? 有什么技巧可以做到这一点吗?

You would need to enable JsConfig.IncludeTypeInfo = true; 您需要启用JsConfig.IncludeTypeInfo = true; on the client side, so the serializer includes the type information with the request. 在客户端,因此序列化程序将类型信息包含在请求中。 This will add an extra property ( __type ) with the type definition so the service knows what to type it as. 这将在类型定义中添加一个额外的属性( __type ),以便服务知道将其键入为什么。

It fails currently because requests by default don't provide type information to deserialize the object into the class that implements the interface. 当前失败,因为默认情况下请求不提供类型信息以将对象反序列化为实现接口的类。 This was an issue that was previously raised . 这是先前提出的问题。

The problem is the when the JSON client makes the request, it will serialize up the a class that implements IThisOrThat such as your This class. 问题是当JSON客户端发出请求时,它将序列化实现IThisOrThat的类,例如您的This类。 But when it gets to the other end ServiceStack.Text doesn't know what to deserialize the object into. 但是当到达另一端时,ServiceStack.Text不知道将对象反序列化成什么。 The type information is lost so it doesn't know what kind of IThisOrThat it is. 类型信息丢失,因此它不知道它是哪种IThisOrThat So without the additional __type information property in the request this is happening: 因此,在请求中没有其他__type information属性的情况发生了:

Scenario: 场景:

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; }
}

Then you make the call from your JsonServiceClient using a typed object 然后,使用类型对象从JsonServiceClient进行调用

client.Get(new MySomething { Name: "Duck", Age: 20 });

The JSON that is sent would be { "Name":"Duck", "Age":20 } what type does the deserialiser choose now? 发送的JSON将是{ "Name":"Duck", "Age":20 }解串器现在选择哪种类型? It could be an MySomething or a MySomethingElse , or even another ISomething that it just doesn't know about yet. 可能是MySomethingMySomethingElse ,甚至可能是尚不知道的另一个ISomething So because it can't decide the result is simply null . 因此,因为无法确定结果只是null

Generally interfaces and DTOs don't mix, see here . 通常,接口和DTO不会混合使用, 请参见此处

I had a similar problem, and realized i didn't have { get; 我遇到了类似的问题,并且意识到我没有{ set; 组; } applied to the response DTO, so the result of my object was always null... }应用于响应DTO,所以我对象的结果始终为null ...

Thought this information could also help anyone searching for this ... 认为此信息也可以帮助任何人搜索此信息...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM