【问题标题】:WCF REST operation object null reference on first call第一次调用 WCF REST 操作对象空引用
【发布时间】:2014-04-15 08:16:32
【问题描述】:

我使用以下 URI 模板合同编写了一个基于 REST 的示例 WCF 服务

[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 实践 /entity/entityId/mem 的 URI 工作正常。

但是,对于 /entity/entityId/string,它总是会在第一次调用时抛出异常,然后再处理后续调用。

请求错误 服务器在处理请求时遇到错误。 异常消息是“对象引用未设置为 一个东西。'。有关更多详细信息,请参阅服务器日志。异常堆栈 跟踪是:

在 System.ServiceModel.Dispatcher.TaskMethodInvoker.InvokeEnd(Object 实例,Object[]& 输出,IAsyncResult 结果)在 System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeEnd(MessageRpc& RPC)在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage7(MessageRpc& rpc) 在 System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

没有事件日志可以告知此对象引用失败的位置。我不知道为什么第二次操作只有在第一次调用时才会进入这种情况?

2014 年 4 月 21 日更新

进一步挖掘,似乎在第一次请求时,WebOperationContext.Current 为空。为什么那会是空的?之后的其他请求都可以吗?

【问题讨论】:

    标签: wcf serialization


    【解决方案1】:

    由于对于 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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-19
      • 1970-01-01
      • 1970-01-01
      • 2019-08-09
      • 2012-01-29
      • 2021-10-28
      • 2016-08-14
      相关资源
      最近更新 更多