REST似乎拒绝JSON POST

本文关键字:JSON POST 拒绝 REST | 更新日期: 2023-09-27 18:10:36

我试图以JSON格式POST数据,但服务器拒绝它。如果我在XML中POST,它将在XML或JSON中回复。

合同是

[ServiceContract]
public interface IService
{
    // One string data
    [OperationContract]
    [WebInvoke(
        BodyStyle = WebMessageBodyStyle.Bare,
        Method = "POST",
        ResponseFormat = WebMessageFormat.Xml,
        UriTemplate = "data")]
    string DataPost(Hidden param);
}
// If you get a compilation error, add
// System.Runtime.Serialization to the references
[DataContract(Name = "Hidden", Namespace = "")]
public class Hidden
{
    [DataMember]
    public string id { get; set; }
}

实现为

public class Service : IService
{
    public string DataPost(Hidden param)
    {
        Console.WriteLine("DataPost " + param.id);
        return "DataPost said " + param.id;
    }
}

在客户端,它是运行的工厂标准的东西。

namespace client
{
enum HttpVerb
{
    GET,
    POST,
    PUT,
    DELETE
};
class RestClient
{
    // Properties
    public string EndPoint { get; set; }
    public HttpVerb Method { get; set; }
    public string ContentType { get; set; }
    public string ParamData { get; set; }
    public string PostData { get; set; }
    // Methods
    public string MakeRequest()
    {
        var responseValue = string.Empty;
        string ep = EndPoint;
        if (!string.IsNullOrEmpty(ParamData))
            ep += "/" + ParamData;
        var request = (HttpWebRequest)WebRequest.Create(ep);
        request.Method = Method.ToString();
        request.ContentLength = 0;
        request.ContentType = ContentType;
        // Postdata parameters
        if (!string.IsNullOrEmpty(PostData) && Method == HttpVerb.POST)
        {
            var encoding = new UTF8Encoding();
            var bytes = Encoding.GetEncoding("iso-8859-1").GetBytes(PostData);
            request.ContentLength = bytes.Length;
            using (var postStream = request.GetRequestStream())
            {
                postStream.Write(bytes, 0, bytes.Length);
            }
            if (PostData.Substring(0, 1) != "<")
                request.ContentType = "application/json";
            Console.WriteLine("Content type is " + request.ContentType.ToString());
        }
        // Send request and get response
        using (var response = (HttpWebResponse)request.GetResponse())
        {
            // Did it work?
            if (response.StatusCode != HttpStatusCode.OK)
            {
                var message = String.Format("Request failed.  Received HTTP {0}", response.StatusCode);
                throw new ApplicationException(message);
            }
            // get response
            using (var responseStream = response.GetResponseStream())
            {
                if (responseStream != null)
                {
                    using (var reader = new StreamReader(responseStream))
                    {
                        responseValue = reader.ReadToEnd();
                    }
                }
            }
        }
        return responseValue;
    }
    void TalkTo(
        HttpVerb in_method,
        string in_endPoint,
        string in_paramdata,
        string in_postdata)
    {
        Method = in_method;
        EndPoint = in_endPoint;
        ContentType = "text/xml";
        ParamData = in_paramdata;
        PostData = in_postdata;
        try
        {
            string response = MakeRequest();
            Console.WriteLine("Endpoint: " + EndPoint);
            Console.WriteLine("Resp    : " + response);
            Console.WriteLine();
        }
        catch (System.Net.WebException e)
        {
            Console.WriteLine("Endpoint: " + EndPoint);
            Console.WriteLine("Failed  : " + e.Message);
        }
    }
    static void Main(string[] args)
    {
        RestClient me = new RestClient();
        string endPointPrefix = @"http://localhost:8000/";
        me.TalkTo(
            HttpVerb.POST,
            endPointPrefix + "data",
            "",
            "<Hidden><id>xml works</id></Hidden>");
        string post = "{'"id'":'"json works'"}";
        Console.WriteLine("Json string is [" + post + "]");
        me.TalkTo(
            HttpVerb.POST,
            endPointPrefix + "data",
            "",
            post);
        Console.WriteLine("Press <Enter> to terminate");
        Console.ReadLine();
    }
}
}

在客户端,我得到

Content type is text/xml
Endpoint: http://localhost:8000/data
Resp    : <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">DataPost said xml works</string>
Json string is [{"id":"json works"}]
Content type is application/json
Endpoint: http://localhost:8000/data
Failed  : The remote server returned an error: (400) Bad Request.
Press <Enter> to terminate

当我查看帮助时,它说JSON格式是允许的,但当我尝试它时,它摔倒了。来自服务器调试的跟踪似乎暗示它忽略了application/json,只是假设所有内容都是xml。

Exception: System.Runtime.Serialization.SerializationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Message: There was an error checking start element of object of type System.String. The data at the root level is invalid. Line 1, position 1.
Last few lines of stack trace
System.Runtime.Serialization.XmlObjectSerializer.IsStartObjectHandleExceptions(XmlReaderDelegator reader)
System.Runtime.Serialization.DataContractSerializer.IsStartObject(XmlDictionaryReader reader)
System.ServiceModel.Dispatcher.SingleBodyParameterMessageFormatter.ReadObject(Message message)

我在SO和其他网站上看到的所有示例都没有添加任何特别的内容,所以它不工作是因为我使用VS2013 express吗?

EDIT它也发生在VS2013 Web Express

EDIT2看起来不像是孤立的表达版本-我刚刚在VS2010专业版上尝试过。它仍然使用XMLObjectSerializer来解析JSON,并且失败得很惨。

REST似乎拒绝JSON POST

修复方法是不将PostData转换为字节

        if (!string.IsNullOrEmpty(PostData) && Method == HttpVerb.POST)
        {
            if (PostData.Substring(0, 1) != "<")
                request.ContentType = "application/json";
            Console.WriteLine("Content type is " + request.ContentType.ToString());
            request.ContentLength = PostData.Length;
            using (var postStream = new StreamWriter(request.GetRequestStream()))
            {
                postStream.Write(PostData);
            }
        }