【问题标题】:POST to WCF from Fiddler succeeds but passes null values从 Fiddler POST 到 WCF 成功但传递空值
【发布时间】:2011-11-10 21:23:12
【问题描述】:

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

我在使用 Fiddler 的 SubmitEval 方法(保存评估)时遇到问题。调用有效,但 Eval 的所有字段均为空(或默认),但 Id 除外,它是在服务本身中设置的。

这是我的Eval 声明(使用属性而不是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 的请求生成器中,我将方法设置为 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"}}

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

似乎 WCF 正在获取请求,但没有正确反序列化对象。但如果是这样的话,我不知道为什么它没有抛出某种异常。看起来我做得对,还是我错过了什么?

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

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

以及端点行为所指:

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

【问题讨论】:

    标签: wcf json fiddler


    【解决方案1】:

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

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

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

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

    更新:您的代码中还有另一个问题,因为您使用的是 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();
        }
    }
    

    【讨论】:

    • Http 400,确切地说。错误消息显示“服务器在处理请求时遇到错误。有关详细信息,请参阅服务器日志。”
    • 这是因为您的代码中的 DateTime 不是预期的格式。我也用解决方案更新了答案。
    • 做到了!我希望它能够更好地解析 DateTime,因为我以前使用过 Web 服务,并且可以使用通常的格式找到这些服务。
    • 这是对 WCF 的常见抱怨。在 4.5 上,他们修复了它,因此您可以更改日期时间格式
    【解决方案2】:

    对于 POST,您需要使用 BodyStyle = WebMessageBodyStyle.Bare NOT
    WebMessageBodyStyle.Wrapped

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

    【讨论】:

      猜你喜欢
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多