【问题标题】:Breeze Web API with Cordova Phone App Saving ChangesBreeze Web API 与 Cordova 电话应用程序保存更改
【发布时间】:2014-02-22 05:44:04
【问题描述】:

我创建了一个 ASP.NET MVC 4 Web API 项目并通过 NuGet 安装了 Breeze,包括客户端示例,并且 ToDo 应用程序运行良好。我还有通过 Cordova 在 Android 平板电脑上调用 WebAPI 运行的应用程序,除了保存实体时,这也很有效。我已对 Global.asax ("Access-Control-Allow-Origin", "*") 进行了适当的更改以支持跨域操作。

当 Android 客户端调用它的 saveChanges() 时,数据实际上被保存到数据库中,但它的失败承诺总是在客户端触发。

在 Web API 服务器上,我注意到通过浏览器进行 Breeze 调用时,我得到以下输出跟踪并成功保存:

iisexpress.exe Information: 0 : Operation=ODataActionFilter.ActionExecuting
iisexpress.exe Information: 0 : Message='Action returned 'Breeze.WebApi.SaveResult'', Operation=ReflectedHttpActionDescriptor.ExecuteAsync
iisexpress.exe Information: 0 : Message='Will use same 'JsonMediaTypeFormatter' formatter', Operation=JsonMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Selected formatter='JsonMediaTypeFormatter', content-type='application/json; charset=utf-8'', Operation=DefaultContentNegotiator.Negotiate
iisexpress.exe Information: 0 : Operation=ApiControllerActionInvoker.InvokeActionAsync, Status=200 (OK)
iisexpress.exe Information: 0 : Operation=ODataActionFilter.ActionExecuted, Status=200 (OK)
iisexpress.exe Information: 0 : Operation=BreezeSampleController.ExecuteAsync, Status=200 (OK)
**iisexpress.exe Information: 0 : Response, Status=200 (OK), Method=POST, Url=http://localhost:59912/api/BreezeSample/SaveChanges, Message='Content-type='application/json; charset=utf-8', content-length=unknown'**
iisexpress.exe Information: 0 : Operation=JsonMediaTypeFormatter.WriteToStreamAsync
iisexpress.exe Information: 0 : Operation=BreezeSampleController.Dispose

但是当从 Android 应用程序调用时,我得到了写入的数据,但是这个跟踪出现了错误:

iisexpress.exe Information: 0 : Message='Action returned 'Breeze.WebApi.SaveResult'', Operation=ReflectedHttpActionDescriptor.ExecuteAsync
iisexpress.exe Information: 0 : Message='Will use same 'XmlMediaTypeFormatter' formatter', Operation=XmlMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Selected formatter='XmlMediaTypeFormatter', content-type='application/xml; charset=utf-8'', Operation=DefaultContentNegotiator.Negotiate
iisexpress.exe Information: 0 : Operation=ApiControllerActionInvoker.InvokeActionAsync, Status=200 (OK)
iisexpress.exe Information: 0 : Operation=ODataActionFilter.ActionExecuted, Status=200 (OK)
iisexpress.exe Information: 0 : Operation=BreezeSampleController.ExecuteAsync, Status=200 (OK)
**iisexpress.exe Information: 0 : Response, Status=200 (OK), Method=POST, Url=http://192.168.1.9:59912/api/BreezeSample/SaveChanges, Message='Content-type='application/xml; charset=utf-8', content-length=unknown'**
iisexpress.exe Error: 0 : Operation=XmlMediaTypeFormatter.WriteToStreamAsync, Exception=System.Runtime.Serialization.SerializationException: Type 'SMHMobileAPI.Models.BreezeSampleTodoItem' with data contract name 'BreezeSampleTodoItem:http://schemas.datacontract.org/2004/07/SMHMobileAPI.Models' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
   at WriteArrayOfanyTypeToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , CollectionDataContract )
   at System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
   at WriteSaveResultToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract )
   at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter writer, Object graph)
   at System.Net.Http.Formatting.XmlMediaTypeFormatter.<>c__DisplayClass7.<WriteToStreamAsync>b__6()
   at System.Threading.Tasks.TaskHelpers.RunSynchronously(Action action, CancellationToken token)

除了一些序列化错误,我还注意到帖子标题“application/xml”。我不确定这是否相关,但如果有人可以提供帮助,我肯定需要一些帮助来尝试找到解决方案。

谢谢 标记

【问题讨论】:

    标签: breeze


    【解决方案1】:

    我很确定 "application/xml" 相关的。

    保存后,Breeze Web API 控制器将更新/添加的实体返回给您。您提到的“接受”标头会导致 Web API 尝试使用几乎总是失败的 XML 格式化程序格式化这些实体。

    我不认为 Breeze 本身不会在 POST 上设置 Accept 标头(我不确定它是否也在 GET 上设置了 Accept 标头)。

    查看 IE10 中 jQuery AJAX 生成的请求表明 GET 的 Accept 标头是 "application/json, text/javascript, */*; q=0.01"。对于 POST,Accept 和 Content-type 标头分别为 "*\*""application/json"

    您的 Android 流量中的 Accept 标头是什么?您没有指定将哪个标头设置为"application/xml" ...但由于这总是“错误”,我认为这并不重要:)

    您可以自定义 Breeze AJAX 适配器或完全替换它as described here。你可以试试:

    // 获取当前默认的 Breeze ajax 适配器 var ajaxAdapter = 微风.core.config.getAdapterInstance("ajax"); // 设置固定标题 ajaxAdapter.defaultSettings = { 标题:{ “接受”:“应用程序/json,文本/javascript,*/*;q=0.01” }, };

    这似乎在我对 IE10 和 Chrome 的测试中起到了作用。

    我还将建议 Breeze Web API JsonFormatterAttribute 删除 XML 格式化程序,因为我们知道它不适用于 Breeze 流量​​。

    希望这可行。

    【讨论】:

    • 非常感谢 Ward 添加 Accept 标头工作。现在看着这个 PhoneGap / Cordova Android 应用程序通过 .NET Web API 更新我的 EF 数据库,我脸上露出了灿烂的笑容。
    猜你喜欢
    • 2014-05-17
    • 2015-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    相关资源
    最近更新 更多