The problem is that the .NET lib tries to be too smart about this.

The culprit is the AtomEntryCollection.Add overwrite. What this does  
is, that it creates a source wrapper when you add an entry that comes  
from an existing feed.

It should not do that. I filed bug:

http://code.google.com/p/google-gdata/issues/detail?id=209

For now, what i would recommend, if possible to restructure the code  
in a way that you:

a) either create all entries you add to the batchfeed
b) have the batchfeed point to the same feed uri (that is the reason  
the add() code believes it is required to create a source, when you  
construct the batchfeed you give that feed a different uri as a self  
uri). So if you change this line:

>   ContactsFeed batchFeed = new ContactsFeed
> (contactsFeed.Batch, contactsService);

to

>   ContactsFeed batchFeed = new ContactsFeed
> (contactsFeed.Self, contactsService);


that will probably fix the source issue, and by that reasoning the  
missing batch element issues as well, because CopyEntry on AtomEntry  
(which is invoked when you import a source element) does not copy the  
batch elements.

Frank

On Jan 28, 2009, at 9:57 AM, Matthias wrote:

>
> Hi Frank,
>
> thanks for your response.
> Regarding your first answer:
> Even if I set the default type of the batch feed to "insert" and
> assign each entry to operation type "update", the  <batch:operation/>
> elements are missing. I this still correct?!?
> Regarding the second post...
> This is the code that creates the batch entries:
>
>            List<ContactEntry> entriesToUpdate = new List<ContactEntry>
> ();
>
>            // update each resulting entry
>            for (int i = 0; i < createdEntries.Count; i++)
>            {
>                if (createdEntries[i].BatchData.Status.Code == 201) //
> created
>                {
>                    createdEntries[i].Title.Text += "updated";
>                    createdEntries[i].BatchData = new
> GDataBatchEntryData("update" + i.ToString(),
> GDataBatchOperationType.update);
>                    entriesToUpdate.Add((ContactEntry)createdEntries
> [i]);
>                }
>            }
>
>
> And this is the code (in another function) which creates the batch
> feed request using the entries created above (variable
> "contactEntries"):
>            // create contacts URI:
>            if (bShared)
>                uriString = "http://www.google.com/m8/feeds/contacts/";
> + userMail.Host + "/full";
>            else
>                uriString = "http://www.google.com/m8/feeds/contacts/";
> + userMail.Address + "/full";
>
>            Uri feedUri = new Uri(uriString);
>
>            ContactsQuery query = new ContactsQuery();
>            query.Uri = feedUri;
>            ContactsFeed contactsFeed = contactsService.Query(query);
>
>            AtomEntryCollection returnedEntries = new
> AtomEntryCollection(contactsFeed);
>            if (contactsFeed.Batch != null)
>            {
>
>                int i = 0;
>                while (i < contactEntries.Count)
>                {
>                    //Login(userMail.Address, password);
>
>                    ContactsFeed batchFeed = new ContactsFeed
> (contactsFeed.Batch, contactsService);
>                    batchFeed.BatchData = new GDataBatchFeedData();
>                    batchFeed.BatchData.Type = batchOperationType;
>
>                    int j = 0;
>                    while ( (j < limitEntriesBatchOperation) && (i <
> contactEntries.Count) )
>                    {
>                        ContactEntry ce = contactEntries[i];
>                        if (ce.BatchData == null)
>                        {
>                            if (batchOperationType ==
> GDataBatchOperationType.delete)
>                            {
>                                ContactEntry ceNew = new ContactEntry
> ();
>                                ceNew.Id = new AtomId
> (ce.Id.AbsoluteUri);
>                                ceNew.EditUri = ce.EditUri;
>                                ceNew.BatchData = new
> GDataBatchEntryData(i.ToString(), GDataBatchOperationType.delete);
>                                ce = ceNew;
>                            }
>                            else
>                            {
>                                ce.BatchData = new GDataBatchEntryData
> (i.ToString(), batchOperationType);
>                            }
>                        }
>                        batchFeed.Entries.Add(ce);
>                        //if ( (ce.Id != null) && (ce.Id.Uri != null)
> && (ce.BatchData == null) )
>                        //    //ce.BatchData = new GDataBatchEntryData
> (ce.Id.Uri.Content, batchOperationType);
>                        //    //ce.BatchData = new GDataBatchEntryData
> (i.ToString(), batchOperationType);
>
>                        i++;
>                        j++;
>                    }
>                    bool bSuccess = false;
>                    int nTries = 0;
>                    while ((!bSuccess) && (nTries < 10))
>                    {
>                        try
>                        {
>                            AtomFeed resultFeed = contactsService.Batch
> (batchFeed, new Uri(contactsFeed.Batch));
>                            bSuccess = true;
>                            foreach (AtomEntry entry in
> resultFeed.Entries)
>                            {
>                                returnedEntries.Add(entry);
>                            }
>                        }
>                        catch (Exception ex)
>                        {
>                            System.Diagnostics.Trace.WriteLine
> (ex.Message);
>                            nTries++;
>                            System.Threading.Thread.Sleep(2000);
>                        }
>                    }
>
>                }
>            }
>
> Just a side note:
> For the delete operation I had to create new entries with only Id,
> EditUri and BatchData properties set. Otherwise it did not work for
> me.
>
> With this code I get the batch update request that I sent in my first
> post...
> Is something wrong with the code?
>
> Regards
> Matthias
>
>
> On 27 Jan., 15:46, Frank Mantek <[email protected]> wrote:
>> Ok, a correction on my side. I misread your original post. The server
>> is complaining about a missing "entry id", not a missing batch id.
>>
>> Now, while that message could be clearer, it pinpointed the problem.
>> In the update feed you are sending, the entries you are updating are
>> contained inside a <source> tag?
>>
>> Why is that? How did you create that update feed?
>>
>> Regards
>>
>> Frank Mantek
>> Google
>>
>> On Jan 27, 1:43 pm, Frank Mantek <[email protected]> wrote:
>>
>>
>>
>>> regarding the different operations..
>>
>>> from the spec:
>>
>>> An operations feed contains a list of entries to insert, update,
>>> delete, or query. Each operation is defined by a <batch:operation
>>> type="insert|update|delete|query"/> element.
>>
>>> This element may be a direct child of a <feed> element, a direct  
>>> child
>>> of any of the entries in the feed, or both. When included in an  
>>> entry,
>>> it specifies the operation to execute for that specific entry. When
>>> included in the feed, this element specifies the default operation  
>>> to
>>> execute on any entries that do not have a <batch:operation/>  
>>> element.
>>
>>> So that the update feed contains a batch:operation only on the feed
>>> level is quiet alright.
>>
>>> For the operation id:
>>
>>> GData entry results are not necessarily returned in the same order  
>>> as
>>> the request. You can track an operation through its lifetime using  
>>> an
>>> identifier.
>>
>>> For update, delete, and query operations, you can use the id of the
>>> entry itself to track the operation.
>>
>>> For insert operations, since no ID yet exists, you can pass in an
>>> operation identifier. This identifier can be used to link the result
>>> entries to the request entries. The operation identifier is passed  
>>> in
>>> the <batch:id> element.
>>
>>> So, to me it looks like that update feed is just fine on the wire.  
>>> Why
>>> your insert feed has the operation several times (on the feed and
>>> entry level) i don't know, if you specify this explictly, the client
>>> lib will not try to be smart and "fold" that together...
>>
>>> So, in principle, just by looking at what you deemed suspicious,  
>>> this
>>> looks fine.
>>
>>> Someone from the contacts support team needs to look at this. This
>>> looks like a server side problem, the contacts server should not
>>> require a batch id for updates (or, we need to fix the  
>>> documenation).
>>> Beside that, if your code actually sets the BatchData.Id element  
>>> (and
>>> it is probably doing this for inserts somewhere else), the .NET  
>>> client
>>> should send the id. I am looking at the batch unitiest in gbase.cs  
>>> in
>>> the unittest directory, and that one is setting the ID explictly for
>>> everything (the .net lib is not magically creating ids).
>>
>>> Frank Mantek
>>> Google
>>> On Jan 27, 2009, at 12:50 PM, Matthias wrote:
>>
>>>> Hi,
>>
>>>> I am actually working on a C# application for managing shared  
>>>> contacts
>>>> using the .NET Client Library.
>>>> This application shall use batch feeds.
>>>> The batch feed works fine for inserting and also deleting contacts.
>>>> However I have a problem with updating contact entries. When I  
>>>> try to
>>>> update a couple of entries, I get back a collection with only one
>>>> entry, which has a batch data status code 400 and an error message
>>>> "Missing entry Id".
>>
>>>> I debugged the problem down to the source code of the client  
>>>> library
>>>> and checked the raw requests that are sent. These requests seemt to
>>>> look quite different for inserts and updates, so I am wondering  
>>>> if I
>>>> found a bug in the library. Could anyone please give a comment, so
>>>> that I can raise an issue if necessary? Thanks!
>>
>>>> Here is the batch request for inserting 3 contact entries (which  
>>>> works
>>>> fine):
>>
>>>> <?xml version="1.0" encoding="utf-8"?>
>>>> <feed xmlns="http://www.w3.org/2005/Atom"; xmlns:batch="http://
>>>> schemas.google.com/gdata/batch" xmlns:gd="http://schemas.google.com/g/
>>>> 2005">
>>>>  <batch:operation type="insert" />
>>>>  <entry>
>>>>    <gd:email address="[email protected]" primary="true"  
>>>> rel="http://
>>>> schemas.google.com/g/2005#work" />
>>>>    <batch:id>insert0</batch:id>
>>>>    <batch:operation type="insert" />
>>>>    <title type="text">Test User 0</title>
>>>>    <category term="http://schemas.google.com/contact/2008#contact";
>>>> scheme="http://schemas.google.com/g/2005#kind"; />
>>>>  </entry>
>>>>  <entry>
>>>>    <gd:email address="[email protected]" primary="true"  
>>>> rel="http://
>>>> schemas.google.com/g/2005#work" />
>>>>    <batch:id>insert1</batch:id>
>>>>    <batch:operation type="insert" />
>>>>    <title type="text">Test User 1</title>
>>>>    <category term="http://schemas.google.com/contact/2008#contact";
>>>> scheme="http://schemas.google.com/g/2005#kind"; />
>>>>  </entry>
>>>>  <entry>
>>>>    <gd:email address="[email protected]" primary="true"  
>>>> rel="http://
>>>> schemas.google.com/g/2005#work" />
>>>>    <batch:id>insert2</batch:id>
>>>>    <batch:operation type="insert" />
>>>>    <title type="text">Test User 2</title>
>>>>    <category term="http://schemas.google.com/contact/2008#contact";
>>>> scheme="http://schemas.google.com/g/2005#kind"; />
>>>>  </entry>
>>>> </feed>
>>
>>>> And here is the batch feed for updating the newly created contact
>>>> entries (which fails):
>>>> <?xml version="1.0" encoding="utf-8"?>
>>>> <feed xmlns="http://www.w3.org/2005/Atom"; xmlns:batch="http://
>>>> schemas.google.com/gdata/batch" xmlns:gd="http://schemas.google.com/g/
>>>> 2005">
>>>>  <batch:operation type="update" />
>>>>  <entry>
>>>>    <gd:email address="[email protected]" primary="true"  
>>>> rel="http://
>>>> schemas.google.com/g/2005#work" />
>>>>    <title type="text">Test User 0updated</title>
>>>>    <link href="http://www.google.com/m8/feeds/photos/media/induit.de/
>>>> 6438a1ca8a831b6d/1B2M2Y8AsgTpgAmY7PhCfg" rel="http://
>>>> schemas.google.com/contacts/2008/rel#edit-photo" type="image/*" />
>>>>    <link href="http://www.google.com/m8/feeds/contacts/induit.de/full/
>>>> 6438a1ca8a831b6d" rel="self" type="application/atom+xml" />
>>>>    <link href="http://www.google.com/m8/feeds/contacts/induit.de/full/
>>>> 6438a1ca8a831b6d/1233055640422000" rel="edit" type="application/ 
>>>> atom
>>>> +xml" />
>>>>    <category term="http://schemas.google.com/contact/2008#contact";
>>>> scheme="http://schemas.google.com/g/2005#kind"; />
>>>>    <content type="text" />
>>>>    <source>
>>>>      <id>http://www.google.com/m8/feeds/contacts/induit.de/full</ 
>>>> id>
>>>>      <link href="http://www.google.com/m8/feeds/contacts/induit.de/
>>>> full" rel="http://schemas.google.com/g/2005#feed";  
>>>> type="application/
>>>> atom+xml" />
>>>>      <link href="http://www.google.com/m8/feeds/contacts/induit.de/
>>>> full" rel="http://schemas.google.com/g/2005#post";  
>>>> type="application/
>>>> atom+xml" />
>>>>      <link href="http://www.google.com/m8/feeds/contacts/induit.de/
>>>> full/batch" rel="http://schemas.google.com/g/2005#batch";
>>>> type="application/atom+xml" />
>>>>      <title type="text">Batch Feed</title>
>>>>      <updated>2009-01-27T12:27:20+01:00</updated>
>>>>    </source>
>>>>    <updated>2009-01-27T12:27:20+01:00</updated>
>>>>  </entry>
>>>>  <entry>
>>>>    <gd:email address="[email protected]" primary="true"  
>>>> rel="http://
>>>> schemas.google.com/g/2005#work" />
>>>>    <title type="text">Test User 1updated</title>
>>>>    <link href="http://www.google.com/m8/feeds/photos/media/induit.de/
>>>> 565ab6a28f1faf82/1B2M2Y8AsgTpgAmY7PhCfg" rel="http://
>>>> schemas.google.com/contacts/2008/rel#edit-photo" type="image/*" />
>>>>    <link href="http://www.google.com/m8/feeds/contacts/induit.de/full/
>>>> 565ab6a28f1faf82" rel="self" type="application/atom+xml" />
>>>>    <link href="http://www.google.com/m8/feeds/contacts/induit.de/full/
>>>> 565ab6a28f1faf82/1233055640533000" rel="edit" type="application/ 
>>>> atom
>>>> +xml" />
>>>>    <category term="http://schemas.google.com/contact/2008#contact";
>>>> scheme="http://schemas.google.com/g/2005#kind"; />
>>>>    <content type="text" />
>>>>    <source>
>>>>      <id>http://www.google.com/m8/feeds/contacts/induit.de/full</ 
>>>> id>
>>>>      <link href="http://www.google.com/m8/feeds/contacts/induit.de/
>>>> full" rel="http://schemas.google.com/g/2005#feed";  
>>>> type="application/
>>>> atom+xml" />
>>>>      <link href="http://www.google.com/m8/feeds/contacts/induit.de/
>>>> full" rel="http://schemas.google.com/g/2005#post";  
>>>> type="application/
>>>> atom+xml" />
>>>>      <link href="http://www.google.com/m8/feeds/contacts/induit.de/
>>>> full/batch" rel="http://schemas.google.com/g/2005#batch";
>>>> type="application/atom+xml" />
>>>>      <title type="text">Batch Feed</title>
>>>>      <updated>2009-01-27T12:27:20+01:00</updated>
>>>>    </source>
>>>>    <updated>2009-01-27T12:27:20+01:00</updated>
>>>>  </entry>
>>>>  <entry>
>>>>    <gd:email address="[email protected]" primary="true"  
>>>> rel="http://
>>>> schemas.google.com/g/2005#work" />
>>>>    <title type="text">Test User 2updated</title>
>>>>    <link href="http://www.google.com/m8/feeds/photos/media/induit.de/
>>>> 52cba980a0d385b/1B2M2Y8AsgTpgAmY7PhCfg" rel="http://
>>>> schemas.google.com/
>>>> contacts/2008/rel#edit-photo" type="image/*" />
>>>>    <link href="http://www.google.com/m8/feeds/contacts/induit.de/full/
>>>> 52cba980a0d385b" rel="self" type="application/atom+xml" />
>>>>    <link href="http://www.google.com/m8/feeds/contacts/induit.de/full/
>>>> 52cba980a0d385b/1233055640674000" rel="edit" type="application/atom
>>>> +xml" />
>>>>    <category term="http://schemas.google.com/contact/2008#contact";
>>>> scheme="http://schemas.google.com/g/2005#kind"; />
>>>>    <content type="text" />
>>>>    <source>
>>>>      <id>http://www.google.com/m8/feeds/contacts/induit.de/full</ 
>>>> id>
>>>>      <link href="http://www.google.com/m8/feeds/contacts/induit.de/
>>>> full"
>>
>> ...
>>
>> Erfahren Sie mehr ยป- Zitierten Text ausblenden -
>>
>> - Zitierten Text anzeigen -
> >


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Google Contacts API" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/google-contacts-api?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to