I have a really simple WCF service - this is the service contract:
[ServiceContract]
public interface IHelloService
{
[OperationContract]
string SayGreeting(string name);
[OperationContract]
string SayRudeGreeting(string name);
}
and this is the implementation:
public class HelloService : IHelloService
{
public string SayGreeting(string name)
{
return "Well, hello there, " + name;
}
public string SayRudeGreeting(string name)
{
return string.Format("What do you want, {0} ?", name);
}
}
That's not the interesting part :-) what I'm trying to do is self-host this simple service in a Windows command line app. I'm doing this with these lines of code:
Uri baseAddress = new Uri("http://localhost:9099");
using (ServiceHost host = new ServiceHost(typeof(HelloService), baseAddress))
{
host.Open();
Console.WriteLine("HelloService is up and running ....");
Console.ReadKey();
Console.WriteLine("HelloService - closing down...");
}
and I have a really simple, straightforward app.config for that host:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="DevDebug">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="WcfService1.HelloService"
behaviorConfiguration="DevDebug">
<endpoint
address="HelloService"
binding="wsHttpBinding"
contract="WcfService1.IHelloService" />
<endpoint
address="HelloService/mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
Nothing fancy at all - just a regular wsHttpBinding endpoint at http://localhost:9099/HelloService and a MEX endpoint as well.
When I build this host and WCF service, and run the host within Visual Studio 2015 which I start "As Administrator", I get this odd message:
System.ServiceModel.AddressAccessDeniedException was unhandled
HResult=-2146233087
Message=HTTP could not register URL http://+:9099/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details).
?!?!?!?!? I'm the ADMINISTRATOR on my box - why wouldn't I be allowed to register this URL!?!?
My suspicion is that this is a new "feature" of Windows 10 (Professional - v1607) - because I'm pretty sure, this setup used to work just fine on my previous Windows 7 box.
OK - so I launch my WCF host from the command line, explicitly as administrator - and now the host comes up and everything seems fine, I can connect to it from the WCF Test Client, and my code seems to work just fine.
But if I now try to connect to it using either SoapUI or just IE 11, I keep getting another slew of error messages ("invalid page" etc.) that seem to indicate that this URL cannot be accessed.....
WHY!?!
What do I need to do in Windows 10 Professional to make WCF self-hosting work again!?
Thanks!
The reason for this is that you have to Register the URL.
Basically, open up a Command Line window CMD (type CMD into Windows 10 search)
Then to Install Net Local Address use the following scripts: (copy and right click paste)
cd C:\Windows\Microsoft.NET\Framework\v4.0.30319
netsh http add urlacl url=http://+:8731/Design_Time_Addresses user=DOMAIN\user
Note: replace the +8731 with your URL and Design_Time_Addresses with your service name (or you can leave this out, but it helps to identify the URL - maybe you have more than one service from the same URL)
To Delete Net Local Address
netsh http delete urlacl url=http://+:8731/Design_Time_Addresses
Then, you need to open up the port through your Windows Firewall.
In Windows Search put: Firewall
On the left menu, Click 'Advance Settings'
Then click the 'Inbound Settings' in the left menu.
In the right menu, click 'New Rule' .. this opens up a new window.
Select 'Port' and click 'Next'
In the textbox, put your URL (mine is 8731) and click 'Next'
Keep the current selection of 'Allow the connection' and click 'Next'
Keep all the checkboxes clicked (unless you know otherwise) and click 'Next'
Give it a good name relating to your application and add a description and click 'Finish'
You should now be able to link to the URL via a web browser.
If you want to serve an actual service out to the outside world, then you'll need to go to your router and set a Static IP address and open the Port through your Firewall also.
You can get to your router via 192.168.0.1 (depending upon your router)
Obviously, if your using a laptop then the second you take your laptop out of your flat then your service will no longer be available to the Outside World, so you really need a dedicated desktop machine to act as a server.
You can find out about Static IPs and Port Forwarding from Google searching and you can Google about your router and it's Firewall settings to allow your URL.
Hopefully, it'll all work out, if not, then just ask again.
Good luck and have fun.
This also works for RestApi's (Asp.Net WebApi), WCF services are usually used for Financial Service companies as they allow for more granular security protocols.
Related
I need help setting up my Azure virtual machine to allow connection to my WCF website service. Please, I am just missing something simple relative to Azure.
I get this error:
"There was no endpoint listening at http://mydomainname.com/registrations.svc that could accept the message"
I have set up the HTTP, HTTPS, FTP, and other endpoints for my VM.
I have searched the web and this site for hours and still no answer - like lots of other folks it seems.
Details:
I have a website on an Azure Virtual Machine (Server 2008). The website is a copy of our production website hosted on our local server. The website has a WCF service used by a windows desktop client. Everything woks on our local server.
Everything on the Azure server works except access to the service. My registered domain name points to the Azure Server public IP address so accessing website hosted on the Azure machine works.
Example: http://www.mydomainname.com brings up my ASP.NET website. It works as expected including the https binding.
The service seems to be visible to the outside world.
Example http://www.mydomainname.com/Registrations.svc?wsdl brings up the details of the service.
Also, if I put a copy of the client code on the VM and a local host version of the website on the VM (using VS Express for web debug) and change the url in my client to point to the local host version of the service - that all works
I have not changed any firewall settings as of yet because I did not need to do so in our onsite server (or even on an ISP webserver).
Here is the service info:
<system.serviceModel>
<services>
<service name="RegistrationsService" behaviorConfiguration="RegistrationsServiceBehavior">
<endpoint address="" binding="wsHttpBinding" contract="IRegistrations"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="RegistrationsServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
Can someone tell me what I may be missing.
Do I need to set up another endpoint for my VM in Azure Portal so WCF will work: Name=AnyName? Protocol= "TCP; public port = ? Private Port= ?
After the above, what ports do I enable in server firewall (the public port or the private port)
Anything else different between an Azure Virtual Machine and other Virtual machines (like our onsite servers or ISP web servers)
Are there any settings I may have missed in IIS or other places. I have everything set just like in our local server where the website and services work.
Any help would be very much appreciated
Dennis
I built a WCF Service in one of my machines of my local network, it has both http and net.tcp (htpp,net.tcp) as enabled protocols in IIS manager.
From another machine a build a client app, and define the endpoints automatically using the Add Service Reference... dialog, I type the service address and when it appears I set the name and click OK. The App.config is updated with two endpoints, one for http (BasicHttpBinding) and the other for net.tcp (NetTcpBinding) as expected.
When running the client app, if I use the BasicHttpBinding:
"using (var proxy = new ProductsServiceClient("BasicHttpBinding_IProductsService"))"
it runs OK, and shows the expected data.
But when I use the NetTcpBinding:
"using (var proxy = new ProductsServiceClient("NetTcpBinding_IProductsService"))"
It throws a SecurityNegotiationException saying that:
"A remote side security requirement was not fulfilled during authentication. Try increasing the ProtectionLevel and/or ImpersonationLevel."
If I do it all in the same machine, I don´t get any exception.
What should I do?
Rafael
By default, the BasicHttpBinding supports no security. So when calling the service from another computer, it will work also.
But by default, NetTcpBinding requires a secure channel. And the default security mode is Transport, so when calling the service from another computer, it will throw a security exception.
The most easy way to solve it is to set the security mode to None as following:
<bindings>
<netTcpBinding>
<binding name="netTcpBindingConfiguration" >
<security mode="None" />
</binding>
</netTcpBinding>
Then we use it in the endpoint
<endpoint address="net.tcp://nelson-laptop:8080/Whatever"
binding="netTcpBinding"
bindingConfiguration="netTcpBindingConfiguration"
contract="ProductsService.IProductsService"
name="NetTcpBinding_IProductsService" />
In Your question you are using the default net.tcp port 808 but have opened port 80 in the firewall. If it is not a typo in the question it could be why it fails.
I am trying to implement scalable wcf solution found at NetFX Harmonics: Creating Streamlined, Simplified, yet Scalable WCF Connectivity
So my solution have 4 projects
Contact.Service (Service and Data Contracts)
Contact.ServiceImpl (HostFactory and Service itself)
Contact.ServiceHost (Web.config and Person.svc)
Contact.ServiceClient
Contact.ServiceClient have App.config and Program.cs which actually call service.
App.config
<configuration>
<appSettings>
<add key="PersonServiceActiveEndpoint" value="PersonServiceBasicHttpBinding" />
</appSettings>
<system.serviceModel>
<client>
<endpoint name="PersonServiceBasicHttpBinding"
address="http://localhost:1031/Person.svc"
binding="basicHttpBinding"
contract="Contact.Service.IPersonService" />
</client>
</system.serviceModel>
</configuration>
Program.cs
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost:1031/Person.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();
Person person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");
Console.WriteLine(person.FirstName);
When I try running this example exception is thrown:
There was no endpoint listening at http://localhost:1031/Person.svc that could accept the message. This is often caused by an incorrect address or SOAP action.
P.S. Person.svc is in my Contact.ServiceHost project
<%# ServiceHost Service="Contact.Service.PersonService" %>
what is the config of the service host? sounds like one of 2 problems:
the service host is not set up to listen on the same port.
the host application is not being run at all
I imagine that by checking the web.config of the service host project you'll likely find that it is either listening on a different port, or not being run at all, and hence not listening.
Is the Visual studio host starting up and hosting the service? You usually get a little 'toast' pop up window in the notification area next to the clock saying the the host is running and you can see which port it is running on. if this is not happening then it is likely that you need to configure it to start the host project as well as the client.
To enable both the client and server to start at the same time you need to:
Right-click on your solution file, and choose Set Startup Projects...
Choose Multiple startup projects and choose Start for your client and server project, leave the other ones set to none.
We have a WCF service with multiple clients to schedule operations amongst clients. It worked great on XP. Moving to win7, I can only connect a client to the server on the same machine. At this point, I'm thinking it's something to do with IPv6, but I'm stumped as to how to proceed.
Client trying to connect to a remote server gives the following exception:
System.ServiceModel.EndpointNotFoundException: Could not connect to net.tcp://10.7.11.14:18297/zetec/Service/SchedulerService/Scheduler. The connection attempt lasted for a time span of 00:00:21.0042014. TCP error code 10060: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 10.7.11.14:18297. ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 10.7.11.14:18297
The service is configured like so:
<system.serviceModel>
<services>
<service
name="SchedulerService"
behaviorConfiguration="SchedulerServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost/zetec/Service/SchedulerService"/>
</baseAddresses>
</host>
<endpoint address="net.tcp://localhost:18297/zetec/Service/SchedulerService/Scheduler"
binding="netTcpBinding"
bindingConfiguration = "ConfigBindingNetTcp"
contract="IScheduler" />
<endpoint address="net.tcp://localhost:18297/zetec/Service/SchedulerService/Scheduler"
binding="netTcpBinding"
bindingConfiguration = "ConfigBindingNetTcp"
contract="IProcessingNodeControl" />
</service>
</services>
<bindings>
<netTcpBinding>
<binding name = "ConfigBindingNetTcp" portSharingEnabled="True">
<security mode="None"/>
</binding>
</netTcpBinding >
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="SchedulerServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling maxConcurrentSessions="100"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
The client connects like so:
String endPoint = "net.tcp://" + GetIPV4Address(m_SchedulerHostAddress) + ":" + m_SchedulerHostPort.ToString(CultureInfo.InvariantCulture) + "/zetec/Service/SchedulerService/Scheduler";
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.None;
m_Channel = new DuplexChannelFactory<IProcessingNodeControl>(this, binding, endPoint);
m_IProcessingNodeControl = m_Channel.CreateChannel();
I've checked my firewall about a dozen times, but I guess there could be something I'm missing. Tried disabling windows firewall. I tried changing localhost to my ipv4 address to try to keep away from ipv6, I've tried removing any anti-ipv6 code.
Don't know if it means anything, but:
Microsoft Telnet> open 10.7.11.14 18297
Connecting To 10.7.11.14...Could not open connection to the host, on port 18297:
Connect failed
The telnet test unfortunately doesn't seem to be key. I have successfully connected to my service's port from localhost and a remote computer when the service is running, but my client did not work from the remote computer.
Looks like connecting to localhost is not always guaranteed. Desktop (win7/32) works, Laptop (win7/64) doesn't work. Other win7/64 boxes do work though. Perhaps due to multiple nic's on the laptop? Also doesn't explain failures to connect on testers' systems.
I set up two win7 machines with IPv6 fully disabled (using 0xffffffff as in http://support.microsoft.com/kb/929852 ). No help.
Something doesn't look right about your host base address and then the end point addresses. One has an explicit port reference, the other doesn't. Usually when you use a base address you use a relative URL in the endpoint address.
I can't think why this would be related to IPv6, because none of the error messages mention IPv6 addresses.
Perhaps try again after disabling the net.tcp port sharing option. Without port sharing, you should be able to confim a connection using telnet like you did.
Also, how is your service hosted in Win7? In IIS7 or self hosted in a Windows Service? Hosting it in a Service may require some permissions to be granted to your exe beyond opening ports on your firewall (like you sometimes have to do for hosting a windows service in HTTP in Win XP).
Sorry, I'm in a hurry and can't look up URLs for these.
I don't have time to go back and test whether it is a combination of the help I received from ligos or not, but the primary fix appears to be adding SMSvcHost.exe to the exceptions in the Windows Firewall.
Thanks a lot for your help, ligos. I was ready to give up until you replied to my question.
Instructions for adding net.tcp to windows firewall:
Go to Services, find the net.TCP port sharing service, and double click it. Swipe the Path to executable (don’t worry if it’s not all on screen, the swiping action should scroll it over) and copy it (ctrl-c)
Go to your firewall and add a new program to be allowed to communicate through the Windows Firewall. Paste in the path from Services and hit ok.
I've got a small WCF webservice working with the built-in WCF Service Host and with hosting by the Visual Studio 2008 built-in development webserver.
I these hosting enviroments I have relied on the WCF Test Client for invoking the service methods.
Now I am running into problems with my next phase of testing:
I have it hosted in IIS 5.1 on my WinXP dev machine and I think maybe the problem is I cannot continue to use WCF Test Client anymore. Here is what's happening:
Case 1: "Anonymous Access" is CHECKED (ENABLED)
WCF Test Client UI comes up properly, exposing the WebMethods and the INVOKE button.
Yet when I click INVOKE it fails to connect with a backend data store (a 3rd party product) that requires Windows authentication. I could post the error I get back from the product.DLL but I don't think it is relevant.
Case 2: "Anonymous Access" is un-CHECKED (DISABLED)
WCF Test Client UI fails to even initialize properly. My researching of this tells me that MEX (WS-Metadata Exchange) requires "Anonymous Access" and (apparently) WCF Test Client requires MEX. Here are key snippets of the error being returned:
Error: Cannot obtain Metadata from http://localhost/wcfiishost
The remote server returned an error: (401) Unauthorized.HTTP GET Error
URI: http://localhost/wcfiishost
There was an error downloading 'http://localhost/wcfiishost'.
The request failed with the error message:
Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service
The are lots of explanations of binding options, message security, etc. and stuff I honestly do not understand. Here is my take on where I am but I would love your opinions:
(a) Because I know my WCF webservice MUST be configured to use Windows Authentication, I conclude I cannot continue to use the WCF Test Client when hosting my service in IIS. That it has effectively outlived it's usefulness to me. I will just have to take the time to write a web client because WCFTestClient won't work without Anonymous.
(or)
(b) It is possible to use WCF Test Client if it and the hosted service are configured propertly (I just don't know what the special configuration techniques are for this).
Which is correct? Time to stop using WCFTestClient or is there a way to have it both ways? Thanks in advance for your advice.
EDIT: 11 June 09
Is there anything else I can provide to help someone else help me on this question?
I just tried to have the same setup - but in my case, everything seems to work just fine.
ASP.NET web site
WCF service, using basicHttpBinding without any special settings at all
IIS Application with anonymous = enabled and Windows authentication = enabled (both turned on)
I can easily connect to it with the WcfTestClient and retrieve the metadata, and I can then call it, no problem.
Inside my service function, I check to see whether the current user is a known user or not, it is correctly identified as a Windows authenticated user:
ServiceSecurityContext ssc = ServiceSecurityContext.Current;
if (ssc.IsAnonymous)
{
return "anonymous user";
}
else
{
if(ssc.WindowsIdentity != null)
{
return ssc.WindowsIdentity.Name;
}
if (ssc.PrimaryIdentity != null)
{
return ssc.PrimaryIdentity.Name;
}
}
return "(no known user)";
I don't really know, what more to check for (except I'm on Vista with IIS7). Any chance you could include this code to check for the user in your service code? Just to see....
Marc
Marc, your setup is not even close to Johns.
John uses WSHttpBinding that uses Windows Credentials for Message mode transport. The Windows Authentication isn't being used with BasicHttpBinding. Furthermore, John had AnonymousAuthentication disabled, which is why the Metadata Exchange (mex) is failing.
The call won't even reach inside the service side function, because we get a Error 401 (Unauthorized) when we try to call.
Just know John, I have the same issue, and I'm trying to somehow set up separate bindings per endpoint. Hopefully that will work.
When I set the title/subject of this question and reached a dead end here, I opened up the same issue in the MSDN forum with a different emphasis on the title (content of question essentially the same).
For me, the real issue was how to use WCFTestClient in IIS without Anonymous Authentication being set (because my service needed Integrated Windows Authentication only).
Mex apparently requires Anonymous and by default WCFTestClient seems to need Mex. The key seems to be accomodating both my doctoring up the web.config file carefully.
Anyway, I got it working with this web.config below (the MSDN link is here:
<?xml version="1.0"?>
<configuration>
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="wsBindingConfig"
contract="sdkTrimFileServiceWCF.IFileService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="basic"
binding="basicHttpBinding"
bindingConfiguration="bindingConfig"
contract="sdkTrimFileServiceWCF.IFileService" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="bindingConfig">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="wsBindingConfig">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
</serviceBehaviors>
</behaviors>