Two endpoints in WCF 3.5 for SOAP and JSON - wcf

I dont know what I am doing wrong. I have a WCF (.NET 3.5) service (JsonSoap.svc) that has two endpoints for soap and json content type. Both the endpoints refer to the same service. I am using only one Json endpoint in the client. My aim is to have the service method GetPerson() to return Json or soap depending on the endpoints used to connect to the service (hopefully this is possible in WCF?). I can see wsdl and was able to successfully ad the service reference in to the client side.
I get the following error after I make a call to the GetPerson() -
"An error occurred while receiving the
HTTP response to
http://localhost:80/JsonSoap/json/GetPerson.
This could be due to the service
endpoint binding not using the HTTP
protocol. This could also be due to
an HTTP request context being aborted
by the server (possibly due to the
service shutting down). See server
logs for more details."
WCF service config
<!-- bindings -->
<bindings>
<basicHttpBinding>
<binding name ="soapBinding">
<security mode="None">
</security>
</binding>
</basicHttpBinding>
<webHttpBinding>
<binding name="webBinding">
</binding>
</webHttpBinding>
</bindings>
<!-- JSON behaviors -->
<endpointBehaviors>
<behavior name="jsonBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="defaultBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="TestService.IJsonSoap" behaviorConfiguration="defaultBehavior">
<host>
<baseAddresses>
<!-- note, choose an available port-->
<add baseAddress="http://localhost:80/JsonSoap" />
</baseAddresses>
</host>
<endpoint address="soap" binding="basicHttpBinding"
bindingConfiguration="soapBinding"
contract="TestService.IJsonSoap" />
<endpoint address="json" binding="webHttpBinding"
bindingConfiguration="webBinding"
behaviorConfiguration="jsonBehavior"
contract="TestService.IJsonSoap" />
</service>
WCF code:
[OperationContract]
[WebGet]
Person GetPerson(int ID);
WCF Client config:
<endpoint address="http://localhost:80/JsonSoap/json" binding="webHttpBinding"
bindingConfiguration="webBinding" behaviorConfiguration="jsonBehavior"
contract="MyService.IJsonSoap" />
Client code:
MyService.JsonSoapClient service = new JsonSoapClient();
MyService.Person person = service.GetPerson(10);

This will not work. WSDL servers only for SOAP services and it is the source for Add Service Reference in Visual Studio. You are using client code generated by Visual Studio but you are using it with Json endpoint which doesn't work.
Json endpoint represents REST service. To call WCF REST service in .NET you must either:
Build manully HTTP Request
Share service contract with a client and use ChannelFactory or WebChannelFactory to build a proxy
Use REST Starter KIT CTP2 and its HttpClient class (not recommended because development of REST Starter KIT ended).

Related

Activation error in WCF web-service using basicHttpBinding, Windpws-Authentication & impersonation

