WCF using Reverse proxy - c#

My apologize for long post...
We have a WCF service written in .Net 4.0 used internally within the organization. Recently there was a requirement to make this service available outside the organization network. So the network guys used reverse proxy to make this service available outside the organization. Here is the picture how it is set up.
As you can see in the picture..the service http://mywebservice.com/readd.svc is hosted on WIndows 2008 R2 which has a internal IP address as XXX.YYY.ZZZ.RRR. The service is hosted on port 80.
what is the problem ?.
Internally I can access the service as http://mywebservice.com/readd.svc using WCFTestClient and browser. But outside the organization if I type http://mywebservice.com/readd.svc I get "404 file not find error" and in WCFTestCleint I get error as "Error: Cannot obtain Metadata from http://mywebservice.com/readd.svc .........".
However if I type in the service as in browser I get the screen which shows soap link as shown below. Please ignore the LookUpService.svc name mismatch.
As you can see in above figure ...address bar is https , but the soap link is http . If I click the http link http://.... ?wsdl , I get not found error. This is since Reverse proxy only allows connection as https .
If I use WCFTextClient and add servicie as https://mywebsite.com/readd.svc I get error as below.
"Error: Cannot obtain Metadata from https://mywebsite.com/readd.svc 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: http://mywebsite.com/readd.svc Metadata contains a reference that cannot be resolved:
'https://mywebsite.com/readd.svc'. Content Type application/soap+xml; charset=utf-8 was not supported
by service https://mywebsite.com/readd.svc.
The client and service bindings may be mismatched.
The remote server returned an error: (415) OK.HTTP GET Error
URI: https://mywebsite.com/readd.svc
The document at the url http://mywebsite.com/readd.svc was not recognized
as a known document type.The error message from each known type may help you
fix the problem:- Report from 'XML Schema' is
'The document format is not recognized (the content type is 'text/html; charset=UTF-8').'.-
Report from 'http://mywebsite.com/readd.svc' is
'The document format is not recognized (the content type is 'text/html; charset=UTF-8').'.-
Report from 'DISCO Document' is 'There was an error downloading 'http://mywebsite.com/readd.svc?disco'.'. -
The request failed with HTTP status 404: Not Found.- Report from 'WSDL Document' is 'The document format is not recognized (the content type is 'text/html; charset=UTF-8').'. "
I was informed by network guys to make service available as https. Here is my web.config file
<behaviors>
<serviceBehaviors>
<behavior name="ServiceLookup.LookupServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="ServiceLookup.LookupServiceBehavior" name="SmallApp.ServiceLookUp.LookUpService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="BSBindingConfig" name="SmallApplianceBSEndPoint"
contract="SmallApp.ServiceLookUp.ILookupService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<!-- Remove this during deployment-->
<!--<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>-->
Can you suggest how I can resole this issue ..so that users outside organization can access the api with WCFTestCleint as http/https .
Updated web.config file
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceLookup.LookupServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl="" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="ServiceLookup.LookupServiceBehavior" name="SmallApp.ServiceLookUp.LookUpService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="BSBindingConfig" name="SmallApplianceBSEndPoint"
contract="SmallApp.ServiceLookUp.ILookupService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<!-- Remove this during deployment-->
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
I am still gettign error accessing as http or https outside organization network

The WSDL is typically generated on the fly based on your models metadata, attributes, and host location. So if the wsdl is then proxied to another environment, it's going to have issues.
One escape hatch in servicemetadata is to specify a externalMetadataLocation:
A Uri that contains the location of a WSDL file, which is returned to the user in response to WSDL and MEX requests instead of the auto-generated WSDL.
Add externalMetadataLocation like this below:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"
externalMetadataLocation="https://example.com/SOAP/Service1.wsdl" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
You can then pre-generate your WSDL ahead of time, tweak at will, and upload the modified file to serve as the contract.
Further Reading
Supply a different endpoint address in the WSDL of a WCF web service
WCF behind a public reverse proxy which is used for traffic encryption
WebService behind reverse proxy
WCF Webservice behind public reverse proxy
Fix the Endpoint Address When Using externalMetadataLocation

Related

add service reference only works with localhost wcf service

