C# RESTful 服务 - HTTP 504 / 连接重置
C# RESTful service - HTTP 504 / Connection Reset
我有一个 C# 应用程序,它通过 RESTful 服务获取和 returns 信息。
我之前处理这些操作的方法是简单地 returned JSON 字符串,然后将这些字符串包装在 XML.
中
为了防止这种情况,我将 ResponseFormat 更改为 JSON,我现在正在 returning DataContracts,它们都来自一个抽象 class:
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 属性,我将上面的接口更改为(现在)抽象 class。
每个衍生产品还应用 DataContract 和 DataMember 属性。
当我调用服务的路由时,命令被执行,我可以在控制台中看到输出。但是,当 returning return 值时,我在控制台中看到以下内容,并且 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
}
如何解决和预防这个问题?
我认为这是一个序列化问题,与您的抽象数据合同有关。
看这个:KnownTypeAttribute - Serialization.
我认为您需要使用 KnownType 属性在抽象基础 class 上指定所有子classes。
这样DataContractSerializer在序列化和反序列化对象时可以识别所有类型。
[DataContract]
[KnownType(typeof(SubClassName1))] <-
[KnownType(typeof(SubClassName2))] <-
[KnownType(typeof(SubClassName3))] <-
public abstract class ClassName
{
...
}
对不起我的英语。希望对您有所帮助,
斯特凡诺
我有一个 C# 应用程序,它通过 RESTful 服务获取和 returns 信息。 我之前处理这些操作的方法是简单地 returned JSON 字符串,然后将这些字符串包装在 XML.
中为了防止这种情况,我将 ResponseFormat 更改为 JSON,我现在正在 returning DataContracts,它们都来自一个抽象 class:
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 属性,我将上面的接口更改为(现在)抽象 class。
每个衍生产品还应用 DataContract 和 DataMember 属性。
当我调用服务的路由时,命令被执行,我可以在控制台中看到输出。但是,当 returning return 值时,我在控制台中看到以下内容,并且 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
}
如何解决和预防这个问题?
我认为这是一个序列化问题,与您的抽象数据合同有关。
看这个:KnownTypeAttribute - Serialization.
我认为您需要使用 KnownType 属性在抽象基础 class 上指定所有子classes。
这样DataContractSerializer在序列化和反序列化对象时可以识别所有类型。
[DataContract]
[KnownType(typeof(SubClassName1))] <-
[KnownType(typeof(SubClassName2))] <-
[KnownType(typeof(SubClassName3))] <-
public abstract class ClassName
{
...
}
对不起我的英语。希望对您有所帮助,
斯特凡诺