Solved

RESTful Service - POST (format XML) passing Object

Posted on 2014-03-10
24
1,946 Views
Last Modified: 2014-03-17
I am trying to consume a Web Service I have written in VS2012 C#.  The operation takes a Transaction object and returns a Transaction object.

I need to consume the web service and am having trouble writing the code for the HttpWebRequest and HttpWebResponse.

I do not know who to pass the Transaction Object to the service method and get the results back and deserialize it back into the Transaction object.  It is a  POST (adding a record).

All the examples I find, do not show me enough detail on how to do this.

Can someone please give me a straight forward example of how to write the client HttpWebRequest/Response and how to pass the object and then how to get the returned data back into the object.

Thank you,
Lisa
0
Comment
Question by:LisaSnyder
  • 13
  • 9
  • 2
24 Comments
 
LVL 25

Expert Comment

by:apeter
ID: 39920187
0
 
LVL 19

Expert Comment

by:Melih SARICA
ID: 39920255
what kind of transaction are u talking about  ?

What u need to do is to serialize the object u want in this case binary serialization ll be better i guess cuz i dont know what u carry in this "transaction object" and deserialize on the client and postback server side..

If u can tell more details about what u want to do we can help u more
0
 

Author Comment

by:LisaSnyder
ID: 39920673
I have a Book Store web service that has 3 operations.  1st 1 returns all books, 2nd operation returns book when passing a ISBN # in.  Those work fine.  The 3rd operation is to add a new book to the books table using POST.  I serialized the book object into XML and then included in HttpWebRequest.  When I try to get response back, I get 404 Error.  

Code to consume web service followed by IbuyBooks operations and buyBooks.svc.cs below:  Thank you for your help.

 try
            {
                byte[] bytes = Encoding.UTF8.GetBytes(xml);
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create  
                               ("http://localhost:24885/buyBooks.svc/NewBook/");
                request.Method = "POST";
                request.ContentLength = bytes.Length;
                request.ContentType = "text/xml";
                using (Stream requestStream = request.GetRequestStream())
                {
                    requestStream.Write(bytes, 0, bytes.Length);
                }

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Stream resStream = response.GetResponseStream();
                StreamReader rdStreamRdr = new StreamReader(resStream);
                if (response.StatusCode != HttpStatusCode.OK)
                {
                    string message = String.Format("POST Failed. Received HTTP {0}",
                                response.StatusCode);
                    throw new ApplicationException(message);
                }
                else
                {
                    string message = rdStreamRdr.ReadToEnd();
                    Response.Write(message);
                }
            }
            catch (Exception ex)
            {
                Response.Write(ex.Message.ToString());                        
            }

Here is the operations from the web service (AddBook method is the one I am having issues with):
IbuyBooks
    [OperationContract]
        [WebInvoke(Method = "GET",
            UriTemplate = "/Books")]
        List<Book> AllBooks();

       
        [OperationContract]
        [WebInvoke(Method = "GET",
            UriTemplate = "/Book/{ISBN}")]
        Book GetBook(string isbn);

        [OperationContract]
        [WebInvoke(Method = "POST",
            UriTemplate = "/NewBook")]
        Book AddBook(Book book);


buyBooks.svc.cs
public Book AddBook(Book b)
        {
            dc.Books.InsertOnSubmit(b);
            dc.SubmitChanges();

            var bookdetail = from book in dc.Books
                             where book.ISBN == book.ISBN
                             select book;

            Book addedBook = new Book();
            foreach (var item in bookdetail)
            {
                addedBook.ISBN = item.ISBN;
                addedBook.Title = item.Title;
                addedBook.Author = item.Author;
                addedBook.Publisher = item.Publisher;
                addedBook.PublishDate = item.PublishDate;
                addedBook.Price = item.Price;
                addedBook.QOH = item.QOH;
            }

            return addedBook;

        }
0
 

Author Comment

by:LisaSnyder
ID: 39920719
Forgot to include the method that I used to do serialization in case there is something wrong there.  I pass the book object in and return xml to use in HttpWebRequest.  Method below:

  public string CreateXML(Book book)
        {
            XmlDocument xmlDoc = new XmlDocument();
            XmlSerializer xmlSerializer = new XmlSerializer(book.GetType());
            using (MemoryStream xmlStream = new MemoryStream())
            {
                xmlSerializer.Serialize(xmlStream, book);
                xmlStream.Position = 0;
                xmlDoc.Load(xmlStream);
                return xmlDoc.InnerXml;
            }
        }
