Odata batch issue - with nightly

Topics: ASP.NET Web API
May 22, 2013 at 9:13 AM
Edited May 22, 2013 at 9:30 AM
Hi,

I'm using the nightly to test the batch support of the Web API Odata. It works good when the batch body contains GET requests without changeset, but when I try updating(PUT) or creating(POST) with changeset, I do not get the call in the contoller.

here is the request:
POST http://localhost:53809/odata/$batch HTTP/1.1
Content-Type: multipart/mixed; boundary=batch_36522ad7-fc75-4b56-8c71-56071383e77b
Host: localhost:53809
Content-Length: 1473

--batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: multipart/mixed; boundary=changeset_77162fcd-b8da-41ac-a9f8-9357efbbd621 
Content-Length: 1000

--changeset(77162fcd-b8da-41ac-a9f8-9357efbbd621) 
Content-Type: application/http 
Content-Transfer-Encoding: binary

PUT /odata/Incidents HTTP/1.1
Host: localhost:53809
Content-Type: application/atom+xml
Content-Length: 1000

<?xml version="1.0" encoding="utf-8"?>
<entry xml:base="http://localhost:53809/odata/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml">
  <category term="Incidents.Incident" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
  <title />
  <updated>2013-05-21T07:47:39Z</updated>
  <author>
    <name />
  </author>
  <content type="application/xml">
    <m:properties>
      <d:IncidentID m:type="Edm.Int32">500</d:IncidentID>
      <d:Name>New Inc from Web API</d:Name>
    </m:properties>
  </content>
</entry>

--changeset(77162fcd-b8da-41ac-a9f8-9357efbbd621)-- 
--batch_36522ad7-fc75-4b56-8c71-56071383e77b--

respond:

HTTP/1.1 202 Accepted
Cache-Control: no-cache
Pragma: no-cache
Content-Type: multipart/mixed; boundary=batchresponse_652b36a4-684e-4642-9a9f-1ceda11ef110
Expires: -1
Server: Microsoft-IIS/8.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST,GET,DELETE,PATCH,PUT,OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, Accept,WWW-Authenticate
DataServiceVersion: 3.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcU01cNy4zXFRoaXJkUGFydHlXZWJBUElcb2RhdGFcJGJhdGNo?=
X-Powered-By: ASP.NET
Date: Wed, 22 May 2013 08:04:25 GMT
Content-Length: 268

--batchresponse_652b36a4-684e-4642-9a9f-1ceda11ef110
Content-Type: multipart/mixed; boundary=changesetresponse_1c719232-531d-43e5-805b-117fd7e5feb4

--changesetresponse_1c719232-531d-43e5-805b-117fd7e5feb4--
--batchresponse_652b36a4-684e-4642-9a9f-1ceda11ef110--
any idea?
thanks.
Developer
May 22, 2013 at 10:26 PM
Hi,

I tried to repro it on my machine and I haven't been able to do so. Can you copy your packages.config file to see which versions of the packages you are using? Also... does the put request work under normal circumstances? (without being inside a batch). Are you implementing the controller by extending EntitySetController or are you extending ODataController directly?
May 23, 2013 at 7:55 AM
Hi jacalvar, thanks for your reply.
  1. the put request is working under normal HTTP PUT request without the batch.
  2. I am extending EntitySetController.
  3. I should add that the EDM I am using (Incident in this example) is constructed manually this way:
            ODataModelBuilder builder = new ODataModelBuilder();
            EntitySetConfiguration<Incident> incident = builder.EntitySet<Incident>("Incidents");
            incident.EntityType.HasKey(c => c.IncidentID);
            incident.EntityType.Property(c => c.Name);

            incident.HasIdLink(eic =>
            {
                return eic.GenerateSelfLink(false);
            }, false);
  1. packages:
<packages>
  <package id="Microsoft.AspNet.Mvc" version="5.0.0-beta1-130519" targetFramework="net45" />
  <package id="Microsoft.AspNet.Razor" version="3.0.0-beta1-130519" targetFramework="net45" />
  <package id="Microsoft.AspNet.Web.Optimization" version="1.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi" version="5.0.0-beta1-130519" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.0.0-beta1-130519" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.0.0-beta1-130519" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.OData" version="5.0.0-beta1-130519" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.0.0-beta1-130519" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages" version="3.0.0-beta1-130519" targetFramework="net45" />
  <package id="Microsoft.Data.Edm" version="5.5.0-alpha2" targetFramework="net45" />
  <package id="Microsoft.Data.OData" version="5.5.0-alpha2" targetFramework="net45" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
  <package id="Microsoft.Web.Optimization" version="1.0.0-beta" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
  <package id="PerfIt" version="0.1.2.0" targetFramework="net45" />
  <package id="System.Spatial" version="5.5.0-alpha2" targetFramework="net45" />
  <package id="TypeScriptBundleTransform" version="1.0.0.8" targetFramework="net45" />
  <package id="Unity" version="3.0.1304.0" targetFramework="net45" />
  <package id="Unity.WebAPI" version="0.10" targetFramework="net45" />
  <package id="WebGrease" version="1.1.0" targetFramework="net45" />
