I’m calling a web service via WCF (w/ .NET 4.0) that requires basic HTTP authentication (with username and password.) over HTTPS. While, I think I’ve got everything setup correctly, I’m getting a 401 error whenever I make the call to the service. I monitored the HTTP traffic and noticed that WCF seems to be ignoring that I told it to use an authorization header with the username and password, as none is sent in the request. Here’s my configuration below. Any ideas? Thanks!
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicAuthSecured">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://REMOVED FOR CONFIDENTIALITY"
binding="basicHttpBinding" bindingConfiguration="BasicAuthSecured"
contract="Five9.WsAdmin" name="WsAdminPort" />
</client>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
And here’s my code:
var five_9_client = new WsAdminClient();
five_9_client.ClientCredentials.UserName.UserName = “REMOVED FOR CONFIDENTIALITY";
five_9_client.ClientCredentials.UserName.Password = "REMOVED FOR CONFIDENTIALITY";
var call_log_response = five_9_client.getCallLogReport(call_log); //Bombing out here
I’m getting this exception:
{"The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was ''."}
With inner exception:
{"The remote server returned an error: (401) Unauthorized."}
With stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest request, HttpWebResponse response, WebException responseException, HttpChannelFactory factory)
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory factory, WebException responseException, ChannelBinding channelBinding)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Found the solution: basically, the problem was that the header had to be attached to the current request, like so:
var base_64_encoded_credentials =
BasicHTTPAuthenticationEncoder.base_64_encode_credentials(
client.ClientCredentials.UserName.UserName, client.ClientCredentials.UserName.Password);
HttpRequestMessageProperty request = new HttpRequestMessageProperty();
request.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " + base_64_encoded_credentials;
OperationContextScope clientScope = new OperationContextScope(five_9_client.InnerChannel);
OperationContext.Current.OutgoingMessageProperties.Add(HttpRequestMessageProperty.Name, request);
It may be that the problem is that you have not set the client credential type, see http://msdn.microsoft.com/en-us/library/ms731925.aspx
Either it is not being sent at all, or the default client credential type does not send the credentials in the header.
Related
I am struggling with this WCF error for some time now without any luck. Basically I am tying to fetch an Entity Poco with Navigation Properties and connected objects via WCF Services. My EF v6 code successfully get the poco with all the related entities from the DB
Poco debug view
but as i try to access this Entity via WCF service, i see the following error -
An error occurred while receiving the HTTP response to http://localhost:8734/Design_Time_Addresses/BusinessLogicServicesLayer/userServices/. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at IuserServicesQuery.getCompleteUserSnapshot(String emailAddress)
at IuserServicesQueryClient.getCompleteUserSnapshot(String emailAddress)
Inner Exception:
The underlying connection was closed: An unexpected error occurred on a receive.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
Inner Exception:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
Inner Exception:
An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
my AppConfig file looks like this -
<endpoint address="" behaviorConfiguration="MyBehavior" binding="basicHttpBinding"
bindingConfiguration="IncreasedTimeout" name="BasicHttpEndpoint"
contract="BusinessLogicServicesLayer.IuserServicesQuery" listenUriMode="Explicit">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
&&
<bindings>
<basicHttpBinding>
<binding name="IncreasedTimeout"
openTimeout="12:00:00"
receiveTimeout="12:00:00" closeTimeout="12:00:00"
sendTimeout="12:00:00">
</binding>
</basicHttpBinding>
</bindings>
.
.
<behaviors>
<endpointBehaviors>
<behavior name="MyBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483646" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
can someone please help out or point me to a correct direction
This is because when data is returned, serialization fails, causing the WCF service to stop automatically.
Solution:
We can serialize the proxy class into the entities we need before returning the data.
Here is a demo,The student class contains the navigation properties of other entities:
public Student Getstu()
{
CodeFirstDBContext codeFirstDBContext = new CodeFirstDBContext();
Student student =codeFirstDBContext.Student.Find(1);
var serializer = new DataContractSerializer(typeof(Student), new DataContractSerializerSettings()
{
DataContractResolver = new ProxyDataContractResolver()
});
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, student);
stream.Seek(0, SeekOrigin.Begin);
var stu = (Student)serializer.ReadObject(stream);
return stu;
}
}
This is the method that the client will call.
ServiceReference1.ServiceClient serviceClient = new ServiceReference1.ServiceClient();
var stu = serviceClient.Getstu();
Client-side will call successfully.
UPDATE Disabling Loading loading also solves this problem:
public class CodeFirstDBContext : DbContext
{
public CodeFirstDBContext() : base("name=DBConn")
{
this.Configuration.ProxyCreationEnabled = false;
this.Configuration.LazyLoadingEnabled = false;
Database.SetInitializer(new CreateDatabaseIfNotExists<CodeFirstDBContext>());
}
}
I have a self hosted .Net 4.0 WCF service that I'm trying to convert from WsHttpBinding to NetTcpBinding for performance reasons. The service works just fine with the WsHttpBinding.
Strangely enough, The service seems to work after switching to NetTcpBinding. (The service posts messages to a enterprise messaging system, and the message is posted and the client receives no error) however the following error is written to the server log:
Error: Service: MessageSenderService, Details: System.ServiceModel.CommunicationException: The socket connection was aborted. This could be caused
by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue.
Local socket timeout was '10675199.02:48:05.4775807'. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.ServiceModel.Channels.SocketConnection.HandleReceiveAsyncCompleted()
at System.ServiceModel.Channels.SocketConnection.BeginReadCore(Int32 offset,Int32 size, TimeSpan timeout, WaitCallback callback, Object state)
--- End of inner exception stack trace ---
at System.ServiceModel.Channels.SocketConnection.BeginReadCore(Int32 offset,Int32 size, TimeSpan timeout, WaitCallback callback, Object state)
at System.ServiceModel.Channels.TracingConnection.BeginRead(Int32 offset, Int32 size, TimeSpan timeout, WaitCallback callback, Object state)
at System.ServiceModel.Channels.SessionConnectionReader.BeginReceive(TimeSpan timeout, WaitCallback callback, Object state)
at System.ServiceModel.Channels.SynchronizedMessageSource.ReceiveAsyncResult.PerformOperation(TimeSpan timeout)
at System.ServiceModel.Channels.SynchronizedMessageSource.SynchronizedAsyncResult`1..ctor(SynchronizedMessageSource syncSource, TimeSpan timeout, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.TransportDuplexSessionChannel.BeginReceive(TimeSpan timeout, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.TransportDuplexSessionChannel.TryReceiveAsyncResult..ctor(TransportDuplexSessionChannel channel, TimeSpan timeout, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.TransportDuplexSessionChannel.BeginTryReceive(TimeSpan timeout, AsyncCallback callback, Object state)
at System.ServiceModel.Dispatcher.ErrorHandlingReceiver.BeginTryReceive(TimeSpan timeout, AsyncCallback callback, Object state)
Again, no error occurs on the server log when using the WsHttpBinding.
Server Config:
<service behaviorConfiguration="debugEnabled" name="My.Service">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="netTcpBindingConfig"
contract="My.Service.Contract" />
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
....
<behaviors>
<serviceBehaviors>
<behavior name="debugEnabled">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling maxConcurrentSessions="200" maxConcurrentCalls="500" maxConcurrentInstances="200"/>
<serviceMetadata httpGetEnabled="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
</behaviors>
....
<bindings>
<netTcpBinding>
<binding name="netTcpBindingConfig" maxReceivedMessageSize="5242880" closeTimeout="00:01:00" receiveTimeout="00:01:00" sendTimeout="00:01:00" openTimeout="00:01:00">
<readerQuotas maxArrayLength="5242880" />
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
We build the client binding in code, not config. That looks like this:
return new NetTcpBinding(SecurityMode.None, reliableSessionEnabled)
{
MaxBufferPoolSize = Int32.MaxValue,
MaxReceivedMessageSize = Int32.MaxValue,
ReaderQuotas = new XmlDictionaryReaderQuotas
{
MaxArrayLength = Int32.MaxValue,
MaxDepth = Int32.MaxValue,
MaxStringContentLength = Int32.MaxValue
},
ReceiveTimeout = TimeSpan.FromMinutes(1.0),
CloseTimeout = TimeSpan.FromMinutes(1.0),
OpenTimeout = TimeSpan.FromMinutes(1.0),
SendTimeout = TimeSpan.FromMinutes(1.0)
};
Any ideas out there?
EDIT: I would like to add that I see the error on every call to the service, not only under load. The request and response messages are very small so it likely not related to message size. The error is written almost instantaneously, so it it not a timeout problem.
Fixed it.
As it turns out, I was not properly closing the client proxy. For whatever reason that didn't cause a problem with the WsHttpBinding, but with NetTcpBinding it caused that error.
After putting the client proxy in a using block the problem went away.
Despite many searches and read articles such as this: Exploring the WCF Named Pipe Binding - Part 1(part 2 and 3 inclusively), I haven't been able to make my service work properly.
Here's my config:
<system.serviceModel>
<client>
<endpoint address="net.pipe://localhost/GlobalPositioningService"
binding="netNamedPipeBinding"
contract="GI.Services.GlobalPositioning.Contracts.IGlobalPositioning" />
</client>
<services>
<service name="GI.Services.GlobalPositioning.Services.GlobalPositioningService">
<endpoint address=""
binding="wsHttpBinding"
contract="GI.Services.GlobalPositioning.Contracts.IGlobalPositioning">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="net.pipe://localhost/GlobalPositioningService"
binding="netNamedPipeBinding"
contract="GI.Services.GlobalPositioning.Contracts.IGlobalPositioning" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/GlobalPositioningService/"/>
</baseAddresses>
</host>
</service>
</services>
Then, I try to test my service through Named Pipes:
[TestFixture]
public class GlobalPositioningServiceTests {
[TestFixtureSetUp]
public void SetUpHost() {
var channelFactory = new ChannelFactory<IGlobalPositioning>(binding, new EndpointAddress(address));
channelFactory.Open();
service = channelFactory.CreateChannel();
}
private const string address = "net.pipe://localhost/GlobalPositioningService";
private static readonly Binding binding = new NetNamedPipeBinding();
private static IGlobalPositioning service;
}
And I have also tried another way using a ServiceHost instance:
[TestFixtureSetUp]
public void SetUpHost() {
host = new ServiceHost(typeof(GlobalPositioningService));
host.AddServiceEndpoint(typeof(IGlobalPositioning), binding, address);
host.Open();
service = new GlobalPositioningService();
}
And I always obtain this error with stack trace:
Error 2 Test 'GI.Services.GlobalPositioning.Services.Tests.GlobalPositioningServiceTests.GetGlobalPositionWorksWithDiacriticsInMunicipalityName("143, rue Marcotte, Sainte-Anne-de-la-P\x00E9rade",46.5736528d,-72.2021346d)' failed:
System.ServiceModel.EndpointNotFoundException : There was no endpoint listening at net.pipe://localhost/GlobalPositioningService that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
----> System.IO.PipeException : The pipe endpoint 'net.pipe://localhost/GlobalPositioningService' could not be found on your local machine.
Server stack trace:
at System.ServiceModel.Channels.PipeConnectionInitiator.GetPipeName(Uri uri)
at System.ServiceModel.Channels.NamedPipeConnectionPoolRegistry.NamedPipeConnectionPool.GetPoolKey(EndpointAddress address, Uri via)
at System.ServiceModel.Channels.CommunicationPool`2.TakeConnection(EndpointAddress address, Uri via, TimeSpan timeout, TKey& key)
at System.ServiceModel.Channels.ConnectionPoolHelper.EstablishConnection(TimeSpan timeout)
at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)
at System.ServiceModel.Channels.ServiceChannel.EnsureOpened(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at GI.Services.GlobalPositioning.Contracts.IGlobalPositioning.GetGlobalPosition(String mailingAddress)
at GI.Services.GlobalPositioning.Services.Tests.GlobalPositioningServiceTests.GetGlobalPositionWorksWithDiacriticsInMunicipalityName(String address, Double latitude, Double longitude) in C:\Open\Projects\Framework\Src\GI.Services\GI.Services.GlobalPositioning.Services.Tests\GlobalPositioningServiceTests.cs:line 27
--PipeException C:\Open\Projects\Framework\Src\GI.Services\GI.Services.GlobalPositioning.Services.Tests\GlobalPositioningServiceTests.cs 27
For your information, I'm using:
Visual Studio 2010
Windows 7
NUnit
And my service is contained within a WCF Service Library.
It seems that you are attempting to do integration testing with a running instance of your service using the netNamedPipesBinding. To do this, you need to have both a service host providing an instance of your service and a service proxy instance to use for making calls to the service. You could try combining both the code in both of your sample TestFixtureSetup methods so that you are instantiating both the service host and the service proxy (the result of the CreateChannel method). For an example of how to do this, look at this blog post.
Everything I've found so far says I should be able to use WCF to call a .asmx web service that uses WS-Security. The question is how to configure the WCF-Port. I'm using WCF-BasicHttp. First of all, is that okay? Second, how to enter the user/pass properly. On the security tab, which "Security Mode" should I pick?
The only one that seems to let me enter credentials is TransportWithMessageCredential, then I can click the "Edit" button by username credentials and enter a user/pass.
But when I did, I got this:
<soap:Fault xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<faultcode xmlns:q0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">q0:Security</faultcode>
<faultstring>Microsoft.Web.Services3.Security.SecurityFault: Security requirements are not satisfied because the security header is not present in the incoming message.
at Microsoft.Web.Services3.Design.UsernameOverTransportAssertion.ServiceInputFilter.ValidateMessageSecurity(SoapEnvelope envelope, Security security)
at MSB.RCTExpress.Presentation.Web.UsernameOverTransportAssertion.ServiceInputFilter.ValidateMessageSecurity(SoapEnvelope envelope, Security security)
in C:\projects\la1safe1\RCT Express\MSB.RCTExpress\3.10\Presentation.Web\UsernameOverTransportNoSendNone.cs:line 27
at Microsoft.Web.Services3.Security.ReceiveSecurityFilter.ProcessMessage(SoapEnvelope envelope)
at Microsoft.Web.Services3.Pipeline.ProcessInputMessage(SoapEnvelope envelope)
at Microsoft.Web.Services3.WseProtocol.FilterRequest(SoapEnvelope requestEnvelope)
at Microsoft.Web.Services3.WseProtocol.RouteRequest(SoapServerMessage message)
at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response)
at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)</faultstring>
<faultactor>http://rct3.msbexpress.net/demo/ExpressLync/ValuationService.asmx</faultactor>
</soap:Fault>
Any ideas?
Thanks,
Neal Walters
Follow-up to TomasR's post - using WS-HTTP binding:
1) BizTalk "Consume WCF Wizard" builds a custom binding file and a WS-BasicHTTP Binding file, so I changed SendPort, and manually copied over all the configurations.
Set as follows:
Security Mode: Message
Message Client Credential Type: UseName
Algorithm Suite: Basic256 [I had no idea what to put here]
I also checked two other boxes:
a) Negotiate service credential [if I don't check this, it wants a "thumbprint"]
b) Establish security context [also tried not checking this one]
2) Ran and got this error:
Description:
The adapter failed to transmit message going to send port "WcfSendPort_ValuationServicePort_ValuationServicePortSoap" with URL "http://rct3.msbexpress.net/demo/ExpressLync/ValuationService.asmx". It will be retransmitted after the retry interval specified for this Send Port.
Details:"System.NullReferenceException: Object reference not set to an instance of an object.
Server stack trace:
at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout)
at System.ServiceModel.Security.SspiNegotiationTokenProvider.OnOpen(TimeSpan timeout)
at System.ServiceModel.Security.TlsnegoTokenProvider.OnOpen(TimeSpan timeout)
at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Security.CommunicationObjectSecurityTokenProvider.Open(TimeSpan timeout)
at System.ServiceModel.Security.SecurityUtils.OpenTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout)
at System.ServiceModel.Security.SymmetricSecurityProtocol.OnOpen(TimeSpan timeout)
at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.ClientSecurityChannel`1.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.DoOperation(SecuritySessionOperation operation,
EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.GetTokenCore(TimeSpan timeout)
at System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionClientSettings`1.ClientSecuritySessionChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open()
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at System.ServiceModel.ICommunicationObject.Open()
at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfClient`2.GetChannel[TChannel](IBaseMessage bizTalkMessage,
ChannelFactory`1& cachedFactory)
at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfClient`2.SendMessage(IBaseMessage bizTalkMessage)".
Now tried custom binding, added user/pass and get this error:
<soap:Fault xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Code>
<soap:Value xmlns:q0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">q0:Security</soap:Value>
</soap:Code>
<soap:Reason>
<soap:Text xml:lang="en">Microsoft.Web.Services3.Security.SecurityFault:
Security requirements are not satisfied because the security header is not present in the incoming message.
at Microsoft.Web.Services3.Design.UsernameOverTransportAssertion.ServiceInputFilter.ValidateMessageSecurity(SoapEnvelope envelope,
Security security)
at MSB.RCTExpress.Presentation.Web.UsernameOverTransportAssertion.ServiceInputFilter.ValidateMessageSecurity
(SoapEnvelope envelope, Security security) in
C:\projects\la1safe1\RCT Express\MSB.RCTExpress\3.10\Presentation.Web\UsernameOverTransportNoSendNone.cs:line 27
at Microsoft.Web.Services3.Security.ReceiveSecurityFilter.ProcessMessage(SoapEnvelope envelope)
at Microsoft.Web.Services3.Pipeline.ProcessInputMessage(SoapEnvelope envelope)
at Microsoft.Web.Services3.WseProtocol.FilterRequest(SoapEnvelope requestEnvelope)
at Microsoft.Web.Services3.WseProtocol.RouteRequest(SoapServerMessage message)
at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response)
at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)</soap:Text>
</soap:Reason>
<soap:Node>http://rct3.msbexpress.net/demo/ExpressLync/ValuationService.asmx</soap:Node>
</soap:Fault>
My next attempt, went back to WS-HTTP, but tried to put the User/Pass in a message assignment rather than in the SendPort:
msgRCTGetRequest(SOAP.Username) = "myuser";
msgRCTGetRequest(SOAP.Password) = "mypass";
//msgRCTGetRequest(SOAP.UseSoap12) = true;
Resulted in this error:
<soap:Fault xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Code>
<soap:Value>soap:Sender</soap:Value>
</soap:Code><soap:Reason>
<soap:Text xml:lang="en">System.Web.Services.Protocols.SoapHeaderException: WSE012: The input was not a valid SOAP message because the following information is missing: action.
at Microsoft.Web.Services3.Utilities.AspNetHelper.SetDefaultAddressingProperties(SoapContext context, HttpContext httpContext)
at Microsoft.Web.Services3.WseProtocol.CreateRequestSoapContext(SoapEnvelope requestEnvelope)
at Microsoft.Web.Services3.WseProtocol.FilterRequest(SoapEnvelope requestEnvelope)
at Microsoft.Web.Services3.WseProtocol.RouteRequest(SoapServerMessage message)
at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response)
at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)</soap:Text>
</soap:Reason>
</soap:Fault>
Fifth attempt, about to give up and open a Microsoft ticket:
msgRCTGetRequest(WCF.UserName) = "myuser";
msgRCTGetRequest(WCF.Password) = "mypass";
msgRCTGetRequest(WCF.Action) = "GetPropertyInfoSourceRecordPolicyNum";
msgRCTGetRequest(SOAP.MethodName) = "GetPropertyInfoSourceRecordPolicyNum";
msgRCTGetRequest(SOAP.Username) = "myuser";
msgRCTGetRequest(SOAP.Password) = "mypass";
same error as fourth attempt.
According to the doc of the vendor providing the web service, I should put the user in W-Security UsernameToken element, the password in WS-Security password, and set the element's attribute to "PasswordDigest". It also says "This token should be added to the SOAP request for the Web method." I'm not sure how this translates from the old WSE3 days to the new WCF days.
Neal, for WS-Security, you need to use the WCF-WsHttp binding/Adapter. WCF-BasicHttp is only for the simpler scenarios where the WS-* protocols are not needed.
.NET 4.0 and .NET 3.5 SP1 with hotfix 971831 allow WS-Security over http transport. Try using this sample binding:
<customBinding>
<binding name="httpAndWSSecurity">
<security authenticationMode="UserNameOverTransport"
allowInsecureTransport="true"/>
<textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" />
<httpTransport/>
</binding>
Also see this MSDN article on SecurityBindingElement.AllowInsecureTransport
Use custom binding, and from the BizTalk send port, click configure, then go to the right-most tab which says "Import/Export". Paste the following XML into a file (sample.config) and then import it into the configuration port. This basically saves the time of manually typing a lot of stuff on the binding tab.
<configuration>
<system.serviceModel>
<client>
<endpoint
address="http://rct3.msbexpress.net/demo/ExpressLync/ValuationService.asmx"
binding="customBinding"
bindingConfiguration="ValuationServicePortSoap12"
contract="BizTalk"
name="WcfSendPort_ValuationServicePort_ValuationServicePortSoap12"/>
</client>
<bindings>
<customBinding>
<binding name="ValuationServicePortSoap12">
<security authenticationMode="UserNameOverTransport"
messageProtectionOrder="SignBeforeEncrypt"
includeTimestamp="true"
messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
requireDerivedKeys="false"
requireSignatureConfirmation="false"/>
<textMessageEncoding messageVersion="Soap11WSAddressingAugust2004"/>
<httpsTransport />
</binding>
</customBinding>
</bindings>
</system.serviceModel>
</configuration>
The above is not very intuitive (I'm still waiting for a link from Microsoft which describes this is more detail).
Then you still specify the user/pass on the credentials tab.
However, this caused a problem for us, in that the vendor's .asmx web service we were calling did not have IIS set to "requires SSL". Apparently, that is a requirement for this to work with WCF. In other words, it works fine with WSE3 calling .NET to .NET, but when trying to call WCF to .asmx, WCF has a slightly more stringent requirement.
Neal Walters
Whew! Ok… I solved my Wcf / Linq errors (and learned a lot – a series of blog posts will follow next weak). Now I need to deploy. We run on the Mosso / Rackspace cloud, and for the moment that environment runs in a partial trust environment.
To make it simple, I added a method to my Wcf service that does just about NOTHING.
public string Echo(string what)
{
return what;
}
I built it all, and shipped it to the test server with the following Web.Config (relevant section only)… yes, I will need to add security obviously before exposing the dangerous methods, but for now I jsut want the anonymous stuff running :)
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicAnonymous">
<security mode="None"/>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="FooBar.Backend.Web.Services.CoreDataWcfServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="FooBar.Backend.Web.Services.CoreDataWcfServiceBehavior"
name="FooBar.Backend.Web.Services.CoreDataWcfService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicAnonymous" contract="FooBar.Backend.Web.Services.ICoreDataWcfService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
<baseAddressPrefixFilters>
<add prefix="http://backend.FooBar.com"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
</system.serviceModel>
So, off I go to call it in the simplest way I can with a console application. i add the service reference and it adds fine. Then I call it (I took inactive code for brevity)…
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CoreWcfHarness.CoreDataServiceReference;
namespace CoreWcfHarness
{
class Program
{
static void Main(string[] args)
{
var context = new CoreDataWcfServiceClient();
var echoval = context.Echo("Hello World!");
Console.WriteLine(String.Format("{0}\n", echoval));
Console.ReadKey();
}
}
}
And blammo. I get hit with an exception.
System.ServiceModel.FaultException`1 was unhandled
Message="Request failed."
Source="mscorlib"
StackTrace:
Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at CoreWcfHarness.CoreDataServiceReference.ICoreDataWcfService.Echo(String what)
at CoreWcfHarness.CoreDataServiceReference.CoreDataWcfServiceClient.Echo(String what) in C:\PathToProject\corewcfharness\service references\coredataservicereference\reference.cs:line 1890
at CoreWcfHarness.Program.Main(String[] args) in C:\PathToProject\CoreWcfHarness\Program.cs:line 42
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext, String[] activationCustomData)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone()
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
This is about as simple as it gets. Anyone familiar with medium trust environments and / or good with a stack trace?
Thanks!
"Request Failed" could be a number of things.
It looks like the most probable reason is that the request is not reaching the server. You should check the server logs to make sure that the request is being sent to the correct place.