0
 
LVL 19

Expert Comment

by:Melih SARICA
ID: 39920921
its seems like flushing the requeststream.
after a write try flush to force the data to be  send to the stream.

if this dont work. what did u get when debug the add operation on the service file ? do u get any objects, i mean the book object is null or has a value ?
0
 

Author Comment

by:LisaSnyder
ID: 39921085
I am not sure exactly how to debug. Used Fiddler and am getting 404 error. I will try the flush and see what happens.
0
 

Author Comment

by:LisaSnyder
ID: 39921115
Can you tell me how to check to see if object is null?
0
 
LVL 25

Expert Comment

by:apeter
ID: 39921193
Run both your client and service at the same machine.  Let client point to the url of your local server url. If this setup is done, if the client makes a request, using breakpoint in svc file you can debug.
0
 
LVL 19

Expert Comment

by:Melih SARICA
ID: 39921376
how do u call the service ? 404 is not found error
0
 

Author Comment

by:LisaSnyder
ID: 39921587
I posted the HttpWebRequest and HttpWebResponse above.  That is the code I use to call the service.
0
 
LVL 19

Expert Comment

by:Melih SARICA
ID: 39921654
can u post the calling code of the books? for the list of the books
0
 
LVL 19

Expert Comment

by:Melih SARICA
ID: 39921704
and try to change the url without / at the end..
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 

Author Comment

by:LisaSnyder
ID: 39921730
Here is where I call the operations to return the list of books.  The status that comes back is OK.  I will post the code and the string that is displayed, so you can see.  I only see 1 xml tag in the string.  Not sure why.

Code to Display List of Books
  HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:27601/buyBooks.svc/Books");
            request.Method = "GET";
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            Stream receiveStream = response.GetResponseStream();
            Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
            // Pipes the stream to a higher level stream reader with the required encoding format.
            StreamReader readStream = new StreamReader(receiveStream, encode);
           
            Response.Write("");
            Char[] read = new Char[256];
            // Reads 256 characters at a time.    
            int count = readStream.Read(read, 0, 256);

            while (count > 0)
            {
               
                // Dumps the 256 characters on a string and displays the string to the console.
                String str = new String(read, 0, count);
                Response.Write(str +",         ");
                count = readStream.Read(read, 0, 256);
            }

            // Releases the resources of the response.
            response.Close();
            // Releases the resources of the Stream.
            readStream.Close();


The string that I display from results.  The only tag that shows is <Author>.  

Barry123-3232008-02-17T00:00:00Hall2Jerry344-1122011-01-01T00:00:00Prentice5< Author>Bob454-3942009-05-01T00:00:00Prentice10

It should look like"
<books>
 <book/>
  <ISBN/>
   <Title/>
   <Author/>
   <Publisher/>
   <PublishDate/>
   <Price/>
   <QOH/>
 </book>
</books>
   <
0
 

Author Comment

by:LisaSnyder
ID: 39921849
As requested previously, I called the flush, but it did not change the results.  I tried to debug.  I see the request has the XML, but the response is NULL.  When it gets to the HttpWebResponse, it skips right to the 404 Exception.  

Also, something interesting.  I started Fiddler.  Outside of the client, I called browse on the webservice and successfully returned the list of books and it displayed in XML.  The line returned in Fiddler was 200.  However, it was immediately followed by a 404 Result.  Can someone tell me what is happening?  Could it be related to my issue with calling the operation in Webservice POST that is getting the 404?



#      Result      Protocol      Host      URL      Body      Caching      Content-Type      Process      Comments      Custom      
1      200      HTTP      localhost:27601      /buyBooks.svc      1,321            text/html; charset=UTF-8      iexplore:10040                  
2      404      HTTP      localhost:27601      /favicon.ico      4,958      private      text/html; charset=utf-8      iexplore:10040
0
 
LVL 19

Expert Comment

by:Melih SARICA
ID: 39921906
Internet explorer searches for favicon.ico as default behaviour.
dont think about it.
0
 

Author Comment

by:LisaSnyder
ID: 39922019
Thank you Melih.  I can then focus on my POST for add book that is still getting 404 Exception.
0
 
LVL 19

Expert Comment

by:Melih SARICA
ID: 39922184
did u try to call service without / at the end..

