2017-02-09 50 views
0

我有一个C#应用程序,通过RESTful服务接收并返回信息。 我之前处理这些操作的方式是方法简单地返回JSON字符串,然后这些字符串被包装在XML中。C#RESTful服务 - HTTP 504 /连接重置

为了防止这种情况,我改变了ResponseFormat以JSON和我现在回到DataContracts,而这一切从一个抽象类派生:

using System.Runtime.Serialization; 

/// <summary> 
/// Abstract class for defining a standard definition of a command return result. 
/// A command is not required to return a result, however it is recommended. 
/// A return result must implement the properties defined in this abstract class. 
/// A command may return an anonymous object instead of an instance of this abstract class. 
/// </summary> 
[DataContract(Namespace = "")] 
public abstract class ICommandResult { 
// Don't let the name disturb you, this used to be an interface. 

    /// <summary> 
    /// Gets or sets the message. 
    /// </summary> 

    [DataMember] 
    public abstract string Message { get; set; } 

} 

要应用DataContract属性,我改变了上述接口的(现在)抽象类。

每个派生也应用DataContract和DataMember属性。

当我调用服务的路由时,命令被执行,我可以在控制台中看到输出。但是,返回返回值时,我在控制台中看到以下内容,并且Web浏览器保持空白。 Fiddler(在Windows上)向我显示HTTP 504错误,而我的Mac显示连接重置。

XmlException (Dropped Connection?): On JSON writer data type 'type' must be specified. Object string is 'object', server type string is '__type'. 

具体方法我使用来测试此,如下:

IRestService:

[OperationContract] 
[WebGet(UriTemplate = Routing.GetRoutesRoute, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)] 
ICommandResult GetAllRoutes(); 

RestService(实施):

public ICommandResult GetAllRoutes() { 
    var results = ExecuteCommand("print-routes", "--no-output"); 
    // ExecuteCommand returns an ICommandResult object 
    return results; 
} 

实际命令实现(所以也可以通过控制台调用):

ICommandResult Command_PrintRoutes(Command sender, params string[] args) { 
     var fields = typeof(Routing).GetFields(); 
     var fieldValues = new Dictionary<string, string>(); 
     var outputToConsole = true; 

     if (args.Count(x => x.ToLowerInvariant().Equals("--no-output")) == 1) 
      outputToConsole = false; 

     foreach (var field in fields) 
      fieldValues.Add(field.Name, (string)field.GetRawConstantValue()); 

     var output = JsonConvert.SerializeObject(fieldValues, Formatting.Indented); 

     if (outputToConsole) 
      WriteLine(output); 

     //return new CommandResult<Dictionary<string, string>>("Found following routes", fieldValues); 
     return new CommandResult<string>("Found following routes (JSON-encoded)", output); // Trying out different return types 
    } 

这是如何解决和防止的?

回答

0

我认为这是一个序列化问题,与您的抽象DataContract。

看这个:KnownTypeAttribute - Serialization

我认为你需要使用KnownType属性在抽象基类上指定所有的子类。

通过这种方式,DataContractSerializer可以在序列化和反序列化对象时识别所有类型。

[DataContract] 
[KnownType(typeof(SubClassName1))] <- 
[KnownType(typeof(SubClassName2))] <- 
[KnownType(typeof(SubClassName3))] <- 
public abstract class ClassName 
{ 
     ... 
} 

对不起,我的英语。我希望我是有帮助的,

斯特凡诺

+0

不是一个非常可扩展的方式做事情在这种情况下。 我会试一试,我会尽快回复您。 – SimonC

+0

这似乎并没有解决问题。 除非我必须定义可能或不可以用在返回值中的每一种类型。 它必须比这更容易。 – SimonC

+0

@Beatsleigher是的,如果你想在wcf dto中使用抽象类,你必须定义所有这些属性。 我试图在vs中重新创建你的情况,如果我调用返回抽象类的OperationContract,我可以调试它,但是当它返回时,响应不会到达。 (就像你看到的)。 如果我把属性[KnownType(typeof(SubClassName1))]我可以看到wcf响应。 – SteeBono