I am trying to host a svc service in my web application and I am trying to connect to it with a simple client application.
When the host is hosted in my own computer and solution, and I run the web application locally, everything works fine, meaning that I can add the reference to the service using add service reference in my client solution with http://localhost:6543/Hello.svc as the address and when I navigate to the service's url, it shows me the service's information as it should.
But when I publish my website, and I try to add the reference to my service using add service reference with http://myserver.com/Hello.svc as the address, i get the error message bleow:
There was an error downloading
'http://myserver.com/Hello.svc/_vti_bin/ListData.svc/$metadata'. The
request failed with HTTP status 404: Not Found. Metadata contains a
reference that cannot be resolved: 'http://myserverc.com/Hello.svc'.
The remote server returned an unexpected response: (405) Method Not
Allowed. The remote server returned an error: (405) Method Not
Allowed. If the service is defined in the current solution, try
building the solution and adding the service reference again.
and oddly when I navigate to myserver.com/Hello.svc, the browser starts to download the Hello.svc file instead of showing the service's details and information.
this is my website's web.config file:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="crossDomain" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="WithDebug">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service name="HelloWorldService.HelloService" behaviorConfiguration="WithDebug">
<host>
<baseAddresses>
<add baseAddress="http://myserver/Hello.svc"/>
</baseAddresses>
</host>
<endpoint
address=""
binding="webHttpBinding" bindingConfiguration="crossDomain"
contract="HelloWorldService.IHelloWorld" />
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
I think I am missing something big here, but since I am new to WCF, I don't know what it is.Any help would be appreciated and I am more than happy to issue more details about my project if needed.
Thanks in advance
You need to run ServiceModel registration tool
"This command-line tool provides the ability to manage the registration of WCF and WF components on a single machine. Under normal circumstances you should not need to use this tool as WCF and WF components are configured when installed. But if you are experiencing problems with service activation, you can try to register the components using this tool."

WCf REST service client side config file empty