http://localhost:24885/buyBooks.svc/NewBook



and also what i realise is.
ur add bok url port and getbook url port is different

one is 24885 other is 27601.

are they different services? or the same service with misstype ports?
0
 

Author Comment

by:LisaSnyder
ID: 39922247
Melih - The previous code with call with port 24885 was a different project.  I created a new solution with new projects and the calls are all to 27601.  No, I did not try to call without the / at the end.  I can try that.  Since I am changing  that, can you tell me how the UriTemplate should look for that?  Right now it looks like the following:

 [OperationContract]
 [WebInvoke(Method = "POST",
            UriTemplate = "/NewBook")]
 Book AddBook(Book book);
0
 
LVL 19

Expert Comment

by:Melih SARICA
ID: 39922258
thats seems like ok..

when u get 404 while calling a service its almost the URL that u call gives the error
0
 

Author Comment

by:LisaSnyder
ID: 39922378
I changed the call to remove the trailing /.  Now I get a Exception 400 Bad request.  

This is the Xml that is being put into byte[] array:

"<?xml version=\"1.0\"?>
<Book xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
<ISBN>111-111</ISBN>
<Title>Test Title</Title>
<Author>Pat</Author>
<Publisher>aaa</Publisher>
<PublishDate>2011-01-11T00:00:00
<Price>15.11</Price>
<QOH>17</QOH>
</Book>"
0
 
LVL 19

Expert Comment

by:Melih SARICA
ID: 39922733
<Publisher>aaa</Publisher>
<PublishDate>2011-01-11T00:00:00
<Price>15.11</Price>

Publish date XMLElement is not correct.. must ave endelement

<Publisher>aaa</Publisher>
<PublishDate>2011-01-11T00:00:00</PublishDate>
<Price>15.11</Price>
0
 

Author Comment

by:LisaSnyder
ID: 39923198
That was a cut/paste error on my part.  The </PublishDate> is there.  That, unfortunately, is not the issue.
0
 

Accepted Solution

by:
LisaSnyder earned 0 total points
ID: 39923638
I have resolved my 404 error.  I found a very good article (after much searching and searching) that stepped completely through how to do POST to a webservice and test with client app.  This example had the web service as well as the client.  I will post link to article below.  The one thing I noticed is that the author had you create a RequestObj class and a ResponseObj class in the web service.  He also made sure to include a name space in the RequestObj class.  The other thing is that the RequestObj had a datamember of string and the ResponseObj class was the object you are trying to save in database.  Next, in the method Add in the web service, he parsed/split out the data into var response  from the request and there is where you can assign to the fields in your object, save it to the database and then return the response, which comes back to the client in a nice xml.  

I think I was going wrong when the method was expecting a Book object when it was really a string and then I have to parse that out.

That being said, here is the article from Code Project named "CREATE RESTful WCF Service API Using POST: Step By Step Guide" by By ashutosh k. shukla

Link:
http://www.codeproject.com/Articles/201901/CREATE-RESTful-WCF-Service-API-Using-POST-Step-By?msg=4777620#xx4777620xx

Thank you for all your help and suggestions.  I hope the article I found helps someone else that may be having the same issues.
0
 

Author Closing Comment

by:LisaSnyder
ID: 39933763
I was very pleased at the amount of support that I received.  This was my first time asking a question, usually I just browse for answers.  But I could not find a solution to this problem.  Some experts referred me to links, which I had already investigated without resolution.  I also received some suggestions for code modifications, but unfortunately none resolved the issue.  I kept searching this morning and finally found an article that stepped through the service and test app.  It finally made clear where I had the issue.  I revised my code based on the article (in my comment) and it worked.
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Suggested Solutions

Using Quotation Marks in PHP This question (http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28217211.html) seems to come up a lot for developers who are new to PHP.  And it got me thinking, "How can we explain the rule…
New Relic recently released its Synthetics product that allows for the creation of performance monitors that periodically test a site's performance. If you wish to test an interactive workflow New Relic employs Selenium WebDriverJS to run those test…
Wufoo.com provides powerful tools for surveying targeted groups, and utilizing data from completed surveys to find trends, discover areas of demand or customer expectation, and make business decisions on products or services.
Use Wufoo, an online form creation tool, to make powerful forms. Learn how to choose which pages of your form are visible to your users based on their inputs. The page rules feature provides you with an opportunity to create if:then statements for y…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now