我编写了一个基于REST的WCF服务示例,其中包含以下URI模板合同
[OperationContract]
[WebGet(UriTemplate = "/entity/{entityIdString}/mem",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare)]
Task<Entity> TestEntityJsonMemory(string entityIdString);
[OperationContract]
[WebGet(UriTemplate = "/entity/{entityIdString}/string",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare)]
Task<System.ServiceModel.Channels.Message> TestEntityJsonString(string entityIdString);
首先是将实体对象直接返回到WCF以进行序列化(使用DataContractJsonSerializer),另一个是在执行自定义JSON.NET序列化之前作为原始消息进行性能比较。
public async Task<Entity> TestEntityJsonMemory(string entityIdString)
{
return await new Tests.TestLoader().TestEntityJsonMemory(entityIdString);
}
public async Task<Message> TestEntityJsonString(string entityIdString)
{
var entity = await new Tests.TestLoader().TestEntityJsonMemory(entityIdString);
var jsonString = JsonConvert.SerializeObject(entity);
return WebOperationContext.Current.CreateTextResponse(jsonString, "application/json; charset=utf-8", Encoding.UTF8);
}
在返回客户端之前,两个操作都使用相同的内部过程来加载和缓存测试对象。使用标准WCF练习/实体/ entityId / mem的URI工作正常。
但是对于/ entity / entityId / string,在处理后续调用之前,它将始终在第一次调用时抛出异常。
请求错误服务器在处理请求时遇到错误。 异常消息是'对象引用未设置为实例 一个东西。'。请参阅服务器日志以获取更多详异常堆栈 追踪是:
at System.ServiceModel.Dispatcher.TaskMethodInvoker.InvokeEnd(Object 实例,对象[]&amp;输出,IAsyncResult结果)at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeEnd(MessageRpc&安培; rpc)at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage7(MessageRpc&安培; rpc)at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
没有事件日志来通知此对象引用失败的位置。我不知道为什么第二次操作只在第一次调用时才会进入这种状态?
更新2014年4月21日
在进一步挖掘时,似乎在第一次请求时,WebOperationContext.Current为null。为什么那会是空的?此后的其他要求也没有问题?
答案 0 :(得分:0)
由于在await之后没有明显的解决方案WCF如何丢失其请求上下文,我找到的解决方法是在等待异步方法之前安全地引用WebOperationContext.Current。
等待之后,对原始上下文的引用因此被保留并可用。
// Custom UTF-8 encoding
private static UTF8Encoding utf8 = new UTF8Encoding(false);
public async Task<Message> RawMessageOperation(string params)
{
var webContext = WebOperationContext.Current;
var result = await whateverAsyncWork(params);
// Further more use custom utf8 encoding otherwise WCF returns additional encoding characters not parsable as JSON.
return webContext.CreateTextResponse(JsonConvert.Serialize(result), "application/json; charset=utf-8", utf8);
}