3

我一直在尝试使用 Breezejs 和 WebAPI OData 控制器发布实体。
以下是配置:

config.Routes.MapODataRoute(
routeName: "odata",
routePrefix: "odata",
model: model,
batchHandler: new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));

模型非常简单的地方:

public class ServiceMetadata
{
    public int ServiceMetadataId { get; set; }
    public string ServiceName { get; set; }
    public string Description { get; set; }
    public ObjectState? State { get; set; }
    public DateTime? LastUpdated { get; set; }
}

它通过默认映射:

ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();

使用 AngularJs 和部分来自 Todo 示例的客户端也非常简单: http ://www.breezejs.com/samples/todo-angular

breeze.config.initializeAdapterInstance("modelLibrary", "backingStore", true);
var serviceName = 'http://localhost:8081/odata/';
breeze.config.initializeAdapterInstances({ dataService: "OData" });
var manager = new breeze.EntityManager(serviceName);
manager.enableSaveQueuing(true);

实际的发布是使用默认的 createEntity() 方法完成的:

function createServiceMetadata(initialValues) {
    return manager.createEntity('ServiceMetadata', initialValues);
}

整个事情看起来像:

 serviceMetadatas.createServiceMetadata({
     ServiceName: $scope.newServiceName,
     Description: $scope.newServiceDescription
 });

 serviceMetadatas.saveChanges();


但是,请求没有被传输到正确的控制器(继承自 EntitySetController 的 ServiceMetadatasController),或任何其他控制器。
HTTP 请求如下所示:

    POST http://localhost:8081/odata/$batch HTTP/1.1
Host: localhost:8081
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0
Accept: multipart/mixed
Accept-Language: he-IL,he;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DataServiceVersion: 2.0
Content-Type: multipart/mixed; charset=UTF-8;boundary=batch_4f09-d7cf-dd99
MaxDataServiceVersion: 2.0
Referer: http://localhost:9000/
Content-Length: 580
Origin: http://localhost:9000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache


--batch_4f09-d7cf-dd99
Content-Type: multipart/mixed; boundary=changeset_ca0c-06b7-ddbe

--changeset_ca0c-06b7-ddbe
Content-Type: application/http
Content-Transfer-Encoding: binary

POST ServiceMetadatas HTTP/1.1
Content-ID: 1
DataServiceVersion: 2.0
Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1
Content-Type: application/json;odata=verbose
MaxDataServiceVersion: 2.0

{"ServiceMetadataId":-1,"ServiceName":"sdf sdf","Description":"sd fgs df","LastUpdated":null}
--changeset_ca0c-06b7-ddbe--

--batch_4f09-d7cf-dd99--

和回应:

    HTTP/1.1 202 Accepted
Cache-Control: no-cache
Pragma: no-cache
Content-Type: multipart/mixed; boundary=batchresponse_966d4460-e00e-4900-b1c9-85b17081cfac
Expires: -1
Server: Microsoft-IIS/8.0
Access-Control-Allow-Origin: http://localhost:9000
Access-Control-Allow-Credentials: true
DataServiceVersion: 2.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcVG9tZXJcRG9jdW1lbnRzXFZpc3VhbCBTdHVkaW8gMjAxMlxQcm9qZWN0c1xFYXN5Qml6eVxFYXN5Qml6eS5XZWJBUElcb2RhdGFcJGJhdGNo?=
X-Powered-By: ASP.NET
Date: Sun, 15 Sep 2013 14:32:39 GMT
Content-Length: 443

--batchresponse_966d4460-e00e-4900-b1c9-85b17081cfac
Content-Type: multipart/mixed; boundary=changesetresponse_44da5dcf-877d-4041-a82b-c51d06a4e9a4

--changesetresponse_44da5dcf-877d-4041-a82b-c51d06a4e9a4
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 406 Not Acceptable
Content-ID: 1


--changesetresponse_44da5dcf-877d-4041-a82b-c51d06a4e9a4--
--batchresponse_966d4460-e00e-4900-b1c9-85b17081cfac--

知道黑客发生了什么吗?BTW GET 请求效果很好。

PS 在看了几个演示之后,我虽然考虑到 WebApi 和 OData,但使用 BreezeJS 会很简单。
我必须说,配置这个JS库并不容易。我希望它会变得难以设置但易于使用。

谢谢。

@UPDATE哈维尔的好答案!!

在仔细研究了微风代码后,我意识到问题在于微风js的createChangeRequests()深处,就在这里:

request.requestUri = entity.entityType.defaultResourceName;

由于某种原因,defaultResouceName 完全忽略了该实体的路径。长话短说,以下是要解决的 hack:

manager.metadataStore.getEntityType(ENTITY_TYPE).setProperties({defaultResourceName: THE_MISSING_PART_FROM_THE_URL + ENTITY_TYPE});
manager.createEntity(ENTITY_TYPE, values);

不是很好,但仍然有效!

4

3 回答 3

4