I have a REST service and I have added it's reference in my WPF application. But as soon as I create a client of my proxy, it throws error and it throws error because my client side app.config is empty:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</configuration>
This line on client throws error:
HelloWorldClient client = new HelloWorldClient();
This is my system.servicemodel section of web.config on the server side:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service name="WCFRestExample.HelloWorld">
<endpoint address="" binding="webHttpBinding" contract="WCFRestExample.IHelloWorld"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Can anybody tell me why is app.config empty? I have also restarted VS2010 but no luck.
NOTE: When I directly browse it in the browser the service is working. So, there is no problem with server side service.
Thanks in advance :)
As some other posts mentioned (such as After creating a wcf service how do I tell whether its restful or soap from the wsdl? and Create a WCF Proxy for a Rest Web Service, among others), Add Service Reference does not work for REST endpoints. You'll need to create the client yourself.
Another issue in your web.config: in order to create a REST endpoint, you need both to have the webHttpBinding (which you do) and add a <webHttp/> endpoint behavior to your endpoint (which you don't).

Why do I have to specify my address in my WCF configuration (it is actually working)

I have set up a wcf service and when I browse to the .svc file I am presented with a screen that says...
You have created a service.
So I know that the service is running successfully. However I have looked in the configuration and it does not actually have an address.
<system.serviceModel>
<services>
<service behaviorConfiguration="CountryProvinceBehavior" name="CountryProvinceWCFService">
<endpoint address="" binding="webHttpBinding" contract="ICountryProvinceWCFService" behaviorConfiguration="CountryProvinceBehavior"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CountryProvinceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="CountryProvinceBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
I then wrote a console app to test the service.
I got thr url from the browser and added a 'Service Reference' from a console application I was expecting the project to create enpoint defintions in my configuration file. And then when I create a client I could load up one of these configs but they aren't there....
You don't have to specify the address in configuration, although in this case you do specify the address for the endpoint (""). That means that WCF will use it as an address relative to the service base address. If the service is hosted in IIS, then it'll be the address of the .svc file. If the service is self-hosted (i.e., using ServiceHost directly), then the address will be the one passed to the ServiceHost constructor.

I've created a WCF service and now I want to call it from a reference but why InvalidOperationException?

I've written a WCF service. I have successfully browsed to the service and it says:
You have created a service.
So then I add a reference to it using a the 'Add Service Reference' in visual studio. Then I write the following code to consume it....
ServiceReference1.VLSContentServiceClient client = new ServiceReference1.VLSContentServiceClient("VLSContentServiceEndpointBehaviour");
List<ServiceReference1.Category> cats = client.GetCategoriesByGET();
But im getting the error:
Could not find endpoint element with
name
'VLSContentServiceEndpointBehaviour'
and contract
'ServiceReference1.IVLSContentService'
in the ServiceModel client
configuration section. This might be
because no configuration file was
found for your application, or because
no endpoint element matching this name
could be found in the client element.
It makes no sense because the argument 'endPointConfigurationName' matches what I have set it to in the service. Here is the service configuration:
<system.serviceModel>
<services>
<service behaviorConfiguration="VLSContentServiceBehaviour" name="VLSContentService">
<endpoint address="" behaviorConfiguration="VLSContentServiceEndpointBehaviour" binding="webHttpBinding" contract="IVLSContentService"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="VLSContentServiceBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="VLSContentServiceEndpointBehaviour">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Whats going on?
You are using REST service - client for such service cannot be created with Add service reference. That is only for SOAP services (no webHttpBinding and webHttp behavior). Also once you use SOAP service you don't pass name of any server side feature to the constructor of the proxy. The proxy constructor expects name of client endpoint from client's configuration.
How to consume REST service
Looks like your contract is not correct. you have:
contract="IVLSContentService"/>
and it is expecting:
contract="ServiceReference1.IVLSContentService"/>
according to the error message.
also your endpoint address is empty. Does that not need to contain something?
The VLSContentServiceEndpointBehaviour parameter while creating an instance of client is the Name of the endpoint and not the endpoing behaviour.
Change
<endpoint address="" behaviorConfiguration="VLSContentServiceEndpointBehaviour" binding="webHttpBinding" contract="IVLSContentService"/>
to
<endpoint address="" name ="Client" behaviorConfiguration="VLSContentServiceEndpointBehaviour" binding="webHttpBinding" contract="IVLSContentService"/>
and create a service client as
ServiceReference1.VLSContentServiceClient client = new ServiceReference1.VLSContentServiceClient("Client");
Also your address is missing which is bit strange.

Unable to properly reference a wcf dataservice

I'm having a couple of issues which may be related, or may not. I noticed that when I use Add Service Reference in Visual Studio to add a reference to my data service, the reference.cs it generates does not compile. It complains about a missing namespace. I can fix it up to compile, but this happens every time I update the reference, and it's worrying on other levels too, such as "will this cause other issues".
I also noticed that when I do this, my host server (a console application hosting the data service) logs this:
An exception occurred [System.Data.Services.DataServiceException] :: The URL
representing the root of the service only supports GET requests.
This is the service config:
<service behaviorConfiguration="behaviour" name="StatsPlus.Server.HostedServices.SPDataServiceHost">
<endpoint address="svc" binding="webHttpBinding" contract="System.Data.Services.IRequestHandler" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8752/DataService/"/>
</baseAddresses>
</host>
</service>
And the behaviour:
<behavior name="behaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="10"/>
</behavior>
When I try to run svcutil http://localhost:8752/DataService/, I get this:
HTTP GET Error
URI: http://localhost:8752/DataService
There was an error downloading 'http://localhost:8752/DataService'.
The request failed with HTTP status 405: Method Not Allowed.
Any ideas? Much appreciated
Thanks
I think you're connecting to a wrong address. You have a base address
<add baseAddress="http://localhost:8752/DataService/"/>
and on top of that a relative endpoint address
<endpoint address="svc" binding="webHttpBinding"
so your complete URL will be the combination of the two:
http://localhost:8752/DataService/svc
Did you try to connect there??
I am not sure if you can have a "mex" metadata exchange endpoint with WCF REST services, really. I was under the impression that the client-side proxy for a WCF Data Service gets its metadata over a special URL call from the HTTP endpoint. So maybe try to remove that from your config as well (and you can't use svcutil on that service, I believe - svcutil is only for SOAP service calls, if I'm not mistaken).
Also, since you're using webHttpBinding and self-hosting, you need to add the webHttp behavior:
<behavior name="behaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="10"/>
<webHttp />
</behavior>
If you do these two steps, I think you should be able to get at your WCF Data Service. Try it and let us know!

Categories

Resources