I have a WCF Service that Hosted in Windows Service
It uses NetTCPBinding and i could connect, i want to implement new Silverlight client to access the service
i have walk through the normal way to add service reference, and it was added with Empty "ServiceReferences.ClientConfig"
so i have viewed some threads and topics, at last i have write my configuration manually for the service
when i try to connect it show's this exception
Could not connect to net.tcp://localhost:4502/MyService/Service. The connection attempt lasted for a time span of 00:00:02.2111265. TCP error code 10013: An attempt was made to access a socket in a way forbidden by its access permissions.. This could be due to attempting to access a service in a cross-domain way while the service is not configured for cross-domain access. You may need to contact the owner of the service to expose a sockets cross-domain policy over HTTP and host the service in the allowed sockets port range 4502-4534.
i believe that the problem related to ClientAccessPolicy.xml file
after search people say i need to have IIS7 installed and file is accessible through it, i have tried this but i couldn't make it work
but, i have worked on this before, but i was using PollinghttpBinding no NetTCP, and i have created another service contract to return the ClientAccessPolicy file
i have tried to do the same i do before with PollinghttpBinding but i can't write the right Configuration of the Service
My client refuse to use IIS, so could i use this way and what is the right configuration i should use with this service?
this is the configuration i use for my Service
<service behaviorConfiguration="serviceBehavior" name="MyService">
<endpoint address="net.tcp://localhost:4502/MyService/Service" behaviorConfiguration="endpointBehavior" binding="netTcpBinding" bindingConfiguration="netTcpServiceBinding" contract="IMyService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="net.tcp://localhost:7000/MyService/mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
</service>
can anyone give help?
Net.tcp bindings are not supported "out-of-the-box" in Silverlight. That's why the config is empty. But you can use it anyway, by using a customBinding and setting the properties you need. However, I have never tried this fyself.
If this is a cross domain problem, this is nedeed related to the ClientAccessPolicy.xml file.
Normally (as stated many places on various forums), this is solved by putting the file in the root of the site. So if your service runs on "http://localhost/MyService", the file should be put so it's available in "http://lovalhost".
However, without a IIS available, this has to be done another way. You will have to create an endpoint on the root manually in the Windows Service, where this file is available.
This is a normal BasicHttp binding either you use "net.tcp" or "http".
I have done this with success this way:
Policy interface:
using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace MyPolicyService
{
[ServiceContract]
public interface IPolicyRetriever
{
[OperationContract]
Stream GetPolicy();
}
}
Policy class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.ServiceModel.Web;
namespace MyPolicyService
{
public class PolicyRetrieverBase : IPolicyRetriever
{
public Stream StringToStream(String result)
{
WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
return new MemoryStream(Encoding.UTF8.GetBytes(result));
}
public Stream GetSilverlightPolicy()
{
string result = #"<?xml version=""1.0"" encoding=""utf-8""?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers=""*"" http-methods=""*"">
<domain uri=""*""/>
</allow-from>
<grant-to>
<resource path=""/"" include-subpaths=""true""/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>";
return StringToStream(result);
}
public Stream GetFlashPolicy()
{
string result = #"<?xml version=""1.0"" encoding=""utf-8""?>
<!DOCTYPE cross-domain-policy SYSTEM ""http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"">
<cross-domain-policy>
<site-control permitted-cross-domain-policies=""all""/>
<allow-access-from domain=""*"" secure=""false"" />
<allow-http-request-headers-from domain=""*"" headers=""*"" secure=""false"" />
</cross-domain-policy>";
return StringToStream(result);
}
}
}
When these classes are created, create the service almost just as you would start the "net.tcp" service, but of course change it to BasicHttpBinding and use some different behaviors and property values related to the BasicHttpBinding (like TransferMode = Buffered etc).
This policy service should, needless to say, be started on the site root (http://localhost).
ID YOU HAVE THE IIS running on this server, do NOT start this policy service because this will take over this address :-)
Hope that gets you moving in the correct-ish direction :-)
Related
I have a WCF webservice that can be accessed via a http endpoint. Now, this service shall be published with a load balancer via https. Clients are created in .Net via svcutil.exe but the WSDL is also needed for a Java client.
What I understand is:
Internally the webservice is a http service and nothing needs to be changed. The address is http://myserver.com/example.svc with WSDL ..?wsdl
Externally the service has to show up as a https service with address https://loadbalancer.com/example.svc and WSDL ..?wsdl
From other posts I have learned that the load balancer problem can be solved with following behaviour configuration:
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<useRequestHeadersForMetadataAddress>
<defaultPorts>
<!-- Use your own port numbers -->
<add scheme="http" port="81" />
<add scheme="https" port="444" />
</defaultPorts>
</useRequestHeadersForMetadataAddress>
</behavior>
Using this workaround I get both URLs resolved to the services help page, but calling
https://loadbalancer.com/example.svc the page leads me to http://loadbalancer.com/example.svc?wsdl. When I replace the http by https I can load the wsdl but it has all internal links as http and not https.
Trying to switch httpsGetEnabled="true" leads me to a lot of https related issues and I don't know if this can help me as my server itself only knows http.
So, my problem is the https for the load balanced URL. Can I tell WCF that it shall show https in the WSDL meta data instead of http and how can I do this?
I have had this issue before and the fix pretty much was overriding the SoapExtensionReflector method name: ReflectDescription.
using System.Web.Services.Description;
namespace LoadBalancer
{
public class HttpsSoapExtensionReflector : SoapExtensionReflector
{
public override void ReflectMethod()
{
//no-op
}
public override void ReflectDescription()
{
ServiceDescription description = ReflectionContext.ServiceDescription;
foreach (Service service in description.Services)
{
foreach (Port port in service.Ports)
{
foreach (ServiceDescriptionFormatExtension extension in port.Extensions)
{
SoapAddressBinding binding = extension as SoapAddressBinding;
if (null != binding)
{
binding.Location = binding.Location.Replace("http://", "https://");//Updating the soap address binding location to use https
}
}
}
}
}
}
}
Once you create the above class into a new or an existing dll project (In my example the dll name is LoadBalancer) you just need to invoke our new extension from the server web config like:
<webServices>
<soapExtensionReflectorTypes>
<add type="LoadBalancer.HttpsSoapExtensionReflector, LoadBalancer"/>
</soapExtensionReflectorTypes>
</webServices>
If it is under LoadBalancer then it will go ahead and modify the binding location and it will be generate the WSDL with the HTTPS url.
Tested on SoapUI and from Visual Studio adding service references (app.config will reflect https).
Thanks
no, no way to tell the WCF to show the https in WSDL meta data instead of http.
our solution is, create both http and https endpointbindings, check if the incoming request is http or https, the incoming request type determine which endpointbindings will be used.
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.
In summary
How do I acces a WCF service on localhost when hosted in IIS on Azure? Azure does not bind localhost or 127.0.0.1 to my website.
Details
I have an ASP.Net application hosted on Azure. I have added a .svc and some workflows that I want to use via WCF. To keep matters simple, my web app simply calls the service on localhost, so I have endpoints like these in web.config;
<client>
<endpoint address="http://localhost:8080/Router.svc/Case" binding="basicHttpBinding" contract="NewOrbit.ExVerifier.Model.Workflow.Case.ICaseWorkflow" name="Case" />
<endpoint address="http://localhost:8080/Workflow/Case/Case_default1.xamlx" binding="basicHttpBinding" contract="*" name="Case_default1" />
</client>
This works just fine on my local machine. The problem is that when I publish this to Azure, the Website in IIS does not get a binding to localhost, instead the bindings are always to the actual IP address of the server.
It ends up looking like this in applicationHost.config:
<bindings>
<binding protocol="http" bindingInformation="10.61.90.44:80:" />
<binding protocol="https" bindingInformation="10.61.90.44:443:" />
<binding protocol="http" bindingInformation="10.61.90.44:8081:" />
</bindings>
So, as soon as my web app tries to call the service on localhost (or 127.0.0.1 for that matter) it fails instantly.
Needless to say, if I rdp on to the server and change the binding then all is fine.
What I find really odd is that there are tons of examples out there where people are accessing WCF services on localhost on Azure so I can't figure out why this is so. I have set the osFamily to 2 and in order to debug this I have enabled web publishing and remote desktop access which I guess, in theory, could mess things up.
What I have already looked at
I can rewrite the end-point address in my code at runtime to substitute localhost for the actual address or create the endpoint dynamically as described by Ron in the answers. Unfortunately I am using the WCF Routing service so I can version workflows. This means that my code calls the Router endpoint and the WCF Router in turns calls the actual service/workflow using an endpoint specified in web.config. I don't have control over the Routing services endpoint resolution without, I think, writing a whole set of routing logic which just seems to be a lot of work when all I want is to call localhost :)
Switching to using named pipes; Alas, it causes some strange issues with workflows, probably due to duplexing, and I am on a deadline so haven't got time to get to the bottom of that at the minute.
You have to build the endpoint address dynamically.
Step 1:
In your ServiceDefinition.csdef you need to declare an Endpoint.
<ServiceDefinition name="MyFirstAzureWorkflow" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="WorkflowWeb" vmsize="ExtraSmall">
<Sites>
<Site name="Web">
<Bindings>
<Binding name="Endpoint1" endpointName="WorkflowService" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="WorkflowService" protocol="http" port="80" />
</Endpoints>
<Imports>
<Import moduleName="Diagnostics" />
</Imports>
</WebRole>
</ServiceDefinition>
Step 2:
When you want to call the service
var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["WorkflowService"].IPEndpoint;
var uri = new Uri(string.Format(
"http://{0}:{1}/MyService.xamlx",
endpoint.Address,
endpoint.Port));
var proxy = new ServiceClient(
new BasicHttpBinding(),
new EndpointAddress(uri));
Okay, so this is how I solved it. IMHO it's a hack but at least it works.
Basically, I need to add a "*" binding, so I can do this in Powershell. The general recipe is here: http://blogs.msdn.com/b/tomholl/archive/2011/06/28/hosting-services-with-was-and-iis-on-windows-azure.aspx
That deals with adding Named Pipes support, but the principle is the same. I just changed the Powershell script to:
import-module WebAdministration
# Set up a binding to 8080 for the services
Get-WebSite "*Web*" | Foreach-Object {
$site = $_;
$siteref = "IIS:/Sites/" + $site.Name;
New-ItemProperty $siteref -name bindings -value #{protocol="http";bindingInformation="*:8080:"}
}
This now allows me to use http://127.0.0.1:8080/service.svc to access my service.
Note: You do need to follow the rest of the recipe to set elevated execution context and change the powershell execution mode, so do follow it carefully
I am trying to achieve the following:
Have one 'full' set of services for consumption by internal apps
Expose a subset of these methods to 3rd parties
The way I have tried to go about this is to create one service that implements two interfaces
For example:
Public Service Interface
[ServiceContract(Namespace = "http://www.myurl.com/public/2011/10")]
public partial interface IPublicService
{
[OperationContract]
ResponseObjOne OperationAvailableToEveryone(RequestObjOne request);
}
Private Service Interface
[ServiceContract(Namespace = "http://www.myurl.com/private/2011/10")]
public partial interface IPrivateService
{
[OperationContract]
ResponseObjOne OperationAvailableToEveryone(RequestObjOne request);
[OperationContract]
ResponseObjTwo OperationAvailableInternally(RequestObjTwo request);
}
Service class to implement both interfaces
public class Service : IPrivateService, IPublicService
{
ResponseObjOne OperationAvailableToEveryone(RequestObjOne request)
{ }
ResponseObjTwo OperationAvailableInternally(RequestObjTwo request)
{ }
}
I would now like to be able to configure this to run as two separate endpoints in IIS. So I have an .svc file with the following:
<%# ServiceHost Language="C#" Debug="true" Service="Adactus.Pulse.SOAServices.Service, Adactus.Pulse.SOAServices" %>
And added the following in the web.config:
<service name="Service">
<endpoint address="/public" binding="basicHttpBinding" contract="IPublicService" />
<endpoint address="/private" binding="basicHttpBinding" contract="IPrivateService" />
</service>
But if I browse to the .svc file I now see all operations in the WSDL and if I add /public to the URL I see a 404. So how can I achieve this?
Ideally I would like to add another .svc endpoint and be able to specify the interface as well as the service implementation class in these svc files. Then I can lock down access to the svc in IIS to secure the internal service.
the key is that some of the operations are exposed in both contracts and I don't want to duplicate their implementation.
Any ideas? Am I going about this in the wrong way?
Cheers,
Rob
While it doesn't answer your question, I would definitely not design it this way. I would create a single class library that includes both interfaces and the implementations for them and then I would create separate WCF projects that expose the different interfaces.
Observations: Your Service class to implement both interfaces seems wrong. both interfaces have same method name OperationAvailableToEveryone infact you have to implement your interfaces explicitly.
I even have same query. Infact you cannnot browse with http://localhost:8001/service.svc/public instead http://localhost:8001/public/service.svc. still you can create proxy with http://localhost:8001/service.svc and you use it as normal and your client enpoint address looks like
</client>
<endpoint address="http://localhost:8001/SOAService.svc/public"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IPublicService"
contract="SOAService.IPublicService" name="BasicHttpBinding_IPublicService" />
<endpoint address="http://localhost:8001/SOAService.svc/private"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IPrivateService"
contract="SOAService.IPrivateService" name="BasicHttpBinding_IPrivateService" />
</client>
Hope this helps.
My WCF service exposes an https AND an http endpoint. Apart from the SSL they are identical. They map to the same code.
The ultimate intention is for external users to connect via https, internal users to use http.
In development this gives me a problem. Cassini, the development web server packaged in VS, hates SSL.
I'm wondering if I can configure the service from code, so when running under Cassini, I would not configure https.
Hence the question - How do I configure the service from code if it is IIS hosted? I'd be very happy with alternative answers on how I can persuade Cassini to NOT complain about the https part of the configuration.
"IIS will take care of spinning up the necessary ServiceHost based on your *.svc file - not a whole lot you can do about that, really."
Not too close to the truth. Exactly in the SVC file of your service there is attribute named Factory. Where you can specify the the class and the assebly where the class is located. This class may be your own descendant of Web|DataServiceHostFactory
So your svc markup would look like this
<%# ServiceHost
Language="C#"
Debug="true"
Service="name.space.myService"
CodeBehind="name.space.myService.svc.sc"
Factory = "name.space.WebServiceHostFactoryEx, assembly.name"
%>
The WebServiceHostFactory will be created for every service hit and will recreate your host the way you want it.
You will also need to inherith WebServiceHost and create it the way you need it with certain endpoins, behaviors, addresses, etc settings - whatever you like.
There is very nice post from Michele Bustamante here
EDIT: I figured out the above link is not working anymore, so here it is another one.
I am using this in IIS hosted enviroment for couple of services that are initialized same way.
When you're hosting in IIS, you're leaving a lot of care taking into the realm of IIS - you cannot really grab a hold of your service in this case.
IIS will take care of spinning up the necessary ServiceHost based on your *.svc file - not a whole lot you can do about that, really.
My solution would be different - externalize the <service> tag in your configuration file (web.config):
<system.serviceModel>
<services>
<service configSource="service.dev.config" />
</services>
</system.serviceModel>
In your dev environment, only expose the http endpoint - so your service.dev.config would look something like this:
<service name=".....">
<endpoint name="default"
address="....."
binding="basicHttpBinding" bindingConfiguration="insecure"
contract="......" />
</service>
Create a second service.prod.config which then contains both endpoints - http and https:
<service name=".....">
<endpoint name="default"
address="....."
binding="basicHttpBinding" bindingConfiguration="insecure"
contract="......" />
<endpoint name="secure"
address="....."
binding="basicHttpBinding" bindingConfiguration="secure"
contract="......" />
</service>
and reference that in your web.config on the deployment server.