新的答案是 .. 使用webApiOData数据服务而不是“OData”:

breeze.config.initializeAdapterInstances({ 
  dataService : 'webApiOData'
});
于 2014-04-26T13:07:32.687 回答
3

问题出在内部请求的 url 中。url 需要相对于主机。假设您的服务托管在host/service(在我们的例子中,服务将等同于 odata 前缀),因此通常您发送类似host/service/Customersor的请求/service/Customers

当您发出批处理请求时,内部请求中的 url 可能是绝对的或相对于主机的。问题是在您的请求中,url 是ServiceMetadatas相对于服务根目录的,而不是主机。

Web API 将相对 url 解释为host/ServiceMetadatas而不是 as host/service/ServiceMetadatas,这就是导致错误的原因。

根据您的复制项目,以下请求可以正常工作:

POST http://localhost:6974/odata/$batch HTTP/1.1
Host: localhost:6974
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0
Accept: multipart/mixed
Accept-Language: he-IL,he;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DataServiceVersion: 2.0
Content-Type: multipart/mixed; charset=UTF-8;boundary=batch_4f09-d7cf-dd99
MaxDataServiceVersion: 2.0
Referer: http://localhost:9000/
Content-Length: 565
Origin: http://localhost:9000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

--batch_4f09-d7cf-dd99
Content-Type: multipart/mixed; boundary=changeset_ca0c-06b7-ddbe

--changeset_ca0c-06b7-ddbe
Content-Type: application/http
Content-Transfer-Encoding: binary

POST odata/ServiceMetadatas HTTP/1.1
Content-ID: 1
DataServiceVersion: 2.0
Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1
Content-Type: application/json;odata=verbose
MaxDataServiceVersion: 2.0

{"ServiceMetadataId":-1,"ServiceName":"sdf sdf","Description":"sd fgs df"}
--changeset_ca0c-06b7-ddbe--

--batch_4f09-d7cf-dd99--

相关响应如下:

HTTP/1.1 202 Accepted
Cache-Control: no-cache
Pragma: no-cache
Content-Type: multipart/mixed; boundary=batchresponse_6779b5e5-6e40-4363-9a98-5a33d062da28
Expires: -1
Server: Microsoft-IIS/8.0
DataServiceVersion: 2.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcamFjYWx2YXJcRG93bmxvYWRzXE9EYXRhQmF0Y2gtbWFzdGVyXENsZWFuV2ViQXBpUHJvamVjdFxvZGF0YVwkYmF0Y2g=?=
X-Powered-By: ASP.NET
Date: Tue, 17 Sep 2013 16:48:50 GMT
Content-Length: 872

--batchresponse_6779b5e5-6e40-4363-9a98-5a33d062da28
Content-Type: multipart/mixed; boundary=changesetresponse_b63ca946-ce66-43e6-a78f-d44a5b8f2d5c

--changesetresponse_b63ca946-ce66-43e6-a78f-d44a5b8f2d5c
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 201 Created
Location: http://localhost:6974/odata/ServiceMetadatas(-1)
Content-ID: 1
Content-Type: application/json; odata=verbose; charset=utf-8
DataServiceVersion: 2.0

{
  "d":{
    "__metadata":{
      "id":"http://localhost:6974/odata/ServiceMetadatas(-1)","uri":"http://localhost:6974/odata/ServiceMetadatas(-1)","type":"CleanWebApiProject.Models.ServiceMetadata"
    },"ServiceMetadataId":-1,"ServiceName":"sdf sdf","Description":"sd fgs df"
  }
}
--changesetresponse_b63ca946-ce66-43e6-a78f-d44a5b8f2d5c--
--batchresponse_6779b5e5-6e40-4363-9a98-5a33d062da28--

我在控制器中所做的唯一更改如下(与批处理无关):

public class ServiceMetadatasController : EntitySetController<ServiceMetadata, int>
{
    protected override ServiceMetadata CreateEntity(ServiceMetadata entity)
    {
        return entity;
    }

    protected override int GetKey(ServiceMetadata entity)
    {
        return entity.ServiceMetadataId;
    }

    public override IQueryable<ServiceMetadata> Get()
    {
        return new List<ServiceMetadata>
               {
                   new ServiceMetadata() {ServiceName = "Service1", Description = "Desc1"},
                   new ServiceMetadata() {ServiceName = "Service2", Description = "Desc1"}

               }.AsQueryable();
    }

}

我希望这可以解决您的问题,如果您是手动生成内部请求的 url 或者是轻率的为您生成的 url,请告诉我,以便我可以跟进并确保它得到修复。

于 2013-09-17T17:02:23.287 回答
0

不确定这是否是您的问题,但 Microsoft 的 ODataModelBuilder 没有实现完整的 OData 模型。特别是,它不会生成外键约束。MS 意识到了这一点,并计划在以后的版本中对其进行更新。在此之前,最好使用 WCF 数据服务来创建 OData 端点。

于 2013-09-16T18:20:13.990 回答