第一次调用时WCF REST操作对象为null引用

时间:2014-04-15 08:16:32

标签: wcf serialization

我编写了一个基于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。为什么那会是空的?此后的其他要求也没有问题?

1 个答案:

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