Online POST to a WCF Service - wcf

I am trying to make a HTTP POST to a WCF Service.But these Service is based on an another service. I referenced that service to my own service. Now I want to POST some data and get a response from my web service but it did not work.
[OperationContract(Name ="GetData")]
[WebInvoke(Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "GetData")]
string GetData(string value);
These is my sample method.
public class Service1 : IService1
{
public string GetData(string value)
{
return string.Format("You entered: {0}", value);
}
}
and this is the content of my method.

Verify following thing in your web.config
Make sure that your using webHttpBinding
Add end point behaviour as show below
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>

Related

problems POSTing data to my WCF service

I am trying to set up a simple service that will allow the user to pass in a Pickup object as XML in the body of a POST. If i set the service to receive a Stream type, i can get it to work fine, but I'm not sure what i need to change in order for it to instead of a custom type is works fine. When I tell the server to expect a Pickup type i get "Request Error. The server has encountered..."
I someone could tell me what i need to change in the server/client to get this to work i would appreciate it very much.
My data Contract
[DataContract]
public class Pickup
{
[DataMember]
public string DelZip
{ get; set; }
}
Operation Contract
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "/pickups",
RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Bare)]
string RequestPickup(Pickup pickup);
public string RequestPickup(Pickup pu)
{
return pu.DelZip;
}
config
<services>
<service name="TestAPI.Services.TestServices" >
<endpoint address=""
binding="webHttpBinding" behaviorConfiguration="webHttp"
contract="TestAPI.Services.ITestServices" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="webHttp">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
my client code
const string url = "http://localhost:18463/TestServices.svc/pickups";
req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/xml";
var xmlDoc = new XmlDocument { XmlResolver = null };
xmlDoc.LoadXml(#"<Pickup><DelZip>55555</DelZip></Pickup>");
string sXml = xmlDoc.InnerXml;
req.ContentLength = sXml.Length;
var sw = new StreamWriter(req.GetRequestStream());
sw.Write(sXml);
sw.Close();
res = (HttpWebResponse)req.GetResponse();
Stream responseStream = res.GetResponseStream();
var streamReader = new StreamReader(responseStream);

Bad Request error on POST to WCF Restful web service Hosted in IIS using Basic Authentication over https

I have a wcf 3.5 restful web service that is hosted in IIS 7.5. It is setup to use Basic Authentication over https. I added as much information as possible below (names of classes, etc have been altered slightly). Any advice or suggestions are greatly appreciated.
Every time I try to send a POST either via Fiddler or through a client application I get this message:
HTTP/1.1 400 Bad Request
I turned on the svctrace logs give me this information:
System.Runtime.Serialization.SerializationException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Unable to deserialize XML body with root name 'user-search-request' and root namespace '' (for operation 'FetchMatchingUsers' and contract ('IMyService', 'http://tempuri.org/')) using DataContractSerializer. Ensure that the type corresponding to the XML is added to the known types collection of the service.
The URL for the service looks like this:
https://mysite.com/program/user/v1.0/MyService.svc
My Service Contract looks like this:
[ServiceContract]
interface IMyService
{
[WebInvoke(UriTemplate = "",
Method = "POST",
RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml)]
[OperationContract]
Users FetchMatchingUsers(User u);
}
My Service Implementation looks like this:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService
{
static Users _users = new Users();
public Users FetchMatchingUsers(User u)
{
return SearchByFullName(u.FirstName, u.LastName);
}
}
The DataContract looks like this:
[CollectionDataContract(Name = "user-search-request", Namespace = "")]
public class Users : List<User>
{ }
[DataContract(Name = "user", Namespace = "")]
public class User
{
[DataMember(Name = "first-name")]
public string FirstName { get; set; }
[DataMember(Name = "last-name")]
public string LastName { get; set; }
}
Service Model is setup like this:
<system.serviceModel>
<diagnostics>
<messageLogging logMalformedMessages="true" logMessagesAtTransportLevel="true" />
</diagnostics>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
</serviceHostingEnvironment>
<services>
<service behaviorConfiguration="basic" name="MyService">
<clear />
<endpoint address="/program/user/v1.0" binding="basicHttpBinding"
name="Default" contract="MyService.IMyService"
listenUriMode="Explicit">
<identity>
<certificateReference storeName="My" storeLocation="LocalMachine"
x509FindType="FindBySubjectDistinguishedName" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="https://mysite.com" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="basic">
<serviceMetadata httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBinding">
<readerQuotas maxStringContentLength="10500" />
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
My POST is setup like this:
private void DoPost
{
String firstname = "Test";
String lastname = "User";
User user = new User();
user.FirstName = firstname;
user.LastName = lastname;
String uristring = #"https://mysite.com/program/user/v1.0/MyService.svc/";
Uri uri = new Uri(uristring);
HttpWebRequest client = (WebRequest.Create(uri)) as HttpWebRequest;
NetworkCredential cred = new NetworkCredential(_username, _password, _domain);
String username = cred.Domain + "\\" + cred.UserName;
byte[] credentialBuffer = new UTF8Encoding().GetBytes(username + ":" + cred.Password);
client.Credentials = cred;
client.Method = "POST";
client.ContentType = "application/xml";
client.Headers["Authorization"] = "Basic " + Convert.ToBase64String(credentialBuffer);
List<User> users = new List<User>();
users.Add(user);
SerializeUsers sa = new SerializeUsers();
String output = sa.SerializeUsers(users);
client.ContentLength = output.Length;
// Write the request StreamWriter
StreamWriter requestWriter = new StreamWriter(client.GetRequestStream(), System.Text.Encoding.ASCII);
requestWriter.Write(output.ToString());
requestWriter.Close();
// Do the request to get the response
try
{
StreamReader responseReader = new StreamReader(client.GetResponse().GetResponseStream());
String response = responseReader.ReadToEnd();
responseReader.Close();
}
catch (WebException ex)
{
String message = ex.Message;
}
}
My Deserializer right now is just a test so the xml is actually hardcoded but I do need to make it work the right way once I get this problem solved.
public class SerializeUsers
{
public String SerializeUsers(List<User> ts)
{
String xml = #"<user-search-request xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">";
foreach (User t in ts)
{
xml += #"<user>";
xml += #"<first-name>" + t.FirstName + "</first-name>";
xml += #"<last-name>" + t.LastName + "</last-name></user>";
}
xml += #"</user-search-request>";
return xml;
}
}
Hello can you try [XmlSerializerFormat] under your service contract so it should look like this:
[ServiceContract]
[XmlSerializerFormat]
interface IMyService
The second thing you might want to do is add a wrapper to your POST like so:
[WebInvoke(UriTemplate = "",
Method = "POST",
BodyStyle = WebMessageBodyStyle.Wrapped,
RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml)]
Failing that then your config file is to blame if I was to hazard a guess, it should be set up with webHttpBinding.

How to Make Multiple Parallel WCF Service Calls from jquery

I have to make multiple WCF service calls by using jquery to update different areas of the web page after a specified time interval. If I make a single call to the WCF service it works fine, but when there are two or more parallel calls to the WCF service no response is received.
All the service calls are made after some specified time-interval. Following is the code of one of them:
var type = "POST";
var contentType = "application/json; charset=utf-8";
var dataType = "json";
var processData = true;
function LoadData()
{
var url = serviceURL;
var data = '{}';
CallService(url, data, LoadDataSuccess);
}
function LoadDataSuccess(result)
{
if (dataType == "json")
{
//other code...
setTimeout("LoadData()", 5000);
}
}
function CallService(url, data, SuccessMethod)
{
$.ajax({
type: type, //GET or POST or PUT or DELETE verb
url: url, // Location of the service
data: data, //Data sent to server
contentType: contentType, // content type sent to server
dataType: dataType, //Expected data format from server
processdata: processData, //True or False
success: function (msg)
{
SuccessMethod(msg);
},
error: ServiceFailed
});
}
function ServiceFailed(result)
{
alert('Service call failed: ' + result.status + '' + result.statusText);
type = null; contentType = null; dataType = null; processData = null;
}
And my wcf service looks like this:
public interface ITestService
{
[OperationContract]
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.Wrapped,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
List<Data> GetData();
[OperationContract]
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.Wrapped,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
List<Data> GetUser();
[OperationContract]
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.Wrapped,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
List<Data> GetCustomer();
}
And the configuration looks like this:
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<behaviors>
<endpointBehaviors>
<behavior name="EndpBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="ServiceBehavior" name="TestService">
<endpoint address="" binding="webHttpBinding" contract="ITestService" behaviorConfiguration="EndpBehavior"/>
</service>
</services>
</system.serviceModel>

WCF Rest Webservice with stream

I read the following post with interest as it is an exact replica of the problem I am experiencing (and driving me insane)
"For request in operation UploadFile to be a stream the operation must have a single parameter whose type is Stream." -http://social.msdn.microsoft.com/Forums/en/wcf/thread/80cd26eb-b7a6-4db6-9e6e-ba65b3095267
I have pretty much followed all code/examples I have found and yet still cannot get around this error -
http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-receiving-arbitrary-data.aspx
All I would like to achieve is to post an image(jpeg/png) from an android device using the standard filename/stream parameters.More than likely it is something simple that I have misconfigured, misunderstood or left out but I need to have a solution for proof of concept.
public interface IConXServer
{
[OperationContract]
[WebInvoke(UriTemplate = "UploadImage({fileName})", Method="POST")]
void UploadImage(string fileName, Stream imageStream);
}
public class ConXWCFServer : IConXServer
{
public void UploadImage(string fileName, Stream imageStream)
{
//implement image save
}
}
web.config settings
-->
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="webHttpEndpoint" helpEnabled="false"/>
</webHttpEndpoint>
</standardEndpoints>
<bindings>
<webHttpBinding>
<binding name="webHttpBinding" transferMode="Streamed"/>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="webHttpBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceThrottling maxConcurrentCalls="2147483647" maxConcurrentSessions="2147483647"/>
</behavior>
</serviceBehaviors>
</behaviors>
Using vs2010 and IIS Express. If I comment out the above method all the others methods work and return data as well as the wsdl query
Regards and thanks in advance
Kern
You mention WSDL, which leads me to believe you're getting the error while trying to browse the metadata endpoint for the service. So, first off, WSDL and REST don't go together, so you shouldn't expect to use it at all for a REST interface. Forget the service metadata concept even exists in the REST world.
Next While it's true the REST's webHttpBinding supports parameters in front of the Stream body parameter, other bindings do not and there must either be a single Stream parameter or a message contract with headers and a stream body.
So, in the end, the problem is not with the REST webHttpBinding at all, I bet it works just fine. If it doesn't I would be absolutely shocked because you're not doing anything that shouldn't work in that department. The problem is that you're expecting the metadata endpoint to generate WSDL for the service contract you've defined and that's just not supported.
I do it this way and it'works.
Add Factory Class to webservice (WcfService2.ServiceFactory)
<%# ServiceHost Language="C#" Debug="true" Service="WcfService2.Service1" CodeBehind="Service1.svc.cs" Factory="WcfService2.ServiceFactory" %>
My Interface:
public interface IService1
{
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest, Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "UploadFile/{fileName}")]
void UploadFile(string fileName, Stream fileContent);
}
My Method:
public void UploadFile(string fileName, Stream fileContent)
{
var pathfile = "\\\\SERVER\\TravelsRequestFiles";
using (var fileStream = new FileStream(string.Concat(pathfile, "\\", fileName), FileMode.Create, FileAccess.Write))
{
fileContent.CopyTo(fileStream);
}
}
my FactoryClass:
public class ServiceFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new MyServiceHost(serviceType, baseAddresses);
}
class MyServiceHost : ServiceHost
{
public MyServiceHost(Type serviceType, Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
}
protected override void InitializeRuntime()
{
ServiceEndpoint endpoint = this.Description.Endpoints[0];
endpoint.Behaviors.Add(new EndpointBehaviors());
base.InitializeRuntime();
}
}
}
I added a EndpointBehaviors class, wich it find de operation UploadFile and remove its DataContractSerializerOperationBehavior, and then works!
public class EndpointBehaviors: IEndpointBehavior
{
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
ContractDescription cd = endpoint.Contract;
foreach (DispatchOperation objDispatchOperation in endpointDispatcher.DispatchRuntime.Operations)
{
if (objDispatchOperation.Name.Equals("UploadFile"))
{
OperationDescription myOperationDescription = cd.Operations.Find("UploadFile");
DataContractSerializerOperationBehavior serializerBehavior = myOperationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>();
myOperationDescription.Behaviors.Remove(serializerBehavior);
}
}
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void Validate(ServiceEndpoint endpoint)
{
BindingElementCollection elements = endpoint.Binding.CreateBindingElements();
WebMessageEncodingBindingElement webEncoder = elements.Find<WebMessageEncodingBindingElement>();
if (webEncoder == null)
{
throw new InvalidOperationException("This behavior must be used in an endpoint with the WebHttpBinding (or a custom binding with the WebMessageEncodingBindingElement).");
}
}
}

