问题
I have used the examples in this article to add client certificate authentication to my WCF Data Service. I had to change the example slightly because I am using WCF DataService 5.6 in which the SendingRequest
event has been deprecated and replaced by SendingRequest2
.
Basically this meant changing the following event handler:
private void OnSendingRequest_AddCertificate(object sender, SendingRequestEventArgs args)
{
if (null != ClientCertificate)
{
((HttpWebRequest)args.Request).ClientCertificates.Add(ClientCertificate);
}
}
To:
private void OnSendingRequest_AddCertificate(object sender, SendingRequest2EventArgs args)
{
if (null != ClientCertificate)
{
((HttpWebRequestMessage)args.RequestMessage).HttpWebRequest.ClientCertificates.Add(ClientCertificate);
}
}
This seems to work. However now I get the following InvalidCastException
on some actions:
System.InvalidCastException: Unable to cast object of type 'System.Data.Services.Client.InternalODataRequestMessage' to type 'System.Data.Services.Client.HttpWebRequestMessage'.
I haven't been able to identify with 100% accuracy which actions these are, but it seems consistently on the SaveChanges method (see stacktrace below:)
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)
I came to the modification from SendingRequest
to SendingRequest2
by trial and error, so I wonder if I overlooked something there. Or is this completely unrelated and should I just add an && args.RequestMessage is HttpWebRequestMessage
to the if statement in the handler?
回答1:
Seems that you are sending a batch request. A batch request contains several internal requests which are InternalODataRequestMessage. SendingRequest2 will apply the OnSendingRequest action into both the $batch request and it's internal requests.
You can try following code
private void OnSendingRequest_AddCertificate(object sender, SendingRequest2EventArgs args)
{
if (null != ClientCertificate && !args.IsBatchPart)
{
((HttpWebRequestMessage)args.RequestMessage).HttpWebRequest.ClientCertificates.Add(ClientCertificate);
}
}
args.IsBatchPart returns true if this event is fired for request within a batch, otherwise returns false.
回答2:
It seems the problem occurs when I perform a batch operation.
I tried to dig through the InternalODataRequestMessage
to see if I could add client certificates to that somehow using reflection and the DataServices source. I found the instance of InternalODataRequestMessage
has a private member requestMessage
of type ODataBatchOperationRequestMessage
. By looking at the source code I couldn't any way to add a certificate.
What I did notice is that I can actually still use the deprecated SendingRequest
event just like before. So that's what I did and everything seems fine.
I feel like there should be a way to use a client certificate without using deprecated methods. So if someone has an answer that shows that, I'll accept that.
来源:https://stackoverflow.com/questions/21237052/how-to-solve-this-invalidcastexception-while-applying-clientcertificate-to-wcf-d