I have a WCF REST service using the webHttpBinding, and I am having some trouble getting it to work in a test environment behind an F5 load balancer - at least I believe the load balancer is an issue.
The service has been proven to run and operate locally using either http or https ("works on my machine"). The service is hosted in the same site that is consuming it.
Our test environment sits behind an F5 load balancer, which terminates SSL and forwards the request to server over http. Our IT staff has indicated that all incoming traffic to the test environment is http, and maintains that the site is configured with both http and https bindings in IIS. The only apparent difference between my local machine and the test environment is that my local machine is IIS 8 and the test environment is IIS 7.5.
The routes are registered like this:
RouteTable.Routes.Add(new ServiceRoute("REST/stuff", new WebServiceHostFactory(), typeof(StuffService)));
Currently, this is the relevant config that works locally:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true">
<security mode="Transport"/>
</standardEndpoint>
</webHttpEndpoint>
</standardEndpoints>
<bindings>
<webHttpBinding>
<binding>
<security mode="Transport"/>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
Initially, this service was deployed to the test environment without SSL, and I received this error when accessing a page that utilized the service:
Mixed Content: The page at 'https://foo.bar.com/thing.aspx' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://foo.bar.com/REST/stuff/'. This request has been blocked; the content must be served over HTTPS.
That seems mysterious to me now, since the site was accessed over https, and the call to the service was using a relative URL. Unfortunately, I cannot debug this now since I changed the configuration.
At the time I received the error above, I did not know about the F5, and figured that all I needed to do was to configure my service to use transport security, as in the above configuration. After changing configuration to use transport security, the service fails to activate in the test environment, initiating this error on the server:
The service '/REST/stuff' cannot be activated due to an exception during compilation. The exception message is: Could not find a base address that matches scheme https for the endpoint with binding WebHttpBinding. Registered base address schemes are [http].
This, I believe, indicates that the service is expecting to operate using https, but the lack of https in registered base address schemes is preventing that, so the service cannot initialize at all. I understand that this may happen when the https binding is missing in IIS (though IT maintains it is not).
I am not sure what else I can do to enable my use case. Any help is greatly appreciated!
My config was fine. For some reason, when interacting through the load-balancer the client side was not using https when using relative URIs to call services. More information on what I believe to be my problem here: How to use HTTPS in AngularJS
Related
I am trying to host a WCF Service Library on IIS 10, with a self signed SSL.
To Obtain Minimum Complete Verifiable Example, Open Visual studio 2017
New>Project>C#>Web>WCFLibrary With this you will get a simple code that has one operation contract which takes an integer and returns a string.
Now I am trying to host this on IIS with Self Signed SSL (Mine has more operation contract but this will do).
What I have tried so far.
Now the next part is hosting it on IIS, so I created the SVC file
My SVC file contains ->
<%# ServiceHost Language = "C#" Debug = "true" Service = "WcfServiceLibrary2.Service1" %>
Then all the tutorials that I can find edit Web.Config, which is unavailable in Visual Studio 2017, so I tried two things
1. Created a Web.Config file and added the configurations
2. Published the website and then obtained Web.Config which did not require any changes
Then I went on to IIS (as administrator) and added a new website
Then while trying to browse, to see the message that IIS service is hosted I got this error "Cannot read configuration file" To Solve this I followed success.trendmicro.com/…
Now that error is gone but now I am getting
To solve this I Followed
IIS - 401.3 - Unauthorized But this lead to the browser letting me browse the directories rather than giving the message that a Service has been created.
Any Idea what I am missing here?
Definitely I am missing something major here as I have failed to host it on HTTP itself, All the tutorials I find online have a file Web.Config and not App.config, I am looking for an example (preferably with Images) that demonstrate it just with this small example.
I know this doesn't follow all SO guidelines on asking questions, but I have failed to articulate it into a question that does.
Edit
As per LexLi's advice that it may already be hosted, I went and tried to consume it using svcutil which gave me the error
WS-Metadata Exchange Error
URI: http://localhost/Service1.svc
Metadata contains a reference that cannot be resolved: 'http://localhost/Service1.svc'.
The remote server returned an unexpected response: (405) Method Not Allowed.
The remote server returned an error: (405) Method Not Allowed.
HTTP GET Error
URI: http://localhost/Service1.svc
There was an error downloading 'http://localhost/Service1.svc'.
The request failed with HTTP status 404: Not Found.
The Url is correct because I obtained it by using the browse functionality from IIS.
First, please don’t set the IIS physic path to desktop, which will cause the permission problem. we could set the IIS site physical path to the folder under C partition.
Second, please read the following link, which mainly indicates that WCF service library project could not published directly to IIS since its Appconfig could not be recognized by IIS unless additional Webconfig is added manually in the root directory of the web site.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/deploying-a-wcf-library-project
Generally speaking, we use the WCF service project template which contains an auto-generated Webconfig file instead of WCF service library project template, since it is generally used as a class library.
By default, the service is hosted with BasicHttpBinding, it depends on the following tag.
<protocolMapping>
<add binding="basicHttpBinding" scheme="http" />
</protocolMapping>
The service could also be configured manually by the following ways. These two ways configuration file is equivalent.
<system.serviceModel>
<services>
<service name="WcfService1.Service1" behaviorConfiguration="mybehavior">
<endpoint address="" binding="basicHttpBinding" contract="WcfService1.IService1" bindingConfiguration="mybinding"></endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="mybinding">
<security mode="None">
</security>
</binding>
</basicHttpBinding>
</bindings>
It is unnecessary to assign the service endpoing address in the webconfig. It should be completed in the IIS site binding module.
WCF System.ServiceModel.EndpointNotFoundException
At last, we could host the service over https by adding an additional service endpoint, refer to the following configuration(simplified configuration).
<protocolMapping>
<add binding="basicHttpBinding" scheme="http"/>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
then add the https protocol in IIS site binding module.
Configuring Web.config to publish WCF Service
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-an-iis-hosted-wcf-service-with-ssl
Feel free to let me know if there is anything I can help with.
First Credit where credit is due, many of the issues I was pointed in the right direction by multiple SO users to name a few would be: Mikael bolinder, Abraham Qian, Lex Li, the wonderful people in the C# chat room and a co-worker of mine(Doesn't have an account on SO as of writing this answer), In this answer I plan to cover everything you might need to host a WCF Library in IIS Server using HTTPS security.
Tools I used:
Visual Studio 2017 professional
IIS 10 (Comes with windows 10 but has to be activated in windows features ) (See below)
First:
Make sure you have all the components you will need from visual studio installed.
Windows -> .Net Desktop Development
Windows -> Universal Windows platfor development
Web & Cloud -> ASP.NET and web development
In this list and among other list that will come, some extra components may be included, the reason for that is I installed them and couldn't verify one way or the another if they are absolutely necessary.
Now, let's add the windows features necessary. Control Panel -> Programs -> Turn Windows features on or off
Make sure to go into WCF Services and check HTTP Activation, don't be fooled by the square block (One of my mistakes)
Now let's get to creating the Service. Open Visual Studio File -> New -> Project -> Visual C# -> Web -> WCF -> WCF Service Library This generates the MCVE that you are trying to host
Now you have to link it with a website in order to generate the Web.Config file along with the SVC file, to do that, On Solutions Explorer, right click on your solution, Add-> New Website.
Now in the web.config file add
<system.serviceModel>
<services>
<service name="WcfServiceLibrary4.Service1"> <!-- Change the library name as per your need -->
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="WcfServiceLibrary4.IService1"/> <!-- Change the library name as per your need -->
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
</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"/>
<!-- 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>
Next add reference to service on the website
Discover services and add the service you have created. Now Build your solution and publish it. **Careful Don't publish the solution in a user Directory like Desktop or documents or else ACL permissions will give you a headache, rather publish it directly in a directory in Drive.
Now Hosting time
First lets open IIS (Always as admin) and create a new certificate.
On the server go to the IIS part and Select Server Certificates, then click create new certificate on the right end.
Now create a new website from the left menu
Make sure to switch to https and select your certificate here, Now to verify that your service is created you will need to browse your websites svc file created, sadly at this point you will get an error saying Server Error in '/' Application.
Could not find a base address that matches scheme http for the endpoint with binding BasicHttpBinding. Registered base address schemes are [https]. I was unable to find the cause of the error, but I was able to find a bypass of it,
Steps to bypass this error -> Select you website from the menu on the left, on the menu at the right click bindings and also add an HTTP binding, with a different port.
After this you will be able to browse the HTTPS version of your svc file.
Now if you browse the HTTPS link you get the message that the service is created
Now you can go Ahead and create an application that consumes this service.
What lies ahead
I will try to find a way to do this without adding an additional binding
The Second goal would be to achieve this without adding the extra website.
If and when I achieve these I will update, however these are not my priority right now and may not be added for quite a while, if anything didn't make sense, or you have any ideas of improvement comment below.
In short here are the steps :
Create Self-Signed Certificate
Add SSL Binding
Configure Virtual Directory for SSL
Configure WCF Service for HTTP Transport Security
This link is more in depth : https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-an-iis-hosted-wcf-service-with-ssl
I'm getting the following exception The operation has timed out when calling my WCF REST service.
I basically have a WCF Web Service project and a web site which references the compiled WCF assembly. The web service works a charm, so my problem is not down to having an incorrect binding, endpoint or service definition in my web.config.
The problem only occurs if I try to insert a large amount of data.
The web.config contains the following info:
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<httpRuntime enable="true" executionTimeout="100000"
maxRequestLength="2147483647"/>
</system.web>
<bindings>
<webHttpBinding>
<binding maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
receiveTimeout="00:10:00"
sendTimeout="00:10:00">
<readerQuotas maxStringContentLength="2147483647"/>
</binding>
</webHttpBinding>
</bindings>
My WCF web service is not referenced in the the project (windows service) as I'm using a wrapper (sdk) which takes care of making all the relevant http request and convert object to json and vice versa. All http request are made via the WebClient which is called the sdk. In this instance:
byte[] returnBuffer = await client.UploadDataTaskAsync(uriString,
"POST", requestBuffer);
While this is happening on a live site (Yikes!!), I can easily reproduce the problem by putting a breakpoint in my web service and letting it hang for 90 seconds or so, then if I try to continue stepping through, the specific error is generated and while it's attempting to continue to run the remaining of the code within the function, the exception is returned back to the client.
I've been googling this problem for hours now but I'm not getting anywhere with this. My web service still times out the default 90 seconds.
Another thing I'm wondering about. I've been reading a lot of various article saying mentioning that the client app, in my case my windows service should have binding, endpoint, etc... information in the app.config. I have none, nor have I ever needed one up to now. Should I look into this?? It really does appear that the timeout is happening on the web service rather than the client end.
Any ideas?
Thanks.
UPDATE:
I've added additional info about my web.config (i.e. service & behaviour definitions):
<services>
<service name="MyCompany.Web.Services.WebDataService"
behaviorConfiguration="WebDataServiceBehaviour">
<endpoint address="" binding="webHttpBinding"
contract="MyCompany.Web.Services.IWebDataService"
behaviorConfiguration="webBehaviour">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WebDataServiceBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webBehaviour">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
I would say this was due to a client-side timeout setting. Do you have a client-side config or some other way to configure the wrapper?
It's hard to say as I don't quite know how your wrapper works but you would want to increase the timeouts on your bindings. e.g.
<binding openTimeout="00:10:00"
closeTimeout="00:10:00"
sendTimeout="00:10:00"
receiveTimeout="00:10:00">
See here for more details
I'm going to answer my own question as I wanted to clarify a few things:
This has nothing to do with having invalid settings in the web.config as the problem was client-side related. It is easy to assume that the problem is server side related but this was not the case in this instance.
There is no point setting the ServiceModel (address, binding, contract) configuration in the app.config on the client-side as I'm calling the WebClient object which as far I'm aware is totally unaware of type of service I'm calling and these settings are quite specific to WCF and while my service is a WCF REST web service and does require a ServiceModel settings on the server end, the WebClient object is totally unaware of these.
The answer to my problem was found in the article How can I change the time limit for webClient.UploadData()?. After making the relevant changes, I test this thoroughly and it's also been deployed on the live site that were having the timeout problem and the problem has definitely been resolved when uploading a large amount of data.
Thanks.
I'm building an ASP.NET website - it's a solution with a few projects, a data base and a web service. Everything worked fine, but last time I tried to run the project, I got the following error:
There was no endpoint listening at http://localhost:[number]/BooksWS.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 inner exception says:
Unable to connect to the remote server
This error sort of came out of the blue, so I'm not sure what additional information I should provide. Does anyone have any idea why this could happen?
I suppose even a general answer could help, the only info I found about this error in the web concerned WCF.
go to webconfig page of your site, look for the tag endpoint, and check the port in the address attribute, maybe there was a change in the port number
Another case I just had - when the request size is bigger than the request size set in IIS as a limit, then you can get that error too.
Check the IIS request limit and increase it if it's lower than you need.
Here is how you can check and change the IIS request limit:
Open the IIS
Click your site and/or your mapped application
Click on Feature view and click Request Filtering
Click - Edit Feature Settings.
I just found also another thread in stack
IIS 7.5 hosted WCF service throws EndpointNotFoundException with 404 only for large requests
An another possible case is make sure that you have installed WCF Activation feature.
Go to Server Manager > Features > Add Features
I had this problem when I was trying to call a WCF service hosted in a new server from a windows application from my local. I was getting same error message and at end had this "No connection could be made because the target machine actively refused it 127.0.0.1:8888". I donot know whether I am wrong or correct but I feel whenever the server was getting request from my windows application it is routing to something else. So I did some reading and added below in Web.config of service host project. After that everything worked like a magic.
<system.net>
<defaultProxy enabled="false">
</defaultProxy>
</system.net>
Short answer but did you have Skype open? This interferes specifically with ASP.NET by default (and localhosts in general) using port:80.
In Windows: Go to Tools -> Options -> Advanced -> Connection and uncheck the box "use port 80 and 443 as alternatives for incoming connections".
Try this:
Delete the service instance.
Create a new instance of the service.
Sometimes the port is changed and generated error.
I tried a bunch of these ideas to get HTTPS working, but the key for me was adding the protocol mapping. Here's what my server config file looks like, this works for both HTTP and HTTPS client connections:
<system.serviceModel>
<protocolMapping>
<add scheme="https" binding="wsHttpBinding" bindingConfiguration="TransportSecurityBinding" />
</protocolMapping>
<services>
<service name="FeatureService" behaviorConfiguration="HttpsBehavior">
<endpoint address="soap" binding="wsHttpBinding" contract="MyServices.IFeature" bindingConfiguration="TransportSecurityBinding" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="HttpsBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="TransportSecurityBinding" maxReceivedMessageSize="2147483647">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
If you are using custom binding, please make sure that you are putting the same name for both custom binding (Server and Client)in config files
<bindings>
<customBinding>
<binding name="BufferedHttpServerNoAuth" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00">
<gzipMessageEncoding innerMessageEncoding="textMessageEncoding" MaxArrayLength="10485760" MaxBytesPerRead="31457280" MaxStringContentLength="102400000" />
<httpsTransport hostNameComparisonMode="StrongWildcard" manualAddressing="False" maxReceivedMessageSize="31457280" authenticationScheme="Anonymous" bypassProxyOnLocal="True" realm="" useDefaultWebProxy="False" />
</binding>
</customBinding>
</bindings>
the binding name "BufferedHttpServerNoAuth" should be same in both.
Hope this would help someone
This is ancient history but I just ran into this issue and the fix for me was recycling the application pool of the website in IIS. Easy fix, for once.
I changed my website and app bindings to a new port and it worked for me. This error might occur because the port the website uses is not available. Hence sometimes the problem is solved by simply restarting the machine
-Edit-
Alternative (and easier) solution:reference
Get PID of process which is using the port
CMD command-
netstat -aon | findstr 0.0:80
Use the PID to get process name -
tasklist /FI "PID eq "
Open task manager, find this process and stop it.
(Note- Make sure you do not stop Net.tcp services)
I solved it by passing the binding with endpoint.
"http://abcd.net/SampleFileService.svc/basicHttpWSSecurity"
Click on Service which you have created right click on it then select update references after this rebuild the application it will work
I have a wcf application. It has "Service1.svc" file. In the web.config file I specified
http://localhost:2005/EmployeeService.svc
as an endpoint. When clicking browse from Visual Studio there is no problem. But, when I hosted it on IIS server I get a blank page. The interesting thing is, If I remove the address from the web. config this time I can see the service at this address.
http://localhost:2005/EmployeeService.svc
web.config file is as below:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="EmployeeServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="EmployeeServiceBehaviour" name="EmployeeConfiguration">
<endpoint address="http://localhost:2005/EmployeeService.svc" binding="basicHttpBinding"
bindingConfiguration="" contract="IEmployeeConfiguration" />
</service>
</services>
</system.serviceModel>
<system.web>
<compilation debug="true"/>
</system.web>
<system.webServer>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
Could you please explain, why I get a blank page on IIS when I provide the adress.
This may happen in HTTP Activation is not installed in Programs and Features in your Windows installation. Check HTTP Activation for both .Net 3.5 and 4.6 to enable opening WCF service via HTTP request to .svc file hosted in IIS.
I think you can remove all text on the address before Service.svc. This might be an issue with different urls.
When you specify the address part, you tell WCF the service is only available on that address. When going through the endpoints, WCF will not find one that matches the given URL and bail out.
When you have multiple endpoints you need the address field. Otherwise you don't.
Read http://msdn.microsoft.com/en-us/library/ms733749(v=vs.110).aspx
And in particular this part:
When hosting with IIS, you do not manage the ServiceHost instance yourself. The base address is always the address specified in the .svc file for the service when hosting in IIS. So you must use relative endpoint addresses for IIS-hosted service endpoints. Supplying a fully-qualified endpoint address can lead to errors in the deployment of the service.
Check if Service attribute in SVC markup equals your implementation class.
Check endpoint contract name. It has to be exactly full name of your interface. Don't add assembly name, it won't work.
Check <serviceMetadata httpGetEnabled="true" />. If false, you get blank page too.
And 4th change which helped me (but I have no idea why): Remove behavior name <behavior name=""> and remove behaviorConfiguration attribute from service element. It becomes default so the behavior will be used anyway.
Be sure you made an Application Pool with active user like this: https://stackoverflow.com/a/19654633/2148387
Be sure you created Web Application where your WCF is hosted
Check if AppPool and WebApp are running
Enable Directory Browse in your Web.config like here: https://stackoverflow.com/a/19630263/2148387
I've been battling with this for days, literally going through a hundred articles giving partial guidelines on how to set up a WCF TCP based service in a web application. If someone can help me, I will make this question into a complete guideline.
Current status
The net.tcp connection works on my development machine. It also works locally after being deployed to a Windows Server 2008 R2. However, it doesn't work remotely, even though it's possible to telnet to port 808 on the server remotely. Scroll to the bottom of the question for details. Please help if you can.
I will create a new question for this detail and update this question with the answer if I get a result out of it.
Code
I created ServerHubService.svc with the following content:
namespace Manage.SignalR
{
[ServiceContract]
public class ServerHubService
{
[OperationContract]
public void UpdateServerStatus(string serverStatus)
{
// Do something
}
}
}
Configuration of the application hosting the service
Following an online tutorial, I added the following to my Web.config (I tried MANY different variations). This is the Web.config of the web application hosting the service that I later want to connect to with TCP.
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration="ServerHubBehavior"
name="Manage.SignalR.ServerHubService">
<endpoint address=""
binding="netTcpBinding"
bindingConfiguration="portSharingBinding"
name="MyServiceEndpoint"
contract="Manage.SignalR.ServerHubService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex"
binding="mexTcpBinding"
bindingConfiguration=""
name="MyServiceMexTcpBidingEndpoint"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://test.mydomain.com:808/SignalR/ServerHubService.svc" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServerHubBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="portSharingBinding" portSharingEnabled="true"/>
</netTcpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
minFreeMemoryPercentageToActivateService="0" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</configuration>
httpGetEnabled="true" is important because otherwise you cannot create a service reference to the service.
Configuration of the server where the web application is running
I am setting this up on my development machine which has IIS 7.5
I read that IIS Express (built into Visual Studio) doesn't support net.tcp, so I set up a new website in IIS 7.5 using .NET 4.5 and that has a net.tcp binding
I also went to Advanced Settings for the website and set Enabled Protocols to http,net.tcp
I ensured that the Windows Feature Non-HTTP Activation is enabled (and restarted). It's a Windows Feature so look for "Turn Windows features on or off" to find this.
Confirming the web application is running
The website works fine for the rest of the web application. I set up test.mydomain.com to point to 127.0.0.1 in my hosts file. I can even visit http://test.mydomain.com/SignalR/ServerHubService.svc and it will show me a nice auto generated page from .NET, explaining how to use this service.
So far so good.
The page generated by .NET tells me to use this address to generate a connection to my service:
net.tcp://computername/SignalR/ServerHubService.svc/mex
Trying to connect to the service as a client
If you do not remember to set httpGetEnabled="true" you will get an error when trying to create a service reference to it. If you use the WCF Test Client (also a tool included in Visual Studio) and didn't set httpGetEnabled, you will get an error like the following:
Error: Cannot obtain Metadata from
net.tcp://computername/SignalR/ServerHubService.svc/mex
If this is a Windows (R) Communication Foundation service to which you
have access, please check that you have enabled metadata publishing at
the specified address. For help enabling metadata publishing, please
refer to the MSDN documentation at
http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata
Exchange Error URI:
net.tcp://computername/SignalR/ServerHubService.svc/mex Metadata
contains a reference that cannot be resolved:
'net.tcp://computername/SignalR/ServerHubService.svc/mex'. Could not
connect to net.tcp://computername/SignalR/ServerHubService.svc/mex.
The connection attempt lasted for a time span of 00:00:04.0032289.
TCP error code 10061: No connection could be made because the target
machine actively refused it [2001:0:4137:9e76:c81:a4c:a547:b2fd]:808.
No connection could be made because the target machine actively
refused it [2001:0:4137:9e76:c81:a4c:a547:b2fd]:808
However, if you've done everything as above, you should be able to add a reference to the service.
Calling methods in the service
When trying to call a simple Hello World method in the service from the WCF Test Client, it returns the following error:
Could not connect to
net.tcp://computername/SignalR/ServerHubService.svc. The connection
attempt lasted for a time span of 00:00:04.0002288. TCP error code
10061: No connection could be made because the target machine actively
refused it.
This is inner stacktrace that is included in with the error:
No connection could be made because the target machine actively
refused it [2001:0:5ef5:79fb:3884:a:a547:b2fd]:808 at
System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot,
SocketAddress socketAddress) at
System.Net.Sockets.Socket.Connect(EndPoint remoteEP) at
System.ServiceModel.Channels.SocketConnectionInitiator.Connect(Uri
uri, TimeSpan timeout)
If you use netstat -an |find /i "listening" to see that nothing is listening on port 808, it's probably because the Net.Tcp Listener Adapter service is not running.
Confirmation
The call goes through now, but some confirmation is needed before it can be declared a success. I need to confirm that this is in fact net.tcp call on port 808 and not actually a call on the http endpoint. I am trying to do this with Wireshark, but it doesn't show up, probably because it's a call happening from and to my local machine.
Deployment
The last challenge to conquer would be to deploy this on a web server, ensuring that what works on the development machine, also works on the web server.
It doesn't work after publish to a Windows Server 2008 R2. It gives the common SocketException: An existing connection was forcibly closed by the remote host.
It works well locally on the server, but it doesn't work remotely.
Here is the checklist used to check the server:
Is the Net.Tcp Listener Adapter service running? Yes
Is the IIS site binding to net.tcp set to 808:*? Yes
Is Enabled Protocols under Advanced Settings for the site in IIS set to http,net.tcp? Yes
Is the server listening on port 808? Yes, checked with netstat -an |find /i "listening"
Is a port 808 open in the firewall? Yes.
Firewall is turned off on the server.
I can telnet to the server on port 808 from outside with telnet mydomain.com 808
In the configuration of the service on the server, the following was confirmed:
baseAddress is adjusted to net.tcp://mydomain.com:808/SignalR/ServerHubService.svc
This was localhost before, but changed to mydomain.com after it didn't work on the server: <identity><dns value="mydomain.com" /></identity>
It has been tested with a client locally on the server and on another server. Both can connect to port 808 with telnet and both give the same error message.
What configuration could be missing on the server? I am so close to the goal. Please assist me in troubleshooting this and complete the question.
Here is the client configuration on the server calling the service:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="MyServiceEndpoint" />
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://mydomain.com:808/SignalR/ServerHubService.svc"
binding="netTcpBinding" bindingConfiguration="MyServiceEndpoint"
contract="ServerHubService.ServerHubService" name="MyServiceEndpoint">
<identity>
<dns value="mydomain.com" />
</identity>
</endpoint>
</client>
</system.serviceModel>
I also tried without 808 configured in the endpoint, as this is rumored to be the default port for net.tcp connections. However, it still gives the same result.
Instead of trying lots of things randomly, the good question is perhaps: How does one debug something like this? Can I install a program on either server that will tell me exactly WHY this call is being blocked?
With Wireshark configured like this, it's possible to look at the call coming to the server on port 808 and possibly determine why the call doesn't work. However, I have no idea how to analyze this at present time.
Good luck
I gave up and implemented this in the socket layer instead. It worked immediately. I hope this can help someone else, though. I'm setting an answer because many of the issues were solved and it did work locally eventually, so any problem remaining is probably related to me specific environment.
You have to generate the Proxy based on the metadata exposed over HTTP for tcp.(make sure httpGetEnabled is set to true). The address you use at the client should be the hosted address. Please refer the below post.
http://blogs.msdn.com/b/swiss_dpe_team/archive/2008/02/08/iis-7-support-for-non-http-protocols.aspx
In your question you mentioned that you connected to "test.mydomain.com" but the error changed the server to "computername". Then in your comment you mentioned it still failing to connect. If you wish to have the alias returned in the WSDL/MEX Add the useRequestHeadersForMetadataAddress node in your service behavior. Here is the MSDN information on this node: MSDN useRequestHeadersForMetadataAddress node
This is how your config should look. This takes into account answer given by Prasath (httpGetEnabled="true").
<serviceBehaviors>
<behavior name="ServerHubBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<useRequestHeadersForMetadataAddress>
<defaultPorts>
<add scheme="net.tcp" port="808" />
</defaultPorts>
</useRequestHeadersForMetadataAddress>
</behavior>
</serviceBehaviors>
Hosting a TCP Based service in IIS has always been a bear. WCF makes it very easy to run your own service host, listening on your TCP port. My recommendation would be to do that and set it up to run as a Windows Service.
See this article: http://msdn.microsoft.com/en-us/library/ff649818.aspx
I am guessing the issue you are having is that you need to setup the SPN (Service Principal Name) for your WCF service (on the machine) and have it added to the service account under which the service is running.
If you are running it under the default app pool user, then you need to have the SPN configured for the machine.
I know it is troubling, and typically is the surprise waiting fro us devs once our service is ready to deploy to production or pre-production environments.
The SPN is used by Kerberos during the authentication process.
Try using the IP of the machine to resolve your service instead of the hostname. (This is not supposed to require an SPN), replace "test.mydomain.com" by the machine IP address:
<host>
<baseAddresses>
<add baseAddress="net.tcp://192.168.0.253:808/SignalR/ServerHubService.svc" />
</baseAddresses>
</host>
Take a look at these articles:
- Kerberos for the Busy Admin
- WCF on intranet with windows authentication
- For the following post, try to read the one that is not accepted as an answer: What SPN do I need to set for a net.tcp service?
Did you tried to host service (for the testing purpose) in a Windows service on your local machine? This way you will at least know if the problem is on the service side or it's IIS/server configuration.
You have Net.TCP Port sharing service running on the server I guess... haven't found it explicitely stated.
I had a similar problem here today, while calling a net.tcp wcf service from inside an asp.net web api. I won't say that from all the other machines this service has worked for years, but the calls were made wcf self hosting, wcf iis asp.net compatibility hosting -> against the net.tcp service self hosted. When then I published my simple web api calling the same net.tcp service, everything went wrong, and all the connection were aborted without any reason, even the full wcf tracing both sides (service and client) did not helped, just telling the same "connection aborted".
I've already knew that net.tcp comes with the security over transport enabled, using windows authentication to sign and crypt the communication, so well, I just tried to turn off the security and everything start to work properly.
Just give it a try turning off the security in this way both sides (client and service):
<security mode="None"/>
full service binding:
<netTcpBinding>
<binding name="netTcpBinding" portSharingEnabled="true">
<security mode="None"/>
</binding>
</netTcpBinding>
I hope this can help you too.