Wcf webservice not working after migration to https - c#

My react app was working fine when we were using wcf service over http. We decided to implement SSL for our website and now that service is not working. Tried many web config settings but its not working. Read many docs on microsoft site but can not solve this problem.
Webconfig
<bindings>
<webHttpBinding>
<binding name="largeMessage" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" closeTimeout="00:03:00" openTimeout="00:03:00" receiveTimeout="00:10:00" sendTimeout="00:03:00">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" />
<security mode="Transport"/>
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="Service.EService" behaviorConfiguration="serviceBehaviors">
<endpoint address="" contract="Service.IEService" binding="webHttpBinding" bindingConfiguration="largeMessage" behaviorConfiguration="web"></endpoint>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" bindingConfiguration="httpsBinding" />
</service>
</services>

Put httpsGetEnabled="true"
Making security mode="Transport"
3 Removing line endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" bindingConfiguration="httpsBinding" />
After making these changes I am now be able to get the service running on https.

Related

Could not find a base address that matches scheme net.tcp for the endpoint with binding NetTcpBinding. Base address schemes are [http]

I have this configuration for my WCF service which runs on IIS Express port number 50187. The service is hosted on IIS Express of Visual Studio 2017:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="QCConsumerBinding" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="50000000" maxBufferPoolSize="5242880" maxReceivedMessageSize="50000000" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="QCWCFService.QCService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="QCConsumerBinding" contract="QCWCFService.IQCService" />
</service>
<service name="QCWCFService.QCFinalService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="QCConsumerBinding" contract="QCWCFService.IQCFinalService" />
</service>
<service name="QCWCFService.CalibrationService">
<endpoint address="service" binding="netTcpBinding" contract="QCWCFService.ICalibrationService" />
<endpoint address="" binding="wsDualHttpBinding" contract="QCWCFService.ICalibrationService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8080/CalibrationService" />
<add baseAddress="http://localhost:8081/CalibrationService" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add scheme="http" binding="wsDualHttpBinding" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
But when I try to run the service it gives this exception:
System.InvalidOperationException: Could not find a base address that matches scheme net.tcp for the endpoint with binding NetTcpBinding. Registered base address schemes are [http].
While I have another application with the same configuration for Dual Http Binding which works perfectly
By default, The IIS express doesn’t support Net.tcp protocol.
The service endpoint with Nettcpbinding requires a base address based on NetTcp protocol.
<endpoint address="service" binding="netTcpBinding" contract="QCWCFService.ICalibrationService" />
Although we provide a Nettcp base address by using the Host Section, It won’t work. This is due to the fact IIS express use self-configuration to provide a base address to run the current project. The configuration of IIS express usually located in the .vs folder of the current Solution, called applicationhost.config
If we run this project in a console application with this configuration, it will work. Thereby we should provide one base address with Nettcp protocol. This can be completed in IIS.
1. Enable windows feature for net.tcp protocol.
2. Add Net.tcp support on the website.
3. Add net.tcp protocol in site binding module.
Please refer to the below for details of adding net.tcp protocol to a website.
WCF ContractFilter Mismatch when enabling Reliable Session
Feel free to let me know if the problem still exists.

Hosting WCF SOAP, and WCF REST service as Azure App Services