I am trying to host a WCF web service in IIS using Windows Authentication. Due to restrictions, we have to use the basicHttpBinding & use impersonation (impersonate the caller's identity for accessing resources down the chain).
I have declaratively enabled impersonation on the operation contract of my WCF service:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
My web.config is:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="basic">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows">
</transport>
</security>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service name="NotesService">
<endpoint address="http://Client1.osp.local:15000/NotesService/NotesService.svc" bindingConfiguration="basic" binding="basicHttpBinding" contract="NotesService.ServiceContract.INotesService">
<identity>
<servicePrincipalName value="HTTP/Client1.osp.local:15000"/>
</identity>
</endpoint>
</service>
</services>
</system.serviceModel>
However, I am getting an activation error. What am I missing?
The error I am getting is:
The contract operation 'Process' requires Windows identity for automatic
impersonation. A Windows identity that represents the caller is not provided by
binding ('BasicHttpBinding','http://tempuri.org/') for contract
('NotesService','http://tempuri.org/'.
Assuming you are using WCF 4.0, then I think you are seeing an artefact of a WCF 4 feature called default endpoints.
In the service name you need to provide the fully qualified name of the service (including the namespace). Assuming NotesService is in a namespace then when you create the ServiceHost it doesn;t find a match in the config file. If you supply an HTTP base address in the ServiceHost constructor then it will wire up the basicHttpBinding with its default configuration (no authentication) which would produce the error you are seeing

WCF with netTCPBinding

I have written wcf service
everything works fine when i deploy it on IIS7 with http binding.
I want to deploy the same on Windows Process Activation Services (WAS) using netcp binding.
when i try to create proxy for the service using svcutil
i am getting below error message:
Error: Cannot obtain Metadata from net.tcp://localhost/myservice/servi
ce.svc
If this is a Windows (R) Communication Foundation service to which you have acce
ss, please check that you have enabled metadata publishing at the specified addr
ess. For help enabling metadata publishing, please refer to the MSDN documentat
ion at http://go.microsoft.com/fwlink/?LinkId=65455.
WS-Metadata Exchange Error
URI: net.tcp://localhost/servicemodelsamples/service.svc
Metadata contains a reference that cannot be resolved: 'net.tcp://localhost/
servicemodelsamples/service.svc'.
here is web.config:
<system.serviceModel>
<services>
<service name="MyProj.Myservice"behaviorConfiguration="CalculatorServiceBehavior">
<!--This endpoint is exposed at the base address provided by host: net.tcp://localhost/servicemodelsamples/service.svc -->
<endpoint binding="netTcpBinding" bindingConfiguration="PortSharingBinding"contract="MyProj.ICalculator" />
<!--the mex endpoint is explosed at net.tcp://localhost/servicemodelsamples/service.svc/mex -->
<endpoint address="mex"binding="mexTcpBinding"contract="IMetadataExchange" />
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="PortSharingBinding" portSharingEnabled="true">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata />
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
Thanks,
on .net 4 check if "Net.Tcp Listener Adapter" service is using .net 4 version of SMSvcHost.exe (should be ...\v4.0.30319\SMSvcHost.exe)
If not repair installation of .net 4

Getting an Security setting exception while accessing a WCF service

Following are binding configurations of my WCF service.
Anonymous access: off
Basic authentication: on
Integrated Windows authentication: off !!
support HTTP protocol .
I am getting an following exception while accessing my WCF service:
Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MyBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType ="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="WMWcfWebServiceLib.Service1Behavior"
name="WMWcfWebServiceLib.WMWcfWebService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="MyBinding"
contract="WMWcfWebServiceLib.IWMWebService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/Design_Time_Addresses/WMWcfWebServiceLib/Service1/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WMWcfWebServiceLib.Service1Behavior">
<!-- 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="False" />
</behavior>
</serviceBehaviors>
</behaviors>
Please Help!!
Edit
I am able to access the WCF service through the web browser with the following changes:
Changes the security mode to TransportCredentialOnly and Removed the Mex Endpoint, but now as obvious I am not able to create the proxy on the client side.
Please let me know where I am wrong ?
If you want to support HTTP only your configuration is not used at all because mode="Transport" demands HTTPS. First find why config is not used (probably wrong type name in service element). Next change security mode to TransportCredentialOnly. But be aware that TransportCredentialOnly + Basic authentication means that HTTP requests will contain plain text Windows user name and password. In most cases such implementation will not pass any security audit.
Edit:
You can create proxy without mex endpoint if you still support httpGetEnabled in service metadata behavior.

Exposing WCF Services Via HTTP when not hosted in IIS

Like the title says, we need to set up WCF services between a .NET app, and a Adobe AIR app. We don't want to run IIS on the machine, and would much prefer to install and run the WCF services hosted within a windows service.
However, I am uncertain of doing that will let us use HTTP as the transport, of does that only work within IIS? I was able to set things up to use the TCP transport, but that doesn't interop with AIR nearly as nice as using HTTP.
EDIT: Some test code I've been using to see if this works:
Regular console app:
static void Main()
{
using (ServiceHost host = new ServiceHost(typeof(TestService)))
{
host.Open();
}
Console.WriteLine("Waiting...");
Console.ReadLine();
}
TestService is a simple HelloWorld type service.
In the App.Config:
<configuration>
<system.serviceModel>
<services>
<service name="WCFExample2.TestService" behaviorConfiguration="WCFExample2.TestServiceBehavior">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8731/Design_Time_Addresses/WCFExample2/Service1/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address ="" binding="wsHttpBinding" contract="WCFExample2.ITestService">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFExample2.TestServiceBehavior">
<!-- 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="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
You should have no trouble setting up a Windows NT Service which hosts your WCF service and exposes HTTP endpoints - no need for IIS (but the WCF runtime will use the http.sys kernel mode driver).
Have you tried and failed? If so - can you show us what you had, and how and where it failed?
As a bare minimum, you'd probably want to have something like this config on your service side:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="Default"
sendTimeout="00:05:00"
maxBufferSize="500000"
maxReceivedMessageSize="500000" >
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="Namespace.MyWCFService"
behaviorConfiguration="Default">
<host>
<baseAddresses>
<add baseAddress="http://MyServer:8282/MyWCFService/"/>
</baseAddresses>
</host>
<endpoint
address="basic"
binding="basicHttpBinding" bindingConfiguration="Default"
contract="Namespace.IMyWCFService" />
</service>
</services>
</system.serviceModel>
Of course, you might need to tweak things like the timeout settings, buffer size settings etc. on your binding, the security mode, and quite possibly other settings as you need them to be.
Marc
You could skip all the config and use the WebServiceHost class (which will do it all for you in a fairly standard way). Get that working then look into tailoring the config manually to meet any extra requirements you may have.
All the info you need is here WebServiceHost on MSDN it's a very straightforward way to get started on a custom (i.e. non IIS) hosted http service.
Mike
Apart from the config file settings one more thing to consider.
If you selfhost in a windows service, a http endpoint then
Make the service login account a local admin on the machine
or
You have to register the service account for the http namespace with http.sys.
This step has to be done by a local admin but only once in each machine. You can use the HttpSysCfg tool to do this in XP/win 2003. For vista/win 2008 use netsh.

IIS hosted WCF-service + Windows auth in IIS + TransportCredentialOnly/Windows auth in basicHttpBinding

I want to create a WCF-service hosted in IIS6 and disable anonymous authentication in IIS. And don't use SSL.
So only way I have is to use basicHttpBinging with TransportCredentialOnly, itsn't it?
I create a virtual directory, set Windows Integrated Auth and uncheck "Enable Anonymous Access".
Here's my web.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MyBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="Samples.ServiceFacadeService" behaviorConfiguration="ServiceFacadeServiceBehavior">
<endpoint address="" binding="basicHttpBinding" bindingName="MyBinding"
contract="Samples.IServiceFacadeService">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceFacadeServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
You can see that I even haven't included MEX-enpoint for metadata exchange. Just one endpoint and one binding for it with TransportCredentialOnly security.
But when I tries to start service (invoking a method throught client proxy) I got such exception in the EventLog:
Exception:
System.ServiceModel.ServiceActivationException:
The service
'/wcftest/ServiceFacadeService.svc'
cannot be activated due to an
exception during compilation. The
exception message is: Security
settings for this service require
'Anonymous' Authentication but it is
not enabled for the IIS application
that hosts this service.. --->
System.NotSupportedException: Security
settings for this service require
'Anonymous' Authentication but it is
not enabled for the IIS application
that hosts this service.
I have no idea why my service require Anonymous auth? Why?
The answer found jezell. Thanks.
I mixed up bindingName and bindingConfiguration :
<endpoint address="" binding="basicHttpBinding" bindingName="MyBinding"
contract="Samples.IServiceFacadeService">
</endpoint>
That's right:
<endpoint address="" binding="basicHttpBinding" **bindingConfiguration**="MyBinding"
contract="Samples.IServiceFacadeService">
</endpoint>
The MEX endpoint may still be the problem (see this post). Try disabling MEX like this:
<services>
<!-- Note: the service name must match the configuration name for the service implementation. -->
<service name="MyNamespace.MyServiceType" behaviorConfiguration="MyServiceTypeBehaviors" >
<!-- Add the following endpoint. -->
<!-- Note: your service must have an http base address to add this endpoint. -->
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors" >
<!-- This disables it. -->
<serviceMetadata httpGetEnabled="false" />
</behavior>
</serviceBehaviors>
</behaviors>
Here is a good post on securing MEX.
Use basicHttpBinding for your mex endpoint and apply the same bindingConfiguration:
To get VS wcf service project (new sample project) to work with authentication under IIS, you have to:
1) Allow Anonymous access in IIS
2) Prefix your public methods with a attribute like this:
[PrincipalPermission(SecurityAction.Demand, Role = "MyADGroup")]
public string SendMyMessage(string Message)
{...}