Link to home
Start Free TrialLog in
Avatar of LisaSnyder
LisaSnyder

asked on

RESTful Service - POST (format XML) passing Object

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
Avatar of Aaron Jabamani
Aaron Jabamani
Flag of United Kingdom of Great Britain and Northern Ireland image

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
Avatar of LisaSnyder
LisaSnyder

ASKER

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;

        }
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;
            }
        }
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 ?
I am not sure exactly how to debug. Used Fiddler and am getting 404 error. I will try the flush and see what happens.
Can you tell me how to check to see if object is null?
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.
how do u call the service ? 404 is not found error
I posted the HttpWebRequest and HttpWebResponse above.  That is the code I use to call the service.
can u post the calling code of the books? for the list of the books
and try to change the url without / at the end..
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>
   <
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
Internet explorer searches for favicon.ico as default behaviour.
dont think about it.
Thank you Melih.  I can then focus on my POST for add book that is still getting 404 Exception.
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?
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);
thats seems like ok..

when u get 404 while calling a service its almost the URL that u call gives the error
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>"
<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>
That was a cut/paste error on my part.  The </PublishDate> is there.  That, unfortunately, is not the issue.
ASKER CERTIFIED SOLUTION
Avatar of LisaSnyder
LisaSnyder

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.