Sending JSON to WCF Rest Service - object is always null

I am trying to get my application working by using REST, WCF and JSON (new to all those technologies). I have the 'GET' working fine. It is the 'POST' that is causing me problems.
As you will see below I 'pack up' my JSON using JSON.stringify, then fire off the POST to the REST resource. However, when the object gets to the WCF method that is handling the request the object is always null.
Here is the code:
$.ajax({
type: "POST",
dataType: "json",
url: "Services/ContactCompanyService.svc/contactcompanies/customers",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ contactcompany: newCustomer }),
success: function (html) { alert(html); }
});
Here is the config stuff:
<services>
<service behaviorConfiguration="ServiceBehaviour" name="ContactCompanyService">
<endpoint address="contactcompanies" behaviorConfiguration="web" binding="webHttpBinding" contract="IContactCompanyService"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
<enableWebScript/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true"/>
Here is the contract:
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "customers")]
[return: MessageParameter(Name = "ContactCompany")]
ContactCompany AddContactCompany(ContactCompany ContactCompanyObject);
And it is the method that implements the above interface where ContactCompanyObject is null.
What on earth am I doing wrong? Please don't rule out stupidity on my part.
Further:
I changed the WebMessageBodyStyle to .Bare, and this resulted in the object not being null ... but EVERY property of the object being null. That said, wrapped is the way I would like to go.
I would be grateful of any assistance. Let me know if you need further information.
UPDATE
I started from scratch with a completely new project - stripped back.
I am getting exactly the same result - the object, when received by the WCF code, is null.
Here's what I did on this new test project.
WCF Contract:
(under the namespace: NullTestService
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "NullTestPost")]
[return: MessageParameter(Name = "NullTestType")]
NullTestType GettMethod();
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "NullTestPost")]
[return: MessageParameter(Name = "NullTestType")]
NullTestType PostMethod(NullTestType NullTestTypeObject);
}
[DataContract]
public class NullTestType
{
[DataMember]
public string NullTestString { get; set; }
[DataMember]
public int NullTestInt { get; set; }
}
Service Implementation:
(same namespace)
public class Service1 : IService1
{
public NullTestType PostMethod(NullTestType NullTestTypeObject)
{
return NullTestTypeObject;
}
public NullTestType GettMethod()
{
return new NullTestType { NullTestString = "Returned String", NullTestInt = 25 };
}
}
Website project.
Service.svc:
<%# ServiceHost Service="NullTestService.Service1" %>
web.config in the web project:
<system.serviceModel>
<services>
<service behaviorConfiguration="ServiceBehaviour" name="NullTestService.Service1">
<endpoint address="nulltestaddress" behaviorConfiguration="web" binding="webHttpBinding" contract="NullTestService.IService1"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
and finally the jQuery in the web project:
$(function () {
// $.ajax({
// type: "GET",
// url: "http://localhost:8080/TestWeb/Service.svc/nulltestaddress/nulltestpost",
// success: alertResult
// });
alert('about to do it');
$.ajax({
type: "POST",
url: "http://localhost:8080/TestWeb/Service.svc/nulltestaddress/nulltestpost",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: '{"NullTestType":{"NullTestString":"This is a post string","NullTestInt":25}}',
success: alertResult
});
});
function alertResult(data) {
alert(data.NullTestType.NullTestString);
}
So. The (commented out) GET works fine and returns the JSON. The POST does not. On the line:
public NullTestType PostMethod(NullTestType NullTestTypeObject)
{
return NullTestTypeObject;
}
(the 'return' line) the NullTestTypeObject is always NULL.
I would be very grateful for help. I have lost a lot of time over this.
If Wrapped is what you want to do, then you need to wrap the request in the operation parameter name:
var input = { "ContactCompanyObject" : newCustomer };
$.ajax({
data: input
...
});
Or for the second example, if you change the ajax call to the one shown below, you should get the expected result:
var input = { NullTestTypeObject: { NullTestString: "Hello", NullTestInt: 123} };
alert("Input: " + JSON.stringify(input));
$.ajax({
type: "POST",
url: "./Service1.svc/nulltestaddress/NullTestPost",
contentType: "application/json",
data: JSON.stringify(input),
success: function (result) {
alert("POST result: " + JSON.stringify(result));
}
});