How do you do a call to a WCF REST POST method?
-
Monday, March 29, 2010 9:24 PM
Hi!
I'm trying to find out how to call a POST method in a WCF REST webservice... where do I have to put the body?
I've declared a method like this:
[WebInvoke(UriTemplate = "/{communityId}/Login", Method = "POST")]
[OperationContract]
Boolean Login(String communityId, UserLogin login);But... how do I call it now? :D
I've tried several things, but I always get a bad request :(
Guid g = Guid.NewGuid();
String user = "<UserLogin><Name>vt</Name><Password>lalala</Password></UserLogin>";
XmlSerializer s = new XmlSerializer(typeof(UserLogin), "ConsoleApplication1");
UserLogin ul = new UserLogin() { Name = "vt", Password = "lalala" };
WebRequest req = WebRequest.Create("http://localhost/RESTfulService/Service1.svc/" + g.ToString() + "/Login");
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
MemoryStream ms = new MemoryStream();
s.Serialize(ms, ul);
Byte[] array = ms.ToArray();
req.ContentLength = array.Length;
Stream reqStream = req.GetRequestStream();
reqStream.Write(array, 0, array.Length);
reqStream.Close();
//StreamWriter sw = new StreamWriter(reqStream,Encoding.UTF8);
//sw.WriteLine(user);
//sw.Dispose();
Stream responseStream = req.GetResponse().GetResponseStream();Cheers.
.: Valeriano Tórtola MCTS WPF :.: http://www.vtortola.net :.
All Replies
-
Tuesday, March 30, 2010 1:23 AM
hi,
Are your sure your URL is correct?
can you open "http://localhost/RESTfulService/Service1.svc/" + g.ToString() + "/Login" in IE?
additionally, Whatis the bad request data?
Frank Xu Lei--谦卑若愚,好学若饥
专注于.NET平台下分布式应用系统开发和企业应用系统集成
Focus on Distributed Applications Development and EAI based on .NET
欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum -
Tuesday, March 30, 2010 10:57 AM
Yes, the url is correct because I have other methods with a similar uritemplate.
I get a "400 Bad Request" when I post this: "<UserLogin><Name>vt</Name><Password>lalala</Password></UserLogin>" or I serialize the class with a XmlSerializer.
How would you call this method?:
[WebInvoke(UriTemplate = "/{communityId}/Login", Method = "POST")]
[OperationContract]
Boolean Login(String communityId, UserLogin login);Considering:
public class UserLogin
{
public String Name { get; set; }
public String Password { get; set; }
}Cheers.
.: Valeriano Tórtola MCTS WPF :.: http://www.vtortola.net :. -
Tuesday, March 30, 2010 10:57 AM
Yes, the url is correct because I have other methods with a similar uritemplate.
I get a "400 Bad Request" when I post this: "<UserLogin><Name>vt</Name><Password>lalala</Password></UserLogin>" or I serialize the class with a XmlSerializer.
How would you call this method?:
[WebInvoke(UriTemplate = "/{communityId}/Login", Method = "POST")]
[OperationContract]
Boolean Login(String communityId, UserLogin login);Considering:
public class UserLogin
{
public String Name { get; set; }
public String Password { get; set; }
}Cheers.
.: Valeriano Tórtola MCTS WPF :.: http://www.vtortola.net :. -
Wednesday, March 31, 2010 6:23 AMModerator
Hi vtortola,
The problem you encounter is probably due the default serialization behavior of WCF.
* WCF by default use DataContractSerializer to serialize object into XML, for the UserLogin class you provided, you can try define a WebGet operation and let it return a UserLogin object. e.g.[OperationContract] [WebGet] UserLogin GetUserLogin();You will find that it returns the following xml:
<UserLogin xmlns="http://schemas.datacontract.org/2004/07/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Name>user1</Name><Password>password1</Password></UserLogin>
the default output will use the http://schemas.datacontract.org/2004/07/ as a root namespace for your object. And if you do not add this namespace when using webrequest client, it will mismatch the server-side expected xml format. If you want to make the WCF service use XML serialization, you can add the "XmlSerializerFormatAttribute" on the serviceContract like below:
[ServiceContract] [XmlSerializerFormat] public interface IRESTService { [OperationContract] [WebInvoke] string SendUserLogin(UserLogin ul); }Then, it will generate XmlSerializer compatible xml content from object. Here is the test client code I used:
private static void WebRequestClient() { var httpwebrequest = WebRequest.Create("http://localhost:8388/testapp/RESTService.svc/SendUserLogin"); httpwebrequest.Method = "POST"; httpwebrequest.ContentType = "application/xml"; //generated xml object XmlSerializer serializer = new XmlSerializer(typeof(UserLogin)); UserLogin ul = new UserLogin() { Name = "user1", Password = "password1" }; MemoryStream ms = new MemoryStream(); serializer.Serialize(ms, ul); var bytes = ms.ToArray(); ms.Close(); //write xml into request stream var requestStream = httpwebrequest.GetRequestStream(); requestStream.Write(bytes, 0, bytes.Length); requestStream.Close(); //extract resposne result var responseStream = httpwebrequest.GetResponse().GetResponseStream(); StreamReader sr = new StreamReader(responseStream); Console.WriteLine(sr.ReadToEnd()); sr.Close(); responseStream.Close(); }
Please remember to mark the replies as answers if they help and unmark them if they provide no help.- Proposed As Answer by DChernin Friday, October 26, 2012 3:09 AM
-
Wednesday, March 31, 2010 11:05 AM
Hi,
Something is not working (at least in my computer :P)
I've done this:
[ServiceContract(Namespace="http://www.dk.com")]
[XmlSerializerFormat]
public interface IRESTfulService
{
[WebInvoke(UriTemplate = "/{communityId}/Login", Method = "POST")]
[OperationContract]
String Login(String communityId, UserLogin login);
}public class RESTfulService : RESTful_Service.IRESTfulService
{public String Login(String communityId, UserLogin login)
{
return "login=" + login.UserName;
}}
I use you code to perform a call, but I always get this:
<?xml version="1.0" encoding="utf-8"?><string>login=</string>
Maybe the difference... is that I have the class UserLogin declared in the client and in the server... but the serialization output should be the same, shoudn't it?
.: Valeriano Tórtola MCTS WPF :.: http://www.vtortola.net :. -
Wednesday, March 31, 2010 11:05 AM
Hi,
Something is not working (at least in my computer :P)
I've done this:
[ServiceContract(Namespace="http://www.dk.com")]
[XmlSerializerFormat]
public interface IRESTfulService
{
[WebInvoke(UriTemplate = "/{communityId}/Login", Method = "POST")]
[OperationContract]
String Login(String communityId, UserLogin login);
}public class RESTfulService : RESTful_Service.IRESTfulService
{public String Login(String communityId, UserLogin login)
{
return "login=" + login.UserName;
}}
I use you code to perform a call, but I always get this:
<?xml version="1.0" encoding="utf-8"?><string>login=</string>
Maybe the difference... is that I have the class UserLogin declared in the client and in the server... but the serialization output should be the same, shoudn't it?
.: Valeriano Tórtola MCTS WPF :.: http://www.vtortola.net :. -
Thursday, April 01, 2010 3:07 AMModerator
Hi Valeriano,
So the service doesn't report error and just get empty value for the UserLogin object's Username field, correct? In my test service, I also declare the UserLogin class in both client and service project twice, but they are identical, so if you make sure the class definition in both projects are identical(even the namespace) then it should be no problem on that.
Try using the method I mentioned earlier, define a WebGet operation to return the UserLogin and compare its generated XML with the one you send (for the webInvoke operation) to see whether there is difference. You can use fiddler tool to capture message for http service(without message layer security):
http://www.fiddler2.com/Fiddler2/version.aspor you can even try using WebChannelFactory to call REST service to see whether it works. If works, also try capturing its SOAP message to compare it with your current one.
#WebChannelFactory(TChannel) Class
http://msdn.microsoft.com/en-us/library/bb908674.aspx
If necessary, I can send you my test solution so that you can try running it on your side. You can reach me at the following address:
stcheng (AT) microsoft.com
Please remember to mark the replies as answers if they help and unmark them if they provide no help.- Marked As Answer by Mog LiangModerator Monday, April 05, 2010 2:57 AM
-
Friday, October 26, 2012 3:08 AM
Awesome job Steven. I've been looking for hours for an answer to how to do this!
Thanks...Dan
Dan

