I am getting following error in my web application implementing WCF Service method 'Add Numbers'. I am using JSON response format:
Server Error in '/' Application. Operation 'AddNumbers' of contract
'ICalculator' specifies multiple request body parameters to be
serialized without any wrapper elements. At most one body parameter
can be serialized without wrapper elements.
Either remove the extra
body parameters or set the BodyStyle property on the
WebGetAttribute/WebInvokeAttribute to Wrapped.
I solved this issue after searching in the google.
Actually the problem is in web.config file of web application.
I changed a bit of code in it.I added <webHttp defaultBodyStyle="Wrapped"/>
only and hence Solved
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="AllocationBehavior">
<webHttp defaultBodyStyle="Wrapped" />
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint name="Default"
address="http://localhost:3876/Calculator.svc"
binding="webHttpBinding"
behaviorConfiguration="AllocationBehavior"
contract="ServiceReference1.ICalculator" />
</client>
Related
Background
I have created ASMX web services in the past and have been able to access the service from the web browser and Ajax GET requests using the address convention: MyService.asmx/MyMethod?Param=xxx
I just got started using WCF and created a new web service in my ASP.NET project. It creates a file with the .svc extension such as MyService.svc.
Current Situation
I am able to consume the service using the WcfTestClient that comes with VS2008. I am also able to create my own WCF Client by either adding a service reference in another project or using the svcutil.exe commandline to generate the proxy and config file.
The Problem
When I try to use the service from a browser using MyService.svc/MyMethod?MyParam=xxx, I get a blank page without any errors.
What I have tried
I have already added a basicHttpBinding to the web.config and made it HttpGetEnabled in the behavior configuration. I also added the [WebGet(UriTemplate = "MyMethod?MyParam={MyParam}")] attribute to my operation contract.
I have already followed the information in this other stack overflow question:
REST / SOAP EndPoints for a WCF Service
However, I either get a blank page or an HTTP 404 Error after following those steps. There's nothing special about the code. I am just taking in a string as a parameter and returning "Hello xxx". This is a basic "Hello WCF World" proof-of-concept type thing.
UPDATE - Here's the relevant code
[ServiceContract]
public interface IMyService
{
[WebGet(UriTemplate = "MyMethod/MyParam={MyParam}")]
[OperationContract]
string MyMethod(string MyParam);
}
Web.Config - system.serviceModel Section
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="MyService">
<endpoint address=""
binding="wsHttpBinding" contract="IMyService" />
<endpoint address="MyService.svc"
binding="basicHttpBinding" contract="IMyService" />
<endpoint address="mex"
binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
Looking at your web.config serviceModel section, I can see that you need to add a webHttpBinding and associate an endPointBehavior that includes webHttpGet.
Your operation contract is correct. Here's how your system.serviceModel config section should look in order for you to be able to consume the service from a GET HTTP request.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="WebBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="MyService">
<endpoint address="ws" binding="wsHttpBinding" contract="IMyService"/>
<endpoint address="" behaviorConfiguration="WebBehavior"
binding="webHttpBinding"
contract="IMyService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
Be sure to assign a different address to your wsHttpBinding endpoint, otherwise you will get an error saying that you have two endpoints listening on the same URI.
Another option is to leave the address blank in the wsHttpBinding, but assign a different address to the webHttpBinding service. However, that will change your GET address as well.
For example, if you assign the address as "asmx", you would call your service with the address "MyService.svc/asmx/MyMethod?MyParam=xxxx".
The normal WCF requests are always SOAP requests - you won't be able to get this going with just your browser, you'll need the WCF Testclient for that.
There is an add-on for WCF called the WCF REST Starter Kit (which will also be included in WCF 4.0 with .NET 4.0), which allows you to use GET/POST/PUT/DELETE HTTP commands to query WCF services and such. You need to write your services specifically for REST, though - you can't have SOAP and REST on the same service call.
Marc
As marc_s says, the REST Starter Kit can help, but you should also be aware that .NET 3.5 has support for REST services directly in it. It's not quite as complete as what you can do with the starter kit, but it is useful.
The way it works is that you put a [WebGet] attribute on your operations to indicate where in the URL the various parameters should come from:
[WebGet(UriTemplate = "helloworld/{name}")]
string Helloworld(string name);
See this portal for tons of information.
Note, you can have the same service exposed as both SOAP and REST if you specify multiple endpoints/bindings in the configuration.
I have the following problem. Let me describe the steps I took so far...
I created a new WCF Service Application in Visual Studio
I then updated the project via Nuget to get the latest web http libs (webapi.dll)
I then created a service method that looks like this
`
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(Method="POST", UriTemplate="{value}")]
string GetData(int value, Stream inputDocument);
}
`
Now attempting to view the my .svc in the browswer results in an error that says "For request in operation GetData to be a stream the operation must have a single parameter whose type is Stream"
I know this is an issue with configuration, I just don't know what needs to change in web.config Mind you, this seems to have been a common problem in WCF before the new HTTP support, I'm somewhat surprised that this doesn't work out of the box with the new APIs.
Any pointers?
Thanks
[EDIT] I've included my config...
<system.serviceModel>
<services>
<service name="MyService.Service" behaviorConfiguration="serviceBehaviour">
<endpoint behaviorConfiguration="endPointBehaviour" address="" binding="webHttpBinding" contract="MyService.IService"/>
</service>
</services>
<bindings>
<webHttpBinding>
<binding transferMode="Streamed" name="webHttpBinding" />
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="endPointBehaviour">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="serviceBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
You are mixing up the new WCF Web API stuff with the old WCF REST stuff. Take a look at the HttpHelloResource sample as the simplest example of how to run a Web API service under IIS, or my blog post for an even simpler example of a service running in a console.
As for accepting a stream I think your simplest option would be an operation like this:
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(Method="POST", UriTemplate="{value}")]
string GetData(int value, HttpRequestMessage request);
}
and you can get the stream by doing
var stream = request.Content.ContentReadStream
Ok, so it seems the error message was taking me down the wrong path. I think that error message needs to be far more descriptive. Basically there's nothing wrong my code at all, it just doesn't make sense to point my browser to the .svc file as the service is not quite a WCF service. I learmt this by going ahead and accessing the service via code. And it works. Thanks for the help
I've set up a WCF service to require NTLM authentication using the following configuration:
<system.serviceModel>
<bindings>
<customBinding>
<binding name="BinarySecurityBinding">
<binaryMessageEncoding/>
<httpTransport authenticationScheme="Ntlm"/>
</binding>
</customBinding>
</bindings>
<services>
<service name="Services.LogisticsServices" behaviorConfiguration="ServiceBehavior">
<endpoint address="" binding="customBinding" bindingConfiguration="BinarySecurityBinding" contract="Services.ILogisticsServices" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I did this so that the applications that consume the web service are forced to log in because all my service's operations use impersonation ([OperationBehavior(Impersonation = ImpersonationOption.Required)]).
In IIS 7 I've enabled anonymous and Windows authentication.
When I visit http://test.server/LogisticsServices.svc, which hosts the service described above, I can see the default service description page anonymously. However, when Visual Studio tries to access http://test.server/LogisticsServices.svc/$metadata to generate a client proxy, the server is responding with HTTP code 401 and expecting authentication. Not only would I've expected the metadata to be available anonymously, but additionally, the server is not accepting the credentials I am giving it (even though, I know for a fact that they are correct).
Testing different configuration, I tried removing the authenticationScheme from my binding's transport, just to be able to generate the client proxy, but that results in an exception because the service's operations require impersonation ([OperationBehavior(Impersonation = ImpersonationOption.Required)]).
What am I missing in my service's configuration that would make the service's metadata available anonymously? I'm also open to suggestions if I'm approaching the whole thing wrong.
here is a similar discussion:
Getting an Security setting exception while accessing a WCF service
One way around this is not to use the autogenerated proxies.
In cases where we have control over both the server and the client we have found that it is much more productive to avoid using the autgenerated proxies.
A screencast of how to do this can be found here: http://www.dnrtv.com/default.aspx?showNum=122
You could try imperative instead of declarative model, see: http://msdn.microsoft.com/en-us/library/ms730088.aspx
I have a simple WCF 4.0 service with some simple methods and a property with a getter that returns List. The service works fine when connected to programatically. The getter is decorated as are the other methods on the Interface that define the service contract.
My next move is to make the service accessible via the IE web browser so server/deployment admins can do a "smoketest" after service installation.
This works currently:
http://localhost/myservice.svc?wsdl
But I need to take things further and get this to work:
http://localhost/myservice.svc/SmokeTest
and have results show in the browser, SmokeTest is the property with a getter that does stuff and returns the List I want to show in the browser.
So far I can't figure out what my config should look like. All help appreciated.
This is all I have in the web.config for the service. The endpoint is myservice.svc:
<behaviors>
<serviceBehaviors>
<behavior >
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service name="myservice.worker" >
<endpoint address="" binding="basicHttpBinding" contract="myservice.IServicio" />
</service>
</services>
related question, an explanation of what can and can't be done:
Invoking WCF services through a browser
I have a simple WCF service that we are developing... We are hosting in IIS7 on WinServer2k8 (though i cant get it to work in IIS7 on Win7 either)
I want multiple endpoints for the same service contract but have the endpoints behave differently. For example I want one endpoint to return data as XML and another to return data in SOAP messages.
Here is my web.config
<system.serviceModel>
<services>
<service name="MemberService">
<endpoint address="soap" binding="basicHttpBinding" contract="IMemberService" />
<endpoint address="xml" binding="webHttpBinding" contract="IMemberService" behaviorConfiguration="xmlBehavior" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="xmlBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
In my service contract i have a method defined as:
[OperationContract]
[WebGet(UriTemplate = "members/{id}")]
Member GetMember(string id);
When I deploy to IIS (on localhost) and make a request (with fiddler) to http://localhost/MemberService.svc/xml/members/memberid I receive a 404 error, also a 404 with http://localhost/MemberService.svc/soap/
However, http://localhost/MemberService.svc/members/memberid works and serializes the data as expected. We want to add the functionality of JSON in the near future as well, we thought it would be another endpoint with a different behavior. My web.config is modeled after a post i found on here
Following this tutorial....
I was able to quickly deploy the webservices. Then using fiddler I could change the content-type of the request to/from "text/xml" and "text/json" and the service would automatically return the data in the correct format.