如何在将ClientCertificate应用于WCF DataService客户端时解决此InvalidCastException?

时间:2014-01-20 14:54:00

标签: wcf odata wcf-data-services client-certificates

我已使用this article中的示例将客户端证书身份验证添加到我的WCF数据服务。我不得不稍微更改示例,因为我正在使用WCF DataService 5.6,其中SendingRequest事件已被弃用并被SendingRequest2替换。

基本上这意味着更改以下事件处理程序:

private void OnSendingRequest_AddCertificate(object sender, SendingRequestEventArgs args)
{
    if (null != ClientCertificate)
    {
        ((HttpWebRequest)args.Request).ClientCertificates.Add(ClientCertificate);
    }
}

要:

private void OnSendingRequest_AddCertificate(object sender, SendingRequest2EventArgs args)
{
    if (null != ClientCertificate)
    {
        ((HttpWebRequestMessage)args.RequestMessage).HttpWebRequest.ClientCertificates.Add(ClientCertificate);
    }
}

这似乎有效。但是现在我在某些操作上得到以下InvalidCastException

  

System.InvalidCastException:无法转换类型的对象   键入'System.Data.Services.Client.InternalODataRequestMessage'   'System.Data.Services.Client.HttpWebRequestMessage'。

我无法100%准确地确定这些行为是什么,但似乎在SaveChanges方法上始终如一(请参阅下面的stacktrace :)

at MyNamespace.MyContainer.OnSendingRequest_AddCertificate(Object sender, SendingRequest2EventArgs args)
at System.Data.Services.Client.ODataRequestMessageWrapper.FireSendingRequest2(Descriptor descriptor)
at System.Data.Services.Client.BatchSaveResult.GenerateBatchRequest()
at System.Data.Services.Client.BatchSaveResult.BatchRequest()
at System.Data.Services.Client.DataServiceContext.SaveChanges(SaveChangesOptions options)

我通过反复试验从SendingRequestSendingRequest2进行了修改,所以我想知道我是否忽略了那里的某些内容。或者这是完全不相关的,我应该在处理程序中的if语句中添加&& args.RequestMessage is HttpWebRequestMessage吗?

2 个答案:

答案 0 :(得分:2)

似乎您正在发送批量请求。批处理请求包含几个内部请求,即InternalODataRequestMessage。 SendingRequest2会将OnSendingRequest操作应用于$ batch请求及其内部请求。

您可以尝试以下代码

private void OnSendingRequest_AddCertificate(object sender, SendingRequest2EventArgs args)
{
    if (null != ClientCertificate && !args.IsBatchPart)
    {
        ((HttpWebRequestMessage)args.RequestMessage).HttpWebRequest.ClientCertificates.Add(ClientCertificate);
    }
}

如果在批处理中为请求触发此事件,则args.IsBatchPart返回true,否则返回false。

答案 1 :(得分:0)

执行批处理操作时似乎出现问题。

我试图挖掘InternalODataRequestMessage以查看是否可以使用反射和DataServices源以某种方式添加客户端证书。我发现InternalODataRequestMessage的实例有一个requestMessage类型的私有成员ODataBatchOperationRequestMessage。通过查看source code我无法添加证书。

我注意到的是,我实际上仍然可以像以前一样使用已弃用的SendingRequest事件。这就是我做的,一切似乎都很好。

我觉得应该有一种方法来使用客户端证书而不使用弃用的方法。因此,如果某人有答案显示,我会接受。