WCF only accepts localhost - wcf

I'm writing my first WCF in Visual Studio Express, and configured it to run under IIS Express. My Web.config is as bellow. From my browser I can access the service if I do a Get request on http://localhost:50000/Service1.svc, but not http://10.0.0.26:50000/Service1.svc where 10.0.0.26 is my ip. How to configure WCF of IIS Express to accept IP addresses. Ultimatly my service is tio be reached accross the network.
<?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>
<services>
<service name="medSaveWCF.Service1">
<endpoint address="../Service1.svc"
binding="webHttpBinding"
contract="medSaveWCF.IService1"
behaviorConfiguration="webBehaviour" />
</service>
</services>
<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>
<endpointBehaviors>
<behavior name="webBehaviour">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept" />
</customHeaders>
</httpProtocol>
<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>

(Side note: I have blogged about this, including additional setup steps you need to use SSL: http://blog.kutulu.org/2015/01/using-iis-express-with-remote-systems.html)
The problem is that IIS Express only listens on the localhost address, by default. The reason is, IIS runs as a user process, but uses the same HTTPD.SYS system library that the full IIS does. By default the HTTPD.SYS configuration does not allow user processes to bind to an external address. To fix this you'll need to do three things:
Edit the IIS configuration to bind to a new port
Update HTTPD.SYS to permit your user to use that new binding.
Tell WCF you have multiple bindings.
Step One: IIS Express Setup
The IIS Express configuration is done directly through the XML configuration file, which is found at:
C:\Users\[username]\Documents\IISExpress\config\applicationhost.config
If your project is already set up to work with IIS Express, you'll find a configuration block starting around 150 lines into the file -- look for the XML <sites> tag, and you'll find a <site> element:
<site name="MySolution.MyProject" id="2">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/"
physicalPath="C:\Projects\MySolution\MyProject" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:50000:localhost" />
</bindings>
</site>
Inside that <bindings> element is the list of ports and hostnames that IIS Express binds to when running that particular site, you just need to add a new binding element:
<binding protocol="http" bindingInformation="*:50000:10.0.0.26" />
Step Two: HTTPD.SYS Permissions
Full disclosure: this step is optional if you are willing to run Visual Studio and IIS Express as an admin user. But that defeats the entire purpose of IIS Express, which is a user-mode web server, so don't do that.
Instead, you just need to use the netsh command to reconfigure HTTPD.SYS to allow you to bind to the ports you want. Specifically, you need to use the http add urlacl command.
Launch an administrative command prompt and/or PowerShell prompt and do this:
netsh http add urlacl url=http://10.0.0.26:5000 user=Everyone
Once both are done, shut down IIS Express so VS will restart it, and you should be all set.
I wrote myself a small Powershell script to go through and do this for a whole range of ports:
$LowPort = 50000
$RangeSize = 99
for ( $i = 0; $i -le $RangeSize; $i++ )
{
netsh http delete urlacl url="http://${IISHost}:$($LowPort + $i)/"
netsh http add urlacl url="http://${IISHost}:$($LowPort + $i)/" user=Everyone
}
That way I don't have to remember to do this every time, I just need to use a port in the 50000 - 50100 range.
Step Three: Inform WCF
By default, WCF only binds to one site per project. For real IIS this is fine, because that's the *:80 binding you probably want. For IIS Express, you need separate bindings per IP address so you need to tell WCF to use them all. This is easy, just add this to your WCF configuration:
<configuration>
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</configuration>
Once all that's done, shut down IIS Express and let VS restart it and you should be all set.

Related

Confusion about default WCF project web.config layout

Below is the default layout for the web.config of a new WCF Service Application in VS2012.
What confuses me is that it doesn't seem to match any examples or tutorials online. There are no endpoints or bindings defined, yet it's possible to call the service.
I hit a problem when trying to increase the MaxReceivedMessageSize property - I googled it and didn't have a clue where to look in my web.config.
Can someone point me in the right direction of why it's so strangely laid out?
I expected it to look more like This SO question about setting MaxReceivedMessageSize or even any WCF tutorials like Michelle Bustamante's which is how I originally learned WCF.
<?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="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>
Starting with .NET 4.0, WCF introduced the concepts of default endpoints and bindings, allowing developers to create a service without having to define a bunch of stuff in the configuration file.
The posted config file is targeting 4.5, which is why you're seeing such a naked WCF config. If you need to increase your maxMessageSize, you'll need to explicitly define it in the config.
You can do this by either setting that binding definition as the default (by omitting the name attribute on the binding element), or creating an endpoint and explicitly assigning the binding configuration you defined via the bindingConfig attribute.
See A Developer's Introduction to Windows Communication Foundation 4.
You can also check a previous answer by me that has examples: https://stackoverflow.com/a/16099054/745969

WCF Activation for MSMQ where the service (.svc) is on the root

VS 2012/.NET4.5, Windows 8/IIS8 and 64 bit
Using WCF Service application, all the documentation that I've seen so far in naming my MSMQ queue to match the service name assume the fact that I am using an application or a virtual directory underneath the IIS website.
This is quoted from MSDN http://msdn.microsoft.com/en-us/library/ms789042.aspx
The application being activated must match (longest match) the prefix
of the queue name.
For example, a queue name is:
msmqWebHost/orderProcessing/service.svc. If Application 1 has a
virtual directory /msmqWebHost/orderProcessing with a service.svc
under it, and Application 2 has a virtual directory /msmqWebHost with
an orderProcessing.svc under it, Application 1 is activated. If
Application 1 is deleted, Application 2 is activated.
Also, http://blogs.msdn.com/b/tomholl/archive/2008/07/12/msmq-wcf-and-iis-getting-them-to-play-nice-part-1.aspx
However when you are hosting your MSMQ-enabled service in IIS 7 WAS,
the queue name must match the URI of your service's .svc file. In this
example we'll be hosting the service in an application called
MsmqService with an .svc file called MsmqService.svc, so the queue
must be called MsmqService/MsmqService.svc. Queues used for WCF
services should always be private
And, http://msdn.microsoft.com/en-us/magazine/cc163357.aspx
It's important to note that the activation of MSMQ endpoints only
works correctly if the queue has the same name as the .svc file (minus
the machine name). That means that if your service endpoint is
/server/app/service.svc, the queue name must be app/service.svc.
MyService.svc file is directly under the root of my IIS website (which is using a .NET 4 pool in integrated mode), so I did the following:
Creating a private transactional queue called MyService.svc and giving Network Services full control (for testing).
Setting my web.config endpoint: address="net.msmq://localhost/private/MyService.svc"
I was able to push a message to the queue using a client test application using the address in (2).
I added MSMQ protocol support to the website by executing the following:
C:\Windows\System32\inetsrv>appcmd set site "MyWebsite" /+bindings.[protocol='net.msmq',bindingInformation='localhost'] (and checked that it added the support properly)
From my website advanced settings I have http,net.tcp,net.msmq In Enabled Protocols
I double checked that "Net.Msmq Listener Adapter", which is responsible for activating the service when a message arrives, is running and I restarted it.
My web.config:
<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>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpBinding" scheme="http" />
<add binding="netMsmqBinding" scheme="net.msmq" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false"
multipleSiteBindingsEnabled="true" />
<bindings>
<netMsmqBinding>
<binding name="MsmqBinding_IMyService" exactlyOnce="true"
receiveErrorHandling="Move">
<security mode="None"/>
</binding>
</netMsmqBinding>
</bindings>
<services>
<service name="CompanyName.Service.MyService">
<endpoint name="MyService"
address="net.msmq://localhost/private/MyService.svc"
bindingConfiguration="MsmqBinding_IMyService"
binding="netMsmqBinding" contract="IMyService" >
</endpoint>
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="false" />
</system.webServer>
</configuration>
My service is not getting activated with the arrival of new messages to the queue and the messages stay in the queue. Is that because I am not using an application or a virtual directory or is there something I am missing?
The problem is sorted by creating an application within the default website and modifying the configuration to fit the new path.

Seeting the default page of the svc-less WCF service

I made a 'Hello World' WCF service. The service doesn't have a svc file.
Therefore the web.config file determines its address and other settings.
However, I'm stuck with opening the specific page.
When I run the WCF service project, it always shows the error page (HTTP Error 403.14).
This is because the browser tries to go to localhost instead of localhost/HelloWorldService.svc.
Do you know how can I solve it?
I want to open the localhost/HelloWorldService.svc when I start running the WCF service in VS 2012.
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
<a href="http://go.microsoft.com/fwlink/?LinkId=169433">http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="false" targetFramework="4.5"/>
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<serviceHostingEnvironment >
<serviceActivations>
<add factory="System.ServiceModel.Activation.ServiceHostFactory"
relativeAddress="HelloWorldService.svc"
service="HelloWorldService.HelloWorldService"/>
</serviceActivations>
</serviceHostingEnvironment>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Go to Properties -> Web -> click Specific Page and enter /HelloWorldService.svc.

Can't define the endpoint after creating my WCF

I wanna learn WCF so I decided to try out creating some application that uses it. Well what I have in mind is I have 2 databases and I wanna create also an SSIS custom data source extension that calls the web service and passes the data (from one database) to an SSIS ADO.Net Data source (into the second database).
Now I created the 2 databases using SQL Server with one table in each. Then I Added a Connection in Visual Studio and then specified the server instance. (didn't create any .mdf files). I added this connectionString in the Web.Config file
<connectionStrings>
<add name="dbconnection" connectionString="
Data Source = SARE-VAIO;
Integrated Security = true;
Initial Catalog = Database1"/>
</connectionStrings>
When I wrote my service which basically populates Database1 with data, I wanted to define the endpoints but when I clicked on the "Edit WCF Configuration" it says 'No Service' is defined? What possibly am I doing wrong here? I want to create an error free service to be able to use it as a source in the SSIS package.
PS. My service has a basicHttpsBinding
UPDATE: I'm using VS 2012 with .Net Framework 4.5
UPDATE 2:
I skipped the endpoint definition for now and went ahead with testing and deploying my WCF. When I invoke the service it says the following error
Failed to invoke the service. Possible causes: The service is offline or inaccessible;
the client-side configuration does not match the proxy; the existing proxy is invalid.
Refer to the stack trace for more detail. You can try to recover by starting a new proxy,
restoring to default configuration, or refreshing the service.
Here is my web.config file
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="dbconnection" connectionString="Data Source = SARE-VAIO; Integrated Security = true; Initial Catalog = Database1"/>
</connectionStrings>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="false" 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="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
To answer your questions
(1) Why WCF configuration editor shows 'No service is defined' error : Your web.config does not have any services and endpoints defined explicitly (Note: When you host this in IIS you will still get some endpoints added due to the defaults endpoint feature. But config editor tool shows only explicitly defined endpoints). That's the reason the config editor tool shows this message. But you can use the tool to add services and endpoints.
(2) After deploying the service see if the service successfully activated. You can do this by browsing to the metadata URL (your config has metadata enabled). Make sure your service WSDL help page and WSDL shows up fine. If not fix that issue first.
(3) If you are looking a default https endpoint after hosting it in IIS, make sure your IIS has https binding configured with an SSL certificate.
Hope this helps!
Thanks!

WCF (.NET 4.0) + IIS 7 + Windows Authentication Error - "service require Windows Authentication but it is not enabled for the IIS application "

We have a simple WCF (on .NET 4.0) Service which uses Windows authentication and same is enabled on the IIS 7 Authentication feature. This works with same settings and same configuration on two servers, but on one of the server comes back with error Security settings for this service require Windows Authentication but it is not enabled for the IIS application that hosts this service. I checked everything possible on web, and tried all the options like disabling other Authentication mechanisms etc. Nothing seems to be working. Could anyone point what can be the issue.
Again identical settigns on two servers is working perfectly on third server it has the issue.
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="ABCDbConnection" value="Data Source=xxx; Initial Catalog=sss;Integrated Security=True"/>
<add key="MetadataDbConnection" value="Data Source=xxx; Initial Catalog=sss;Integrated Security=True"/>
<add key="UsageEnabled" value="True"/>
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="basicHttpBinding" bindingConfiguration="WindowsBasicHttpBinding"/>
</protocolMapping>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="6553600"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="WindowsBasicHttpBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Did any of the solutions in this thread work?
http://social.msdn.microsoft.com/Forums/en/wcf/thread/021babc6-2009-4ed9-81f4-ac48cc300c94
From this blog post, it mentioned this KB article.
If this error is returned and Windows
Authentication has been enabled in
IIS, it means there is an issue with
the supported network authentication
schemes for the website that the web
service is installed under. The most
likely cause is that it is configured
for NTLM only. We want to specify NTLM
and Negotiate.
Have you tried enabling Windows Authentication through the web.config using
<system.web>
....
<authentication mode="Windows" />
.....
</system.web>
There could be the possibility that one machine is inheriting this setting from a parent configuration file but not on the one throwing the error is not.
You can also verify that Anonymous Authentication is disabled like in the image below