WCF rest service http to https error 404 - c#

I'm working with visual Studio 2015. I have a Xamarin Cross-Platfom's project.
My WCF Rest Service works fine with http. I tried to use HTTPS but I receive a "404 error not found" when I try to access my resource.
You will find below the configs files:
web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" />
</system.web>
<system.serviceModel>
<services>
<service name="PrototypeBHost.PrototypeB" behaviorConfiguration="ServiceBehaviour">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpTransportSecurity"
behaviorConfiguration="restfulBehavior"
contract="PrototypeBHost.IprototypeB" />
<endpoint contract="IMetadataExchange" binding="mexHttpsBinding" address="mex" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webHttpTransportSecurity">
<security mode="Transport" />
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="restfulBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false"/>
<!-- 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>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true" />
</system.webServer>
</configuration>
applicationhost.config
<site name="PrototypeBHost" id="2">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="c:\Users\Ludovic\Documents\Visual Studio 2015\Projects\PrototypeB\PrototypeBHost" />
</application>
<bindings>
<!-- <binding protocol="http" bindingInformation="*:9612:192.168.1.106" />
<binding protocol="http" bindingInformation="*:8023:localhost" />-->
<binding protocol="https" bindingInformation="*:9612:192.168.1.106" />
<binding protocol="https" bindingInformation="*:8023:localhost" />
</bindings>
</site>
I followed some tutorials about WCF Rest but I'm a little bit confused with the SSL certificat. Do I need it? How can I attach the ssl certificat to the WCF Rest Service? Did I miss something?
My_WCF_proprieties

I finally found where was the problem, the default certificate with IIS Express doesn't work and cause some trouble.
First, I delete one of the certificate, I use command prompt for VS2015
netsh http delete sslcert ipport=0.0.0.0:44300
after that
I add a self-signed certificate
netsh http add sslcert ipport=0.0.0.0:44300 certhash=fb02ea72ab7443604aa8frib298e43l751ce3606 appid={214124cd-d05b-4309-8p76-9caa44b2b74a}
the command to show all certificates
netsh http show sslcert > output.txt
and it works :)

Related

WCF Service stops working after 100 calls