I am trying to host existing WCF service and a WCF REST service as a Azure App Services. I have used the Publish option from Visual studio like in the post Here
I am able to browse to the hosted URL for the WCF SOAP site and the WCF REST site, but when i add a service reference for the WCF SOAP site and call a method on it i get below error
Same with the WCF rest service when i call a REST method, i get 404 now found error.
There was no endpoint listening at https://wcfservice.azurewebsites.net/WebService.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
The remote server returned an error: (404) Not Found.
From the failed request log i.e w3svcxxxx log, it says the request https://WcfService:80/Webservice.svc 404 not found status.
For the WCF Rest Service
https://WcfService:80/RESTservice.svc/GetData 404 not found status.
Why is the service internally calling a https://WcfService:80, would this require an configuration to setup. Tried to search around to see if i could find any help around this but could not find much.
Also, i have another WCF site that i had deployed to the App Services, which is setup with a basicHttpBinding and this site worked fine and i was able to get data using it.
Below is the web.config setting on the web site, i am using wsHttpBinging for the WCF SOAP service
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WebServiceOnline">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="AjaxBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="WcfService.WebServiceOnline" behaviorConfiguration="WebServiceOnline">
<endpoint binding="wsHttpBinding" bindingName="wsSecurityByTransport" contract="WcfService.IWebServiceForOnline" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
<service name="WcfService.RESTService" behaviorConfiguration="WebServiceOnline">
<endpoint address="" binding="webHttpBinding" contract="WcfService.IRESTService" name="RunningBarbus.Services.RunningBarbusService" behaviorConfiguration="AjaxBehavior">
<identity>
<dns value="locahost" />
</identity>
</endpoint>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="wsSecurityByTransport">
<security mode="Transport">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services> <service name="WcfService.WebServiceOnline" behaviorConfiguration="WebServiceOnline">
<endpoint binding="wsHttpBinding" bindingName="wsSecurityByTransport" contract="WcfService.IWebServiceForOnline" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> <service name="WcfService.RESTService" behaviorConfiguration="WebServiceOnline">
<endpoint address="" binding="webHttpBinding" contract="WcfService.IRESTService" name="RunningBarbus.Services.RunningBarbusService" behaviorConfiguration="AjaxBehavior">
<identity>
<dns value="locahost" />
</identity>
</endpoint>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" /> </service> </services>
There may be an issue in the configuration file. We could expose the additional service endpoint for wshttpbinding.
Here is my configuration, and it works properly over Azure.
<system.serviceModel>
<services>
<service behaviorConfiguration="mybehavior" name="WcfService1.Service1">
<!--http, https are all configurated-->
<endpoint address="" binding="webHttpBinding" contract="WcfService1.IService1" behaviorConfiguration="webbev" bindingConfiguration="mybinding"></endpoint>
<endpoint address="" binding="webHttpBinding" contract="WcfService1.IService1" behaviorConfiguration="webbev" bindingConfiguration="com"></endpoint>
<endpoint address="myservice" binding="wsHttpBinding" contract="WcfService1.IService1"></endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"></endpoint>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="mybinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" sendTimeout="00:10:00" receiveTimeout="00:10:00">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" />
<security mode="Transport">
<transport clientCredentialType="None"></transport>
</security>
</binding>
<binding name="com">
<security mode="None"></security>
</binding>
</webHttpBinding>
</bindings>
Result
Feel free to let me know if there is anything I can help with.

WCF Site with multiple services and contracts

I am running into an issue trying to host two services on the same site. They have the same base uri, but different services names, and each has its own contract.
While testing in my VS environment (IIS 7.5) everything works fine. However when I deploy to a server (IIS 8.5), both uri's are showing the same wsdl for some reason. It seems like the contract for the second service is ignored.
There are two different .svc files with code behind. (all names have been changed to protect the innocent.)
sites:
https://mysite/services/Service1.svc
https://mysite/services/Service2.svc
Here is my config:
<services>
<service name="Service1" behaviorConfiguration="DefaultBehavior">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="DefaultBinding" contract="Namespace.IService1"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
<service name="Service2" behaviorConfiguration="DefaultBehavior">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="DefaultBinding" contract="Namespace.IService2"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="DefaultBinding" receiveTimeout="00:05:00"
sendTimeout="00:05:00" bypassProxyOnLocal="false" transactionFlow="false"
hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647" messageEncoding="Mtom"
textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<reliableSession ordered="true" inactivityTimeout="00:5:00" enabled="false"/>
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
<wsHttpBinding>
<bindings>
<serviceBehaviors>
<behavior name="DefaultBehavior">
<serviceMetadata httpsGetEnabled="true" httpsGetBindingConfiguration="true" />
<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
<serviceThrottling maxConcurrentCalls="160" maxConcurrentInstances="160" maxConcurrentSessions="100" />
</behavior>
</serviceBehaviors>
The problem is that both sites are reflecting the same WSDL, i.e. same methods for contract="Namespace.IService1" Any ideas on what is going on here to cause this?
I believe the problem is because they both have the same address.
How can the server distinguish if your intent is to call Service1 or Service2?
While keeping the same base URI try to change their address
Unfortunately, WCF doesn't really have a good way to handle this use case. You can't have two contracts on the same endpoint
The address for the endpoint for Service1
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="DefaultBinding" contract="Namespace.IService1"/>
The address must be different from that of Service2
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="DefaultBinding" contract="Namespace.IService2"/>
It actually turned out to be something stupid, an xcopy error. My xcopy script for the new additional service was copied and pasted from the original service, but I forgot to rename the .svc source to the new service name. So it copied the same .svc to two different files.

