我已关注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的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"}}
我从发送该请求时获得的回复是200
,但是当我查看已保存的Evals时,我刚刚添加的回复包含有效Id
,但是{{1} }和Comment
均为空,Submitter
为TimeSubmitted
。
似乎WCF正在获取请求,但未正确反序列化对象。但如果是这样的话,我不知道为什么它不会引发某种例外。看起来我做得对,或者我错过了什么?
更新:这是App.config中的端点声明:
1/1/0001 12:00:00 AM
端点行为指的是:
<endpoint binding="webHttpBinding" behaviorConfiguration="webHttp"
contract="EvalServiceLibrary.IEvalService" />
答案 0 :(得分:6)
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();
}
}
答案 1 :(得分:0)
对于POST,您需要使用BodyStyle = WebMessageBodyStyle.Bare NOT
WebMessageBodyStyle.Wrapped
[OperationContract]
[WebInvoke(RequestFormat = WebMessageFormat.Json,ResponseFormat = WebMessageFormat.Json,UriTemplate = "eval",BodyStyle = WebMessageBodyStyle.Bare)]
void SubmitEval(Eval eval);