简体   繁体   中英

C# RESTful service - HTTP 504 / Connection Reset

I have a C# application that takes and returns information via RESTful services. The way I handled these operations before, was the methods simply returned JSON strings, and these strings were then wrapped in XML.

To prevent this, I changed the ResponseFormat to JSON and I am now returning DataContracts, which all derive from one abstract 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; }

}

To apply the DataContract attribute, I changed the above interface to a (now) abstract class.

Each derivative also applies the DataContract and DataMember attributes.

When I call a route of the service, the command gets executed, and I can see output in the console. When returning the return value, however, I see following in the console, and the web browser stays empty. Fiddler (on Windows) shows me a HTTP 504 error, whereas my Mac shows me a connection reset.

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

The specific method I'm using to test this, is as follows:

IRestService:

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

RestService (implementation):

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

Actual command implementation (so it can be called via the console, too):

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
    }

How can this be fixed and prevented?

I think that this is a serialization problem, with your abstact DataContract.

Look this: KnownTypeAttribute - Serialization .

I think that you need specify all your subclasses on the abstract base class using KnownType Attribute.

In this way the DataContractSerializer can recognize all types when serialize and deserialize objects.

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

Sorry for my english. I hope I was helpful,

Stefano

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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