WCF http binding error: The content type text/html does not match the content type of the binding (text/xml; charset=utf-8)

I have a WPF client which consumes a WCF service which is self hosted in a Winforms app. The client is accessing the service server via a VPN connection. At first initialisation, the client app catches an exception from the service:
There was a problem reaching the service.
The content type of text/html of the response message does not match the content type of the binding (text/xml;charset=utf-8).
If using a custom encoder, be sure that the IsContentTypeSupported method is
implemented properly.
The service is running without issue and this issue only appears when connecting via VPN, not from my Visual Studio development environment which is on the same domain as the service VM:
This exception only occurs on first initialisation, when I run the client app again, the issue is resolved & everything runs as expected. Here is my service app config:
<services>
<service name="IsesService.IsesService">
<endpoint address="" binding="basicHttpBinding" contract="IsesService.IIsesService" bindingConfiguration="basicHttp">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://EMEA-DIIS01v:8082"/>
</baseAddresses>
</host>
</service>
</services>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
<dataContractSerializer maxItemsInObjectGraph="2147483646" />
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
<bindings>
<basicHttpBinding>
<binding name="basicHttp"
useDefaultWebProxy="false"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647"
>
<readerQuotas maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647"/>
</binding>
</basicHttpBinding>
</bindings>
And client side:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IIsesService" useDefaultWebProxy="false"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647">
<readerQuotas maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647"/>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://emea-diis01v:8082/" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IIsesService" contract="ServiceReference.IIsesService"
name="BasicHttpBinding_IIsesService" />
</client>
</system.serviceModel>
Am I missing something simple here?
Check with fiddler what is the content of the first response.
It is probably different when you use VPN.

Delegate IIS Application Pool account to WCF service calls

I have developed a WCF service which is running in IIS (IIS 7.5 to be exact). This service runs under its own app pool, under a specific domain identity. This service references & calls other WCF services hosted elsewhere in the network, which in turn access various resources (Event Log, SQL Servers etc).
Calls to my service are authenticated using username & password, through a custom UserNamePasswordValidator. The username(s) used are not domain credentials.
What I'm trying to do, is that when my service is called & it in turn calls the referenced services using the generated proxy classes, that it delegates the application pool identity as the calling identity, since this domain account has been granted rights to access the background resources like SQL Server.
My current implementation is as follows:
Service Configuration
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="RemoteServiceBinding" closeTimeout="00:10:00"
openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="MyServiceBinding" closeTimeout="00:10:00" openTimeout="00:10:00"
receiveTimeout="00:10:00" sendTimeout="00:10:00" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" />
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://remote.service.address/Service.svc"
binding="basicHttpBinding" bindingConfiguration="RemoteServiceBinding"
contract="RemoteService.IRemoteService" name="RemoteServiceBinding" />
</client>
<services>
<service name="MyService.MyService" behaviorConfiguration="MyServiceBehavior">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="MyServiceBinding" contract="MyService.IMyService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/MyService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="None" />
</clientCertificate>
<serviceCertificate findValue="AuthCert" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyService.CredentialValidator, MyService" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Service behavior code
using (var client = new Proxy.RemoteServiceClient()) {
client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;
return client.PerformAction();
}
Using this code, whenever a client makes a call to my service, the following is thrown:
The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate,NTLM'.
Could someone please assist me, or point me in the right direction on how to implement this authentication configuration?
I've managed to find a working solution. It is implemented as such:
The client proxy credentials need to be set to those of the IIS Application Pool, since these don't get picked up automatically:
client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
Also, the remote service I was connecting to had a service principal that needed to be included in the endpoint configuration. So I modified the config that was generated by the VS tooling to the following:
<client>
<endpoint address="http://remote.service.address/Service.svc"
binding="basicHttpBinding" bindingConfiguration="RemoteServiceBinding"
contract="RemoteService.IRemoteService" name="RemoteServiceBinding">
<identity>
<servicePrincipalName value="spn_name" />
</identity>
</endpoint>
</client>
With this configuration, I was able to authenticate to my service by username & password, then have my service access a SQL Server instance using the domain credentials that the application pool was running under in IIS.

Categories

Resources