none
Manually invoking Astoria service by using HttpWebRequest

    Question


  • Hello,

    I'm facing some problems in invoking Astoria service manually.

    According to Wiki, RESTful uses the different http verbs for CRUD operations.

    //POST     Create, Update, Delete
    //GET     Read
    //PUT     Create, Update
    //DELETE     Delete

    For example: If I want to insert new data, I'm thinking to invoke that astoria with "POST" and will pass the data as posted data. but it doesn't work.

    My question is ~ How Astoria knows what CRUD operations that I want to do? OR How can I tell Astoria what operation I wan to do?

    Becauase, there are same http verbs for different operations. (e.g. POST for Create, Update, Delete)

    Thanks in advance.

    Tuesday, March 11, 2008 5:23 PM

Answers

  • I beleive update is done via JSON... I am not sure about AtomPub

    take a look at Pablo Castro presentation on mix "RESTful data services using ADO.NET Data Services Framework" or download it from here

    There is a demo where Pablo insert new record via Fiddler

    Wednesday, March 12, 2008 10:43 AM
  • We support both atompub and json for updates. So the content-type can be either application/json or application/atom+xml. One can use application/atom+xml when you are doing a CUD operation on a entity, but if you are trying to do update a property of a entity type, then you will have to use application/xml, since the payload is not a atompub payload anymore.

     

    HTH

    Thanks

    Pratik

     

    Wednesday, March 12, 2008 3:43 PM
    Moderator
  •  

    Sync mode sample: Looks like the json you have specified is invalid. Can you please remove the ';' after the product name value and try again. For more information on json payload, you can visit this website: www.json.org. The property seperator in json is ',' not ';' and you need not specify the seperator when you have one property.

     

    Async mode sample: The json payload looks correct here, but uri seems wrong. Why did you comment out the first uri, which seems correct to me. Can you try using the first uri which is commented out and see if it works.

     

    Thanks

    Pratik

     

     

     

    Thursday, March 13, 2008 6:30 PM
    Moderator
  •  

    To insert a new record, the url must point to a collection. In the above example, the url must be http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products

     

    About the format being application/xml, if the url was referring to some property for e.g. http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products(17)/ProductName , then the format must be application/xml and it looks something like:

     

    <adsStick out tongueroductName>tedddddddddddddddddst111</adsStick out tongueroductName>

     

    HTH

    Thanks

    Pratik

    Monday, March 17, 2008 5:40 AM
    Moderator

