从Fiddler到WCF的POST成功,但传递空值 [英] POST to WCF from Fiddler succeeds but passes null values

查看:60
本文介绍了从Fiddler到WCF的POST成功,但传递空值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've followed this video series on WCF and have the demo working. It involves building a WCF service that manages student evaluation forms, and implements CRUD operations to operate on a list of those evaluations. I've modified my code a little according to this guide so it will return JSON results to a browser or Fiddler request. My goal is to figure out how to use the service by building my own requests in Fiddler, and then use that format to consume the service from an app on a mobile device.

使用Fiddler的SubmitEval方法(保存评估)时遇到麻烦.调用可以进行,但是Eval的所有字段均为空(或默认),但Id除外,后者是在服务本身中设置的.

I'm having trouble using the SubmitEval method (save an evaluation) from Fiddler. The call works, but all the fields of Eval are null (or default) except Id, which is set in the service itself.

这是我的Eval声明(使用属性代替

Here is my Eval declaration (using properties instead of fields as per this question):

[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; }
}

这是IEvalService的相关部分:

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

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);
    }
}

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

In Fiddler's Request Builder, I set the Method to POST and the address to http://localhost:49444/EvalServiceSite/Eval.svc/eval. I added the header Content-Type: application/json; charset=utf-8 to the default headers. The request body is:

{"eval":{"Comment":"testComment222","Id":"doesntMatter", 
  "Submitter":"Tom","TimeSubmitted":"11/10/2011 4:00 PM"}}

我从发送该请求得到的响应是200,但是当我查看已保存的评估时,我刚刚添加的评估有一个有效的Id,但是CommentSubmitter是均为null,TimeSubmitted1/1/0001 12:00:00 AM.

The response I get from sending that request is 200, but when I then look at the Evals that have been saved, the one I just added has a valid Id, but Comment and Submitter are both null, and TimeSubmitted is 1/1/0001 12:00:00 AM.

似乎WCF正在获取请求,但未正确反序列化对象.但是,如果真是这样,我不知道为什么它没有引发某种异常.看起来我做对了吗,还是我错过了什么?

It seems like WCF is getting the request, but is not deserializing the object correctly. But if that's the case, I don't know why it's not throwing some sort of exception. Does it look like I'm doing this right, or am I missing something?

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

UPDATE: Here is the endpoint declaration in App.config:

 <endpoint binding="webHttpBinding" behaviorConfiguration="webHttp"
   contract="EvalServiceLibrary.IEvalService" />

端点行为指的是:

<behavior name="webHttp">
  <webHttp defaultOutgoingResponseFormat="Json"/>
</behavior>

推荐答案

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

The default body style in the WebInvoke attribute is Bare, meaning that the object should be sent without a wrapper containing the object name:

{"Comment":"testComment222",
 "Id":"doesntMatter",
 "Submitter":"Tom",
 "TimeSubmitted":"11/10/2011 4:00 PM"}

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

Or you can set the request body style to Wrapped, and that would make the input require the wrapping {"eval"...} object:

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

更新:由于使用的是DateTime,因此代码中还有另一个问题,WCF序列化程序期望的JSON日期格式类似于\/Date(1234567890)\/.您可以按照

Update: there's another problem in your code, since you're using DateTime, and the format expected by the WCF serializer for dates in JSON is something like \/Date(1234567890)\/. You can change your class to support the format you have by following the logic described at MSDN Link (fine-grained control of serialization format for primitives), and shown in the code below.

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();
    }
}

这篇关于从Fiddler到WCF的POST成功,但传递空值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