【问题标题】:C# RESTful service - HTTP 504 / Connection ResetC# RESTful 服务 - HTTP 504 / 连接重置
【发布时间】:2017-02-09 14:22:44
【问题描述】:

我有一个 C# 应用程序,它通过 RESTful 服务获取和返回信息。 我之前处理这些操作的方式是,方法只是简单地返回 JSON 字符串,然后将这些字符串包装在 XML 中。

为了防止这种情况,我将 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
    }

如何解决和预防这种情况?

【问题讨论】:

    标签: c# json rest webinvoke webget


    【解决方案1】:

    我认为这是一个序列化问题,与您的抽象数据合同有关。

    看这个:KnownTypeAttribute - Serialization

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

    这样DataContractSerializer可以在序列化和反序列化对象时识别所有类型。

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

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

    斯特凡诺

    【讨论】:

    • 在这种情况下,这不是一种非常可扩展的做事方式。我会试一试,我会尽快回复您。
    • 这似乎并没有解决问题。除非我必须定义在返回值中可能使用或不使用的每一种类型。它必须比这更容易。
    • @Beatsleigher 是的,如果您想在 wcf dto 中使用抽象类,则必须定义所有这些属性。我试图在 vs 中重新创建您的情况,如果我调用返回抽象类的 OperationContract,我可以对其进行调试,但是当它返回时,响应不会到达。 (就像你看到的那样)。如果我把属性 [KnownType(typeof(SubClassName1))] 我可以看到 wcf 响应。
    • 如果我返回子类,则响应为(示例):{"Message":"NoAbstract"} 如果我返回抽象类,则响应为:{"__type":"TestResult", "Message":"Test"} 这个 '__type' 是我想的子类。如果我记得,在您的帖子中,我在 XMLException 中看到了“__type”一词。也许这两件事以某种方式联系在一起? (我不知道,我想)
    • 最后一件事,您是否尝试过修改“普通”类中的抽象类并查看 WCF 是否返回一些数据?如果您尝试这样做,您/我们可以知道“504 错误”是由抽象类还是由其他东西给出的。
    猜你喜欢
    • 1970-01-01
    • 2018-01-15
    • 1970-01-01
    • 2012-03-11
    • 1970-01-01
    • 1970-01-01
    • 2015-11-30
    • 2014-03-25
    • 1970-01-01
    相关资源
    最近更新 更多