All replies

  • Hi Michael,

     

    Do not forget you have also URL. AFAIK making POST request to

    http://localhost/Northwind.svc/ProductCategories

     will create a new record

    while POST request to http://localhost/Northwind.svc/ProductCategories[1] will update the pointed record.

     

    Hope this helps

     

    P.S. Here are some samples on my blog http://www.galcho.com/Blog/CategoryView.aspx?category=Astoria 

     

    Tuesday, March 11, 2008 7:37 PM
  • Hello Galin,

    Thanks a lot for your reply. I found your post from your blog. I have one more question.

    >>set Request's headers "Accept" AND "Content-Type" to "application/json"

    Setting json is a must?

    Yesterday, I tried making "POST" request but not working. The only difference that we have is that I used "application/x-www-form-urlencoded" instead of "application/json". So, Do I have to set application/json in order to make it work?


    Wednesday, March 12, 2008 2:11 AM
  • I beleive update is done via JSON... I am not sure about AtomPub

    take a look at Pablo Castro presentation on mix "RESTful data services using ADO.NET Data Services Framework" or download it from here

    There is a demo where Pablo insert new record via Fiddler

    Wednesday, March 12, 2008 10:43 AM
  • We support both atompub and json for updates. So the content-type can be either application/json or application/atom+xml. One can use application/atom+xml when you are doing a CUD operation on a entity, but if you are trying to do update a property of a entity type, then you will have to use application/xml, since the payload is not a atompub payload anymore.

     

    HTH

    Thanks

    Pratik

     

    Wednesday, March 12, 2008 3:43 PM
    Moderator
  • Thanks. I have tested with fiddler and it's working fine.  but it doesn't work with my C# code. I wrote the following code in Window Application and Web service is also running with static port "52976".

    I tried with the following c# code but not working.

    Sync-mode

                    string serviceURL = "http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products/";


                    pMessage = "{" + Environment.NewLine;
                    pMessage += "ProductName:\"zo1ne\";" + Environment.NewLine;
                    pMessage += "}" + Environment.NewLine;

                   
                    ASCIIEncoding encoding = new ASCIIEncoding();
                   
                    byte[] data = encoding.GetBytes(pMessage);

                    // Prepare web request...
                    HttpWebRequest myRequest =
                      (HttpWebRequest)WebRequest.Create(serviceURL);

                    myRequest.Method = "POST";
                    myRequest.ContentType = "application/json";
                    myRequest.ContentLength = data.Length;
                    Stream newStream = myRequest.GetRequestStream();
                    // Send the data.
                    newStream.Write(data, 0, data.Length);
                    newStream.Close();


    Async-Mode

            private static string pMessage;
            public static ManualResetEvent allDone = new ManualResetEvent(false);

            private void Form1_Load(object sender, EventArgs e) {
                try {

                    //string serviceURL = "http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products/";
                    string serviceURL = "http://localhost:52895/Service1.asmx/Service1";

                    pMessage = "{" + Environment.NewLine;
                    pMessage += "ProductName=\"zone\"" + Environment.NewLine;
                    pMessage += "}" + Environment.NewLine;


                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(serviceURL);
                    request.ContentType = "application/json";
                    request.UserAgent = "Fiddler";
                    //request.ContentType = "application/x-www-form-urlencoded";
                    request.Method = "POST";
                    request.BeginGetRequestStream(new AsyncCallback(ReadCallback), request);

                    // Keep the main thread from continuing while the asynchronous
                    // operation completes. A real world application
                    // could do something useful such as updating its user interface.
                    allDone.WaitOne();


                }
                catch (Exception ex) {
                    Console.Write(ex.Message);
                }
               
            }
           
            private static void ReadCallback(IAsyncResult asynchronousResult) {
                HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
                // End the operation.
                Stream postStream = request.EndGetRequestStream(asynchronousResult);

                string postData = pMessage;

                // Convert the string into a byte array.
                byte[] byteArray = Encoding.UTF8.GetBytes(postData);
                // Write to the request stream.
                postStream.Write(byteArray, 0, postData.Length);
                postStream.Close();
                allDone.Set();
            }

    Both codes are not working. Any idea? Did I miss something?

    Thanks in advance.

    Thursday, March 13, 2008 2:43 PM
  •  

    Sync mode sample: Looks like the json you have specified is invalid. Can you please remove the ';' after the product name value and try again. For more information on json payload, you can visit this website: www.json.org. The property seperator in json is ',' not ';' and you need not specify the seperator when you have one property.

     

    Async mode sample: The json payload looks correct here, but uri seems wrong. Why did you comment out the first uri, which seems correct to me. Can you try using the first uri which is commented out and see if it works.

     

    Thanks

    Pratik

     

     

     

    Thursday, March 13, 2008 6:30 PM
    Moderator
  • thanks. I have fixed the issue and found that it's working fine in C# winform. I think it might be something wrong with SL.
    I have posted this issue here. thanks a lot for your reply.
    Saturday, March 15, 2008 8:48 AM

  • I noticed one thing. I tried to update the record with fiddler.

    #1.

    POST

    http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products(16)

    Request Header

    User-Agent: Fiddler
    Content-Type: application/json

    Request Body

    {
      ProductName : 'zxc'
    }


    When I execute this, the new record will be added instead of updating. 

    -----------------------------------

    #2.

    I changed POST to PUT and tried to execute it again.


    POST

    http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products(16)

    Request Header

    User-Agent: Fiddler
    Content-Type: application/json

    Request Body

    {
      ProductName : 'zxc'
    }

    I got the following error.

    Error processing request stream. '__metadata' element must be present.
       at Microsoft.Data.Web.Serializers.JsonDeserializer.GetTypeAndUriFromMetadata(Hashtable jsonObject, ResourceType expectedType, IWebDataServiceProvider provider, String& uri, Boolean& metadataElementSpecified)
       at Microsoft.Data.Web.Serializers.JsonDeserializer.CreateObject(Object jsonObject, SegmentInfo segmentInfo, Boolean& existingRelationship, Boolean& existingResource)
       at Microsoft.Data.Web.Serializers.JsonDeserializer.CreateSingleObject(SegmentInfo segmentInfo, Boolean& existingRelationship, Boolean& existingResource)
       at Microsoft.Data.Web.Serializers.Deserializer.ReadEntity(RequestDescription requestDescription)
       at Microsoft.Data.Web.Serializers.Deserializer.UpdateEntity(RequestDescription description, IWebDataService dataService, Stream stream)
       at Microsoft.Data.Web.WebDataService`1.HandlePutOperation(RequestDescription description)
       at Microsoft.Data.Web.WebDataService`1.ProcessIncomingRequest()



    #3.


    I changed URL and tried to execute it again.


    POST

    http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products[16]

    or

    http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products!16

    Request Header

    User-Agent: Fiddler
    Content-Type: application/json

    Request Body

    {
      ProductName : 'zxc'
    }


    I got the following error.

    Resource not found.
       at Microsoft.Data.Web.WebUtil.CheckResourceExists(Boolean resourceExists)
       at Microsoft.Data.Web.RequestUriProcessor.ProcessRequestUri(String requestUri, IWebDataService service)
       at Microsoft.Data.Web.WebDataService`1.ProcessIncomingRequest()

    Any idea why I can't update?

    Thanks in advance.

    Saturday, March 15, 2008 12:37 PM
  • We support both atompub and json for updates. So the content-type can be either application/json or application/atom+xml. One can use application/atom+xml when you are doing a CUD operation on a entity, but if you are trying to do update a property of a entity type, then you will have to use application/xml, since the payload is not a atompub payload anymore.


    As Pratik said, I have tried to use application/xml. But I'm not sure what format I should use. I tried using JSON but not working. I tried XML format as below but not working too.


    <Products>
     <ProductName>theDDDrock</ProductName>
    </Products>


    I think I'm totally missing something about format..


    Saturday, March 15, 2008 2:35 PM
  • Strange!!! I tried the following in Fiddler but it insert new record instead of updating.. Sad

    POST
    http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products(17)

    User-Agent: Fiddler
    Content-Type: application/xml

    <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
    <entry xml:base="http://localhost:52976/SL2Astoria_Web/WebDataService.svc/" xmlns:ads="http://schemas.microsoft.com/ado/2007/08/dataweb" xmlns:adsm="http://schemas.microsoft.com/ado/2007/08/dataweb/metadata" adsm:type="MyStoreModel.Products" xmlns="http://www.w3.org/2005/Atom">
      <id>http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products(17)</id>
      <updated />
      <title />
    <author>
      <name />
      </author>
      <link rel="edit" href="Products(17)" title="Products" />
    <content type="application/xml">
      <adsStick out tongueroductID adsm:type="Int32">17</adsStick out tongueroductID>
      <adsStick out tongueroductName>tedddddddddddddddddst111</adsStick out tongueroductName>
      </content>
      </entry>
    Saturday, March 15, 2008 3:06 PM
  •  

    To insert a new record, the url must point to a collection. In the above example, the url must be http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products

     

    About the format being application/xml, if the url was referring to some property for e.g. http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products(17)/ProductName , then the format must be application/xml and it looks something like:

     

    <adsStick out tongueroductName>tedddddddddddddddddst111</adsStick out tongueroductName>

     

    HTH

    Thanks

    Pratik

    Monday, March 17, 2008 5:40 AM
    Moderator

  • Hello,

    Thanks for your reply.

    >>>To insert a new record, the url must point to a collection. In the above example, the url must be http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products

    Is this a bug if I'm able to insert new record when I'm using
    http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products(14)?

    As I wrote in previous thread, I'm able to insert new record even I'm using http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products(14)  (with ID).

    >>>About the format being application/xml, if the url was referring to some property for e.g. http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products(17)/ProductName , then the format must be application/xml and it looks something like:

    Why do I need to put the ProductName?

    >>><adsroductName>tedddddddddddddddddst111</adsroductName>

    Could you please tell me what "ads" is?

    What if I have more than two properties (e.g. Vender, etc) in my object? Do I have to use like http://....../products(17)/ProductName and
    http://....../products(17)/Vender and http://....../products(17)/etc ??

    Let's say I have a table as below

    ProductID   |||     ProductName ||| Vendor    |||  
    Min-ReorderQty
    -----------------------------------------------------------------------------------------------------------
    17              |||    Orange           ||| Cool Veg |||   20

    So, my entity object would be like

    - ProductID
    - ProductName
    - Vendor
    - Min-ReorderQty

    How can I update this record?

    Can I call like that?

    Http Verb : PUT
    URL        :
    http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products(17)

    Content-type : "application/xml"

    Body ~

    <Products>
      <ProductName>
    Grape </ProductName>
      <Vendor> Another Vendor </Vender>
      <Min-ReorderQty>30</Min-ReorderQty>
    </Products>

    Will it be working?

    Thanks in advance.


    Monday, March 17, 2008 6:35 AM
  •  

    Is this a bug if I'm able to insert new record when I'm using http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products(14)?

    Yes, this is a bug which has been fixed in the latest bits.

     

    about the other issue, i replied to the other mail thread: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3011471&SiteID=1

     

    Thanks

    Pratik

    Tuesday, April 1, 2008 5:11 PM
    Moderator