</packages>
Developer
May 23, 2013 at 7:24 PM
Everything looks good but I'm worried about the following headers. Are you using CORS?

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST,GET,DELETE,PATCH,PUT,OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, Accept,WWW-Authenticate

Have your tried using the ODataConventionModelBuilder?
Can you share the classes?
Can you share a small repro if you have it?

My guess is that it could be an exception within the pipeline that we capture. Do you have the break on all exceptions enabled?
May 28, 2013 at 3:02 PM
Hi jacalvar,
  1. I removed CORS, it did not help.
  2. I've enabled all exception, noting there too.
I've made a small project that you can use to repro the same issue:

https://dl.dropboxusercontent.com/u/43745616/BatchIssueProject.rar

I got the same problem with it, "202 Accepted" is returned but CreateEntity in the controller is not called.


Thanks!
Developer
May 28, 2013 at 5:59 PM
Edited May 28, 2013 at 6:00 PM
Hi, I've figured out the problem, it was simpler than I thought. I assume you have built this request manually on fiddler or with any other utility, am I correct?

The problem is that the verb used for creating an entry is POST, not PUT, so either your verb is wrong in this request (it should be POST) or your url is wrong on the request and should be /odata/Incidents(500) (in that case you should also implement UpdateEntity in EntitySetController. I strongly encourage you to use WCF Data Services client or any OData client to test your services:

You only need to create a console app, start the service without debugging (CTRL+F5), right click on add service reference on the project you just created, point it to your OData Service url and it will generate an OData client.

You can then write code like the following:
            Container container = new Container(new Uri("http://localhost.fiddler:64630/odata"));
            container.AddToIncidents(new Incident() { IncidentID = 500, Name = "Incident name" });
            container.SaveChanges(SaveChangesOptions.Batch);

            Container newContainer = new Container(new Uri("http://localhost.fiddler:64630/odata"));
            Incident incident = newContainer.Incidents.Where(i => i.IncidentID == 500).ToList().Single();
            incident.Name = "Updated incident name";
            newContainer.UpdateObject(incident);
            newContainer.SaveChanges(SaveChangesOptions.Batch | SaveChangesOptions.ReplaceOnUpdate);
Here are the batch requests that I've created using the client and the associated responses, (forget about the .fiddler in the urls, that is just a trick to make sure the requests go trough fiddler):

Batch request creating an entry:
POST http://localhost:64630/odata/$batch HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 3.0;NetFx
Accept: multipart/mixed
Accept-Charset: UTF-8
Content-Type: multipart/mixed; boundary=batch_bf8a41b0-f692-44d1-a355-161e7e81cd97
Host: localhost:64630
Content-Length: 1186
Expect: 100-continue
Connection: Keep-Alive

--batch_bf8a41b0-f692-44d1-a355-161e7e81cd97
Content-Type: multipart/mixed; boundary=changeset_d1cf49c0-3a0c-4c9a-a9d4-38cfa4865d8c

--changeset_d1cf49c0-3a0c-4c9a-a9d4-38cfa4865d8c
Content-Type: application/http
Content-Transfer-Encoding: binary

POST http://localhost.fiddler:64630/odata/Incidents HTTP/1.1
Content-ID: 1
Content-Type: application/atom+xml
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 3.0;NetFx
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8

<?xml version="1.0" encoding="utf-8"?><entry xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><category term="BatchIssueProject.Models.Incident" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /><id /><title /><updated>2013-05-28T16:49:53Z</updated><author><name /></author><content type="application/xml"><m:properties><d:IncidentID m:type="Edm.Int32">500</d:IncidentID><d:Name>Incident name</d:Name></m:properties></content></entry>
--changeset_d1cf49c0-3a0c-4c9a-a9d4-38cfa4865d8c--
--batch_bf8a41b0-f692-44d1-a355-161e7e81cd97--
Response:
HTTP/1.1 202 Accepted
Cache-Control: no-cache
Pragma: no-cache
Content-Type: multipart/mixed; boundary=batchresponse_d1e737c1-04b0-4cf2-8737-8b53c23573a7
Expires: -1
Server: Microsoft-IIS/8.0
DataServiceVersion: 3.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcamFjYWx2YXJcRG93bmxvYWRzXEJhdGNoSXNzdWVQcm9qZWN0XEJhdGNoSXNzdWVQcm9qZWN0XG9kYXRhXCRiYXRjaA==?=
X-Powered-By: ASP.NET
Date: Tue, 28 May 2013 16:49:54 GMT
Content-Length: 1575

--batchresponse_d1e737c1-04b0-4cf2-8737-8b53c23573a7
Content-Type: multipart/mixed; boundary=changesetresponse_b5e7a26f-2329-4b3d-baf3-9b16c5d28b9d

--changesetresponse_b5e7a26f-2329-4b3d-baf3-9b16c5d28b9d
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 201 Created
Location: http://localhost.fiddler:64630/odata/Incidents(500)
Content-ID: 1
Content-Type: application/atom+xml; charset=utf-8
DataServiceVersion: 3.0

<?xml version="1.0" encoding="utf-8"?>
<entry xml:base="http://localhost.fiddler:64630/odata/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml">
  <id>http://localhost.fiddler:64630/odata/Incidents(500)</id>
  <category term="BatchIssueProject.Models.Incident" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
  <link rel="edit" href="http://localhost.fiddler:64630/odata/Incidents(500)" />
  <link rel="self" href="http://localhost.fiddler:64630/odata/Incidents(500)" />
  <title />
  <updated>2013-05-28T16:49:54Z</updated>
  <author>
    <name />
  </author>
  <content type="application/xml">
    <m:properties>
      <d:IncidentID m:type="Edm.Int32">500</d:IncidentID>
      <d:Name>Incident name</d:Name>
    </m:properties>
  </content>
</entry>
--changesetresponse_b5e7a26f-2329-4b3d-baf3-9b16c5d28b9d--
--batchresponse_d1e737c1-04b0-4cf2-8737-8b53c23573a7--
Batch request updating the same entry:
POST http://localhost:64630/odata/$batch HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 3.0;NetFx
Accept: multipart/mixed
Accept-Charset: UTF-8
Content-Type: multipart/mixed; boundary=batch_389f67d4-512f-4cb2-a692-f16f48bcdcb5
Host: localhost:64630
Content-Length: 1236
Expect: 100-continue

--batch_389f67d4-512f-4cb2-a692-f16f48bcdcb5
Content-Type: multipart/mixed; boundary=changeset_5f3f1fc4-0c79-40b5-8235-9a80159d9fd3

--changeset_5f3f1fc4-0c79-40b5-8235-9a80159d9fd3
Content-Type: application/http
Content-Transfer-Encoding: binary

PUT http://localhost:64630/odata/Incidents(500) HTTP/1.1
Content-ID: 2
Content-Type: application/atom+xml
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 3.0;NetFx
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8

<?xml version="1.0" encoding="utf-8"?><entry xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><id>http://localhost:64630/odata/Incidents(500)</id><category term="BatchIssueProject.Models.Incident" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /><title /><updated>2013-05-28T16:49:54Z</updated><author><name /></author><content type="application/xml"><m:properties><d:IncidentID m:type="Edm.Int32">500</d:IncidentID><d:Name>Updated incident name</d:Name></m:properties></content></entry>
--changeset_5f3f1fc4-0c79-40b5-8235-9a80159d9fd3--
--batch_389f67d4-512f-4cb2-a692-f16f48bcdcb5--
Response
HTTP/1.1 202 Accepted
Cache-Control: no-cache
Pragma: no-cache
Content-Type: multipart/mixed; boundary=batchresponse_f0993a32-f104-41f1-9c40-c566b2962aa7
Expires: -1
Server: Microsoft-IIS/8.0
DataServiceVersion: 3.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcamFjYWx2YXJcRG93bmxvYWRzXEJhdGNoSXNzdWVQcm9qZWN0XEJhdGNoSXNzdWVQcm9qZWN0XG9kYXRhXCRiYXRjaA==?=
X-Powered-By: ASP.NET
Date: Tue, 28 May 2013 16:49:54 GMT
Content-Length: 439

--batchresponse_f0993a32-f104-41f1-9c40-c566b2962aa7
Content-Type: multipart/mixed; boundary=changesetresponse_da4d5a22-4f2f-4706-983f-c8e5ff83970f

--changesetresponse_da4d5a22-4f2f-4706-983f-c8e5ff83970f
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
Content-ID: 2


--changesetresponse_da4d5a22-4f2f-4706-983f-c8e5ff83970f--
--batchresponse_f0993a32-f104-41f1-9c40-c566b2962aa7--