从Fiddler到WCF的POST成功但传递空值

Tom*_*ing 3 wcf json fiddler

在WCF上关注了这个视频系列并让演示工作.它涉及构建管理学生评估表单的WCF服务,并实现CRUD操作以对这些评估列表进行操作.我根据本指南稍微修改了我的代码,因此它会将JSON结果返回给浏览器或Fiddler请求.我的目标是通过在Fiddler中构建我自己的请求来弄清楚如何使用该服务,然后使用该格式从移动设备上的应用程序中使用该服务.

我在使用SubmitEvalFiddler 的方法(保存评估)时遇到了麻烦.调用有效,但所有字段Eval都为null(或默认),除了Id在服务本身中设置.

这是我的Eval声明(根据此问题使用属性而不是字段):

[DataContract]
public class Eval //Models an evaluation
{
    [DataMember]
    public string Id { get; set; }

    [DataMember]
    public string Submitter { get; set; }

    [DataMember]
    public string Comment { get; set; }

    [DataMember]
    public DateTime TimeSubmitted { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

以下是相关部分IEvalService:

[ServiceContract]
public interface IEvalService
{
 ...
   [OperationContract]
    [WebInvoke(RequestFormat=WebMessageFormat.Json,
       ResponseFormat=WebMessageFormat.Json, UriTemplate = "eval")]
    void SubmitEval(Eval eval);
}
Run Code Online (Sandbox Code Playgroud)

而且EvalService:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
class EvalService : IEvalService
{
...
  public void SubmitEval(Eval eval)
    {
        eval.Id = Guid.NewGuid().ToString();
        Console.WriteLine("Received eval");
        evals.Add(eval);
    }
}
Run Code Online (Sandbox Code Playgroud)

在Fiddler的Request Builder中,我将Method设置为POST,将地址设置为http://localhost:49444/EvalServiceSite/Eval.svc/eval.我将标头添加Content-Type: application/json; charset=utf-8到默认标头.请求正文是:

{"eval":{"Comment":"testComment222","Id":"doesntMatter", 
  "Submitter":"Tom","TimeSubmitted":"11/10/2011 4:00 PM"}}
Run Code Online (Sandbox Code Playgroud)

我从发送该请求得到的回应是200,但是当我再看看已经保存了Evals,我只是增加了一个具有有效的Id,但CommentSubmitter都为null,并且TimeSubmitted1/1/0001 12:00:00 AM.

看起来WCF正在获取请求,但没有正确反序列化对象.但如果是这样的话,我不知道为什么它不会引发某种例外.看起来我做得对,或者我错过了什么?

更新:这是App.config中的端点声明:

 <endpoint binding="webHttpBinding" behaviorConfiguration="webHttp"
   contract="EvalServiceLibrary.IEvalService" />
Run Code Online (Sandbox Code Playgroud)

并且端点行为指的是:

<behavior name="webHttp">
  <webHttp defaultOutgoingResponseFormat="Json"/>
</behavior>
Run Code Online (Sandbox Code Playgroud)

car*_*ira 6

WebInvoke属性中的默认主体样式是Bare,这意味着应该在没有包含对象名称的包装器的情况下发送对象:

{"Comment":"testComment222",
 "Id":"doesntMatter",
 "Submitter":"Tom",
 "TimeSubmitted":"11/10/2011 4:00 PM"}
Run Code Online (Sandbox Code Playgroud)

或者您可以将请求正文样式设置为Wrapped,这将使输入需要包装{"eval"...}对象:

[OperationContract]
[WebInvoke(RequestFormat=WebMessageFormat.Json,
   ResponseFormat=WebMessageFormat.Json,
   UriTemplate = "eval",
   BodyStyle = WebMessageBodyStyle.WrappedRequest)] // or .Wrapped
void SubmitEval(Eval eval);
Run Code Online (Sandbox Code Playgroud)

更新:您的代码中存在另一个问题,因为您正在使用DateTime,并且WCF序列化程序对JSON中的日期所期望的格式是这样的\/Date(1234567890)\/.您可以按照MSDN Link中描述的逻辑(对基元的序列化格式进行细粒度控制)更改类以支持您的格式,并在下面的代码中显示.

public class StackOverflow_8086483
{
    [DataContract]
    public class Eval //Models an evaluation
    {
        [DataMember]
        public string Id { get; set; }

        [DataMember]
        public string Submitter { get; set; }

        [DataMember]
        public string Comment { get; set; }

        [DataMember(Name = "TimeSubmitted")]
        private string timeSubmitted;

        public DateTime TimeSubmitted { get; set; }

        public override string ToString()
        {
            return string.Format("Eval[Id={0},Submitter={1},Comment={2},TimeSubmitted={3}]", Id, Submitter, Comment, TimeSubmitted);
        }

        [OnSerializing]
        void OnSerializing(StreamingContext context)
        {
            this.timeSubmitted = this.TimeSubmitted.ToString("MM/dd/yyyy h:mm tt", CultureInfo.InvariantCulture);
        }

        [OnDeserialized]
        void OnDeserialized(StreamingContext context)
        {
            DateTime value;
            if (DateTime.TryParseExact(this.timeSubmitted, "MM/dd/yyyy h:mm tt", CultureInfo.InvariantCulture, DateTimeStyles.None, out value))
            {
                this.TimeSubmitted = value;
            }
        }
    }

    [ServiceContract]
    public interface IEvalService
    {
        [OperationContract]
        [WebInvoke(RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json, UriTemplate = "eval",
           BodyStyle = WebMessageBodyStyle.Wrapped)]
        void SubmitEval(Eval eval);
    }

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    class EvalService : IEvalService
    {
        public void SubmitEval(Eval eval)
        {
            Console.WriteLine("Received eval: {0}", eval);
        }
    }

    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        WebServiceHost host = new WebServiceHost(typeof(EvalService), new Uri(baseAddress));
        host.Open();
        Console.WriteLine("Host opened");

        string data = "{\"eval\":{\"Comment\":\"testComment222\",\"Id\":\"doesntMatter\", \"Submitter\":\"Tom\",\"TimeSubmitted\":\"11/10/2011 4:00 PM\"}}";
        WebClient c = new WebClient();
        c.Headers[HttpRequestHeader.ContentType] = "application/json; charset=utf-8";
        c.UploadData(baseAddress + "/eval", Encoding.UTF8.GetBytes(data));

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}
Run Code Online (Sandbox Code Playgroud)