I am facing an issue when working with my WCF service. I consumed my WCF service in a console application and it works fine till 100 requests (in a loop). But it stops working after 100 requests. I have already used
<serviceThrottling
maxConcurrentCalls="500"
maxConcurrentInstances="500"
maxConcurrentSessions="500"/>
in my config but it has not effect on this issue. I have closed the connection after every call to the service but still the issue persists.
Any help is highly appreciated.
Below is my web.config :
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<connectionStrings>
<add name="PriceGain" connectionString="Server=xyz.abc.com;Database=SomeDB;User Id=appuser;password=xxxxxxx;" providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<httpRuntime/>
</system.web>
<system.serviceModel>
<services>
<service name="AirGainUtilities.Service.Utilities" behaviorConfiguration="UtilitiesBehavior">
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
<endpoint address="http://192.168.1.1/AirGain.Utilities.Service/Utilities.svc" binding="basicHttpBinding" contract="AirGainUtilities.Service.IUtilities" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBinding" closeTimeout="00:10:00"
openTimeout="00:10:00" receiveTimeout="00:10:00"
sendTimeout="00:10:00" maxBufferPoolSize="2147483647"
maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="UtilitiesBehavior">
<!-- 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="true" />
<serviceThrottling
maxConcurrentCalls="5000"
maxConcurrentInstances="5000"
maxConcurrentSessions="5000"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
<add binding="basicHttpBinding" scheme="http" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="false" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true" />
<defaultDocument>
<files>
<add value="Utilities.svc" />
</files>
</defaultDocument>
</system.webServer>
</configuration>
Apparently, the problem was an open DB connection in the GetDestinationHotelId method in the Package Class. The DB connections were not closed due to an exception and after 100 open connections MAX CONNECTION POOL LIMIT was reached.
Really silly at my end :-(

WCF hosted on IIS express ssl enabled

I've been banging my head for a week now, I am trying to run a WCF service on IIS express and do a GET from the browser, everything works fine in HTTP, but the minute I try the HTTPS it fails with
HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
I have tried every single config file in stackoverflow answers I also tried this I know it is for IIS but I can't see why it is not working On IIS express. here my config file:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<behaviors>
<endpointBehaviors>
<behavior name="webHttpEnablingBehaviour">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="webHttpEnablingBehaviour">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service
name="ElasticSearchAPI.GetElasticService" behaviorConfiguration="webHttpEnablingBehaviour">
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
<endpoint address=""
binding="webHttpBinding"
bindingConfiguration="default"
contract="ElasticSearchAPI.IGetElasticService"
behaviorConfiguration="webHttpEnablingBehaviour">
</endpoint>
<endpoint address="other"
binding="basicHttpBinding"
bindingConfiguration="default"
contract="ElasticSearchAPI.IGetElasticService">
</endpoint>
</service>
</services>
<client />
<bindings>
<webHttpBinding>
<binding name="default" ></binding>
</webHttpBinding>
<basicHttpBinding>
<binding name="default" allowCookies="true"></binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<validation validateIntegratedModeConfiguration="false"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
I am sure I am missing something really silly, but I am really out of ideas, your help is much appreciated.
Update
I can get to my .svc with https but when i try a get from a browser or post from fiddler nothing is working
Use ServiceBehaviour like below-
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
</behavior>
This may help you.
In WCF Service Config file add following :
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
In client application config file add following :
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
This will allow you to host and access WCF service with HTTPS protocol.

Basic Authentication for WCF

I am trying to do a very basic but secure username/password authentication with wcf.
However when I look at the value of the ServiceSecurityContext.Current.PrimaryIdentity; it contains the credentials of my windows machine and claims it is authorised (even though I have not yet done any authorisation) instead of the username and password I provided to the service.
My web.config of the service is as follows
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- 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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WsHttpBindingConfig">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<protocolMapping>
<add binding="wsHttpBinding" scheme="http" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
and the app.config of the client app is as follows
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1" />
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/WcfSecuredService/Service1.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
contract="ServiceReference1.IService1" name="WSHttpBinding_IService1">
</endpoint>
</client>
</system.serviceModel>
</configuration>
I call the service with the following code
ServiceReference1.Service1Client clnt = new ServiceReference1.Service1Client();
clnt.ClientCredentials.UserName.UserName = "peter";
clnt.ClientCredentials.UserName.Password = "grr";
string result=clnt.GetSecuredData();
What am I doing wrong?
Please note that both the client app and the service are both running on the same machine. I do not know if the identity is that of the machine running the service or the one passed to it from the client as they are both the same credentials.....
I suppose the other question is possibly "How do I get the username and password that were passed to the service?"
I have worked this out now
I needed to create a custom validation class which I found here How to: Use a Custom User Name and Password Validator
I also needed to make a few changes to the web.config
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfService1Secure.Auth,WcfService1Secure" />
</serviceCredentials>
<!-- 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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WsHttpBindingConfig">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<protocolMapping>
<add binding="wsHttpBinding" scheme="https" bindingConfiguration="WsHttpBindingConfig" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
and the app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1" />
</basicHttpBinding>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost/WcfService1Secure/Service1.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
contract="ServiceReference1.IService1" name="WSHttpBinding_IService1" />
</client>
</system.serviceModel>
</configuration>
Now the user is validated on the request and the username is available using
ServiceSecurityContext.Current.PrimaryIdentity;
hi you should add a method that can accept login and password on your server side and store them in a variables or db
your method should look like this
ServiceReference1.Service1Client clnt = new ServiceReference1.Service1Client();
clnt.ClientCredentials.UserName.UserName = "peter";
clnt.ClientCredentials.UserName.Password = "grr";
clnt.SignUp(clnt);
or
clnt.SignUp(login,password);
what you are doing can work on a standalone application but not in a webcall
your call to method service will have something like
http://MyService/IMyContract/MyAction1
Hope this help
If you are using PerSession instance then you can call first Authenticate on server and on successful maintain a flag on server, subsequent call will check for the flag before executing. that means client need to make first call to Authenticate method and then only call other methods.
If not using PerSession instance you can create own proxy class for the server and while creating proxy instance accept LoginName/Password which it can pass in header on each call and on server side implement custom ServiceAuthorizationManager, it can retrieve credential from OperationContext.Current.IncomingMessageHeaders and validates it.

Wcf Endpoint and configuring challenge , please help a WCF newbie

I am new to WCF so please bear with me.
I have StudentData.svc.vb that implements 2 interfaces from the same IStudentData.vb
The 2 Interfaces are IStudentData and IHeartbeat
Heartbeat is a 1 way Operational Contract _
I am using IIS 7.5 to host this service
the web.config is
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" strict="false" explicit="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<bindings />
<client />
<behaviors>
<serviceBehaviors>
<behavior>
<!-- 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>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
<add binding="basicHttpBinding" scheme="http" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</
my app.config after creating the service reference is
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IStudentData" maxReceivedMessageSize="2147483647" />
<binding name="BasicHttpBinding_IHeartbeat" maxReceivedMessageSize="2147483647" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://www.ortho-sync.com:8080/StudentData.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IStudentData"
contract="oStudentData.IStudentData" name="BasicHttpBinding_IStudentData" />
<endpoint address="http://www.ortho-sync.com:8080/StudentData.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IHeartbeat"
contract="oStudentData.IHeartbeat" name="BasicHttpBinding_IHeartbeat" />
</client>
</system.serviceModel>
</configuration>
IStudentData has a class with a datamember of byte array that I am using to transfer an image.
If I use a small file it transfers and everything works
if I use a 1 meg image I get (413) Request Entity Too Large
I have played with the bindings and end points til I am blue in the face,
anyone please help.
Your service is picking up the default values for the bindings because you have not specified your own default basicHttpBinding or created an endpoint (in the service) that references your own basicHttpBinding.
You can make a binding configuration the default configuration for that binding by omitting the name attribute, like this:
<basicHttpBinding>
<binding maxReceivedMessageSize="2147483647" />
Alternatively, you can create an endpoint explicitly and set the binding configuration for that endpoint by using the bindingConfiguration attribute:
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IStudentData"
contract="oStudentData.IStudentData"
name="BasicHttpBinding_IStudentData" />
The second example assumes a binding configuration defined with a name of BasicHttpBinding_IStudentData.
You would use either of these in your service config file.

Why my WSDL still shows basic http binding with the location value of http?

I enabled https binding, but my WSDL has soap address of http. Any ideas why? Thanks!
<wsdl:service name="XXXX"><wsdl:port name="BasicHttpBinding_XXXXService" binding="i0:BasicHttpBinding_XXXService">
<soap:address location="http://dev-soa-app/XXXX/XXXX/XXXService.svc"/></wsdl:port>
</wsdl:service>
Here is my web.config file:
<?xml version="1.0"?>
<configuration>
<system.web>
<customErrors mode="Off"/>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<configProtectedData>
<providers>
<add name="ConnStrings" type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" keyContainerName="ConnStrings" cspProviderName="" useMachineContainer="true" useOAEP="false"/>
</providers>
</configProtectedData>
<connectionStrings configSource="ConnStrings\ConnStrings.config"/>
<system.serviceModel>
<services>
<service name="XXXXService">
<!-- Use a bindingNamespace to eliminate tempuri.org -->
<endpoint address="" name="XXXXService"
binding ="wsHttpBinding" bindingConfiguration="TransportSecurity"
bindingNamespace="WF.CT2.WebServices.XXXXService"
contract="WF.CT2.WebServices.XXXXService.SAMLService" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="TransportSecurity">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpsGetEnabled="true" httpGetEnabled ="false" />
<!-- 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>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
First of all, you should realize that the URL in the service element of the WSDL is only a hint. Your clients should not be depending on this being the correct address of the service.
Second, realize that if your service is hosted in IIS, then it is IIS which determines the address to place in that element, based on your bindings in IIS. I suspect that you have both HTTP and HTTPS enabled on the site hosting the service. You can usually switch this to just HTTPS by setting the "Require SSL" property on the SSL page in IIS Manager.
Remove httpGetEnabled ="false" from your Web.Config and keep httpsGetEnabled="true" as is (see below).
<serviceBehaviors>
<behavior>
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>

Categories