WCF Configuration for Endpoint in Another Project - wcf

I have two projects in a single solution. One project, let's call it MainProject, becomes an executable. The other project, let's call it ControlsProject, contains UserControl's and is referenced (and used) within the MainProject. The ControlsProject also has a WCF Service Reference.
I have a two questions regarding this configuration:
Can I just copy the WCF configuration from the ControlsProject to the MainProject (which I don't believe I can per " How to include Web reference endpoint configuration in another project ")
In the ControlsProject configuration, the contract doesn't have a fully qualified namespace but rather a name such as 'ServiceName.IServiceInterfaceName'. What should the contract name be since the ControlsProject output will be a file located in the bin folder of the MainProject?
I've tried just copying the configuration over, but received the exception: "Could not find default endpoint element that references contract 'MyService.IMyService' 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 contract could be found in the client element." When I copied over the configuration, I fully qualified the name of the interface as ControlsProject.MyService.IMyService.
Any help you can provide is appreciated!
UPDATE (7/14/2011 5:28pm EST)
Here is the snippet from my client app.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IStatService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://intranet/StatService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IStatService"
contract="StatService.IStatService" name="BasicHttpBinding_IStatService" />
</client>
</system.serviceModel>
Here is the snippet from my web service web.config:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

Anytime you see the "Could not find default endpoint element for such and such contract" then your actual contract (the interface) is not referenced correctly in the app.config file. Go to the interface contract in the controls project double check the namespace it's in, you need that exact namespace."Interface name" as the contract element in the app.config. You also need to make sure your service name=Namespace.MyService is the correct namespace and class. One short way to know if you're right (this is only if you have resharper), in the appconfig where you declare service name= put the cursor over the service name and namespace and hit F12, if it doesn't take you anywhere you're referencing a namespace and class that don't exist, same goes for the contract=, if you F12 on that contract and it doesn't take you there, it's not referenced correctly (possibly misspelled).

Related

WCF Error A SOAP 1.2 message is not valid when sent to a SOAP 1.1 only using wsHttpBinding

I am trying to consume a service which I have no control over and have been given just the WSDL to consume. The service requires a certificate for authentication. My configuration for the certificate is fine and I get an error when I try and call the service as below:
The content type text/xml;charset=UTF-8 of the response message does
not match the content type of the binding (application/soap+xml;
charset=utf-8). If using a custom encoder, be sure that the
IsContentTypeSupported method is implemented properly. The first 274
bytes of the response were: 'soap:VersionMismatchA SOAP 1.2 message is not valid when sent to a SOAP 1.1 only
endpoint.'.
I have tried different this like using a customBinding but I landed up with a total new number of more errors and feel am not getting anyway. Can you please assist?
Client Config:
<system.serviceModel>
<client>
<endpoint name="IDeliveryServiceImplPort"
address="WebServiceUrl"
binding="wsHttpBinding"
bindingConfiguration="wsHttpBinding"
behaviorConfiguration="wsHttpCertificateBehavior"
contract="IDeliveryService">
<identity>
<dns value="MyIdentity" />
</identity>
</endpoint>
</client>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false"
hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8"
useDefaultWebProxy="true" allowCookies="false">
<readerQuotas
maxDepth="32" maxStringContentLength="8192"
maxArrayLength="16384" maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<reliableSession enabled="false" ordered="true" inactivityTimeout="00:10:00" />
<security mode="Transport">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
<customBinding>
<binding name="WsHttpSoap11" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00">
<textMessageEncoding messageVersion="Soap11WSAddressing10" />
<security authenticationMode="MutualCertificate" />
<httpsTransport requireClientCertificate="true" />
</binding>
</customBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="wsHttpCertificateBehavior">
<clientCredentials>
<clientCertificate x509FindType="FindBySubjectName" findValue="MyIdentity" storeLocation="LocalMachine" storeName="My" />
<serviceCertificate>
<defaultCertificate x509FindType="FindBySubjectName" findValue="MyIdentity" storeLocation="LocalMachine" storeName="My" />
<authentication certificateValidationMode="PeerOrChainTrust" revocationMode="NoCheck" trustedStoreLocation="LocalMachine" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
I have managed to figure it out with tweaks and trials. In order to solve is I change to basicHttpsBinding which took me another day or two to figure out the default transport clientCredentialType is None and you need to configure a custom binding as below. I wish WCF would tell you why or give a solution to error you get, because it was such a pain. From one error description to the next nonstop.
<bindings>
<basicHttpsBinding>
<binding name="SecureHubBinding">
<security>
<transport clientCredentialType="Certificate" />
<message clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpsBinding>
</bindings>
Are these configurations automatically generated by adding service reference? We can use the WSDL file of the service to generate the binding information used by the server-side and add the service reference to generate the client proxy class.
In addition, if the service with transport security mode authenticates the client with a certificate, please guarantee that below requirements.
The trusted relationship between the client-side and the server-side
should be established. Install mutual certificates in the Local CA.
These two certificates should be accessed by the WCF application.
Please add the Everyone account (or the account running the WCF
application) to the management group of the certificate private key.
Both two certificates should have the client authentication intended
purpose and the server authentication intended purpose.
Feel free to let me know if there is anything I can help with.

WCF metadata shows incorrect service URI on HTTPS

Using .NET 4.7.1 and minimal WCF configuration, the WSDL, when accessed from HTTPS, shows a HTTP address, and shows the incorrect host unless port 80 is enabled in the configuration.
This service should only be available on HTTPS, which will be enforced by a firewall rule further along.
My configuration looks like this
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpsGetEnabled="True"/>
<useRequestHeadersForMetadataAddress/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
And the result looks like this in a browser (demonstrating incorrect scheme and incorrect host. Sorry that I must block out most of this, but you should be able to get what I'm saying...)
resulting wsdl
I understand that "useRequestHeadersForMetadataAddress" tells WCF that I indeed want the WSDL right next to the service. I assumed it also should be able to handle the same intentions for scheme.
Any thoughts?
My issue was assuming I didn't need to specify binding configuration. Without binding configuration, I don't think WCF can figure out you want HTTPS bindings, and all problems flowed from there.
So, unfortunately, my web.config grows to twice its size!
<basicHttpBinding>
<binding name="SecureServiceBinding" closeTimeout="00:02:00" openTimeout="00:02:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="20480000" maxBufferSize="10240000" maxReceivedMessageSize="10240000" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true" messageEncoding="Text">
<readerQuotas maxDepth="100" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="2147483647"/>
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
<message clientCredentialType="UserName" algorithmSuite="Default"/>
</security>
</binding>
</basicHttpBinding>

Calling a webservice from a C# dll from within CLASSIC ASP

I'm a windows dev with very little knowledge of web applications and ASP. I'm trying to create a C# dll (which is making a webservice call) for someone, that is being called from a CLASSIC ASP app.
It all started from a WinForms test app that successfully loaded a WSDL and called that web service. Now the requirement is to take the test app functionality, move it to a dll and call that dll from the ASP app. I naively left the appconfig file there, and when that dll was called, he got this well known error:
Could not find default endpoint element that references contract Service1.MyService 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 contract could be found in the
client element.
I understand that classic asp doesn't have config files - I read a lot of posts about it, and most of the relevant ones mention to use BasicHTTPBinding and provide an endpoint address on the fly. How do I do that? Any examples?
I saw this answer:
All I needed to do is to create a BasicHTTPBinding and provide an endpoint address on the fly.Then create a new instance of the web service using the created binding and endpoint address.
But i'm not sure how to do it.
This is the appconfig that worked for the winforms app:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService">
<security mode="Transport">
<transport clientCredentialType="Certificate" proxyCredentialType="None"
realm="" />
</security>
</binding>
<binding name="BasicHttpBinding_ICustomerService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://MyService.svc"
behaviorConfiguration="custom" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IMyService" contract="MyService.IMyService"
name="BasicHttpBinding_IMyService" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="custom">
<customInspector />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="customInspector" type="CustomBehaviors.CustomBehaviorExtensionElement, CompeteDataServiceTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
You will need to configure the service through code, as there is no config file in this case. See Configuring WCF Services in Code.

configuring WCF with <services> tag

I am trying to solve a WCF error found in my previous question. Basically, the error is:
The maximum string content length quota (8192) has been exceeded while reading XML data.
And someone suggested to use a services tag in my web.config to resolve my issue.
Now, I am facing a different problem. I can’t figure out how am I suppose to configure the services tag in my web.config to work correctly on my server. I always get the following error when I try to use the services tag:
The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.
Here is my web.config with the services tag added:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding
name="BasicHttpBinding_Service1"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00"
sendTimeout="00:01:00"
allowCookies="false"
bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536"
maxBufferPoolSize="524288"
maxReceivedMessageSize="65536"
messageEncoding="Text"
textEncoding="utf-8"
transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas
maxDepth="32"
maxStringContentLength="10000"
maxArrayLength="16384"
maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint
address="http://localhost:53931/WCF/Service1.svc"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_Service1"
contract="ServiceReference.Service1"
name="BasicHttpBinding_Service1" />
</client>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<!--PROBLEM SOMEWHERE IN THE SERVICES TAG-->
<services>
<service
behaviorConfiguration="NewBehavior"
name="AspPersonalWebsite.ServiceReference">
<endpoint
address="http://localhost:53931/WCF/Service1.svc"
binding="basicHttpBinding"
contract="ServiceReference.Service1"
bindingConfiguration="BasicHttpBinding_Service1" />
</service>
</services>
Please note that by removing the services tag everything works fine, but then I will not be able to resolve my original problem posted on my previous question.
so could someone please tell me if I am doing something wrong on my web.config, specifically in my services tag?!
Okay, let's tackle this:
First, you need to define a custom basicHttpBinding binding configuration with some custom settings:
<bindings>
<basicHttpBinding>
<binding name="LargeSettings"
maxBufferSize="524288"
maxBufferPoolSize="524288"
maxReceivedMessageSize="6553600">
<readerQuotas maxDepth="32" maxStringContentLength="100000"
maxArrayLength="16384" maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
This section needs to be in both your server-side's web.config, as well as your client side's config.
Secondly, on the server-side, you need to have a <services> tag that defines your service and its endpoints and their configuration:
<services>
<service name="YourNamespace.YourClassName"
behaviorConfiguration="ServiceWithMetadata">
<endpoint name="Default"
address="http://localhost:53931/WCF/Service1.svc"
binding="basicHttpBinding"
bindingConfiguration="LargeSettings"
contract="YourNamespace.IServiceContract" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceWithMetadata">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
Points to check:
your service name must be the fully qualified name (YourNamespace.YourClassName) of your service class - the class that implements your service contract
your service contract in the endpoint must also be the fully qualified name of your service contract (YourNamespace.IYourServiceContract)
the behaviorConfiguration of your <service> tag must reference and match exactly to the name= attribute as defined in your <behaviors> section
And thirdly, on the client side, you need something like this:
<client>
<endpoint name="Default"
address="http://localhost:53931/WCF/Service1.svc"
binding="basicHttpBinding"
bindingConfiguration="LargeSettings"
contract="ServiceReference.IYourService" />
</client>
You need to reference the endpoint defined in your service's definition on the server side, you need to use the same binding and binding configuration, and you need to use the service contract as defined in your service reference.
For those using the built in service reference, just use the .Endpoint.Binding =THE NEW BINDING
ex:
BasicHttpBinding b = new BasicHttpBinding();
b.Security.Mode = BasicHttpSecurityMode.Transport;
...
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
MyWebServiceReference.ServiceReferenceSoapClient objRE = new MyWebServiceReference.ServiceReferenceSoapClient("ServiceReferenceSoap", "URI");
objRE.Endpoint.Binding = b;
Use this setting for the your bindings,
<basicHttpBinding>
<binding maxReceivedMessageSize="2147483647" messageEncoding="Text" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" >
<readerQuotas maxStringContentLength="525288"></readerQuotas>
</binding>
</basicHttpBinding>

Strange exception when connecting to a WCF service via a proxy server

The exception "This operation is not supported for a relative URI." occurs in the following situation:
I have a WCF service:
[ServiceContract(ProtectionLevel=ProtectionLevel.None)]
public interface IMyService
{
[OperationContract]
[FaultContract(typeof(MyFault))]
List<MyDto> MyOperation(int param);
// other operations
}
public class MyService : IMyService
{
public List<MyDto> MyOperation(int param)
{
// Do the business stuff and return a list of MyDto
}
// other implementations
}
MyFault and MyDto are two very simple classes marked with [DataContract] attribute and each only having three [DataMember] of type string, int and int?.
This service is hosted in IIS 7.0 on a Win 2008 Server along with an ASP.NET application. I am using an SVC file MyService.svc which is located directly in the root of the web site. The service configuration in web.config is the following:
<system.serviceModel>
<services>
<service name="MyServiceLib.MyService">
<endpoint address="" binding="wsHttpBinding"
bindingConfiguration="wsHttpBindingConfig"
contract="MyServiceLib.IMyService" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBindingConfig">
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
This seems to work so far as I can enter the address http://www.domain.com/MyService.svc in a browser and get the "This is a Windows Communication Foundation Service"-Welcome page.
One of the clients consuming the service is a console application:
MyServiceClient aChannel = new MyServiceClient("WSHttpBinding_IMyService");
List<MyDto> aMyDtoList = aChannel.MyOperation(1);
It has the following configuration:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IMyService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="true" transactionFlow="false"
hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="false"
proxyAddress="10.20.30.40:8080" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192"
maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="None">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows"
negotiateServiceCredential="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://www.domain.com/MyService.svc" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IMyService"
contract="MyService.IMyService"
name="WSHttpBinding_IMyService" />
</client>
</system.serviceModel>
When I run this application at a production server at a customer site calling aChannel.MyOperation(1) throws the following exception:
This operation is not supported for a relative URI.
When I run this client application on my development PC with exactly the same config, with the exception that I remove proxyAddress="10.20.30.40:8080" from the bindings the operation works without problems.
Now I really don't know what specifying a proxy server address might have to do with absolute or relative URIs. The use of the proxy server or not is the only difference I can see when running the client on the production or on the development machine.
Does someone have an idea what this exception might mean in this context and how possibly to solve the problem?
Thank you in advance for help!
Edit:
In case it should be important: Service and Client are built with WCF in .NET Framework 4.
10.20.30.40:8080 is not a valid URL. You want http://10.20.30.40:8080.
Here's my diagnostic thought process, in case it helps anyone:
Exceptions don't usually lie. They usually mean just exactly what they say. The trick is to understand how they could possibly be telling the truth.
The exception said, "This operation is not supported for a relative URI". If that were true, then it meant that an operation was being performed, it was being given a relative URL, but it doesn't support relative URIs.
The OP then said that when he runs the application "with the exception that I remove proxyAddress="10.20.30.40:8080" from the bindings".
There, in front of me, was a relative URI. When he removed it, the "operation" worked, so I deduced that this was the relative URI that was supplied to the "operation" that doesn't support them.
You don't exactly have to be Sherlock Holmes to solve this one. The key was being able to instantly see that there was no scheme:// in front of the URI, making it relative.