Wcf OData4j例外情况-“;奇数字符;及;键串“的无效值字符串部分”;
编辑:Wcf OData4j例外情况-“;奇数字符;及;键串“的无效值字符串部分”;,wcf,json,datetime,illegalargumentexception,odata4j,Wcf,Json,Datetime,Illegalargumentexception,Odata4j,编辑: 解决方案是创建一个镜像相关表的视图,并将日期转换为varchar,然后使用匹配的排序规则将其转换回日期 编辑结束 有人能告诉我为什么OData4j可以从我的一个WCF数据服务服务器读取日期时间值,但在从另一个WCF数据服务读取格式完全相同的日期时间类型时遇到非法参数异常(作为键字符串的一部分的错误值字符串) java.lang.IllegalArgumentException:错误的valueString [datetime'2012-01-24T14%3A57%3A22.243']作为
解决方案是创建一个镜像相关表的视图,并将日期转换为varchar,然后使用匹配的排序规则将其转换回日期 编辑结束 有人能告诉我为什么OData4j可以从我的一个WCF数据服务服务器读取日期时间值,但在从另一个WCF数据服务读取格式完全相同的日期时间类型时遇到非法参数异常(作为键字符串的一部分的错误值字符串) java.lang.IllegalArgumentException:错误的valueString [datetime'2012-01-24T14%3A57%3A22.243']作为键串的一部分 另一个问题是,当我从OData4j读取datetime类型没有问题的服务请求JSON响应时,我得到了另一个非法参数异常,错误消息是-奇数个字符 java.lang.IllegalArgumentException: org.odata4j.repack.org.apache.commons.codec.DecoderException:奇数 字符数 因为WCF数据服务不能有多个源,所以我用每个源自己的实体数据模型源(来自现有数据库)创建了两个项目。就像我上面提到的,我犯了这些恼人的错误 总之 示例1:错误的valueString作为keyString的一部分-在读取datetime时。
FormatType.JSON也会发生这种情况
ODataConsumer customerInfoServices = ODataConsumer
.newBuilder("http://10.0.2.2:41664/CustomerInfoWCFDataServices.svc/")
.setFormatType(FormatType.ATOM)
.build();
customer = customerInfoServices
.getEntities("Customers")
.select("name, id")
.filter("id eq " + 5)
.execute()
.firstOrNull();
示例2:奇数个字符。只有FormatType.JSON
发生,读取日期时间没有问题
ODataConsumer businessServices = ODataConsumer
.newBuilder("http://10.0.2.2:35932/BusinessWCFDataServices.svc/")
.setFormatType(FormatType.JSON)
.build();
Enumerable<?> ordrer = businessServices
.getEntities("Orders")
.filter("custId eq " + customer.getProperty("id").getValue())
.execute();
ODataConsumer businessServices=ODataConsumer
.newBuilder(“http://10.0.2.2:35932/BusinessWCFDataServices.svc/")
.setFormatType(FormatType.JSON)
.build();
可枚举ordrer=businessServices
.getEntities(“订单”)
.filter(“custId eq”+customer.getProperty(“id”).getValue()
.execute();
我想要的是接收JSON响应(ATOM对于android来说仍然过于臃肿),并且读取datetime属性没有问题
没有人能帮助我
我一直在努力在谷歌上找到解决方案,但运气不佳
没有日期时间问题的数据库的排序规则是“Danish_Norwegian_CI_AS”,而有读取错误的数据库的排序规则是“SQL_Danish_Pref_CP1_CI_AS”。我不知道这是否有任何意义,但我怀疑这与此有关。解决方案是创建一个视图,镜像相关表并将日期转换为varchar,然后使用匹配的排序规则将其转换回日期。:-) 我今天遇到了这个问题,在谷歌搜索和查看了大约三个小时的代码后,我设法弄明白了到底发生了什么。以下是我的设置/情况以及我的发现:
设置
(OData服务)Windows Server 2012上的Microsoft IIS 8.0使用
默认应用程序池
(OData生产商)微软WCF中间层
使用实体框架和Web数据服务李>
(小田消费者)
Android客户端使用OData4J v0.8快照
问题
在我的中间层(ODataProducer)中,我使用EntityFramework5.0定义一个带有Edm.DateTime
列的简单表。我的MessageTable.edmx
文件生成一个简单的表:
CREATE TABLE [dbo].[MessageTable] (
[Id] int IDENTITY(1,1) NOT NULL,
[Date1] datetime NULL
);
在中间层的WCF数据服务(OData Producer)中,我从Android客户端应用程序截取OData帖子。我使用一些C代码在中间层手动设置Date1列:
注意,我使用了C#的静态属性。MSDN文档说明DateTime.Now
:
获取一个DateTime对象,该对象设置为此计算机上的当前日期和时间,表示为本地时间
要认识到的关键是,本地时间意味着C#date时间结构现在包含本地时区信息
因此,在中间层代码完成后,WCF服务将OData POST插入到我的表中。然后,Microsoft将[Date1]
列发送回我的Android客户端(OData消费者)。Microsoft似乎将该日期编码为OData DateTimeOffset,因为它包含本地时区信息。即as2013-08-26T17:30:00.0000000-7:00
代码
在OData4j中,有一个包org.odata.internal
,用于解析odata日期时间字符串。在版本0.6中,我在第40-44行找到了关于用于解析日期时间字符串的DATETIME_模式regex模式的以下注释:
40 // Since not everybody seems to adhere to the spec, we are trying to be
41 // tolerant against different formats
42 // spec says:
43 // Edm.DateTime: yyyy-mm-ddThh:mm[:ss[.fffffff]]
44 // Edm.DateTimeOffset: yyyy-mm-ddThh:mm[:ss[.fffffff]](('+'|'-')hh':'mm)|'Z'
45 private static final Pattern DATETIME_PATTERN =
46 Pattern.compile("(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2})(:\\d{2})?(\\.\\d{1,7})?((?:(?:\\+|\\-)\\d{2}:\\d{2})|Z)?");
47
48
在OData4j v0.7中,DATETIME\u模式
已成为DATETIME\u XML\u模式
:
40
41 private static final Pattern DATETIME_XML_PATTERN = Pattern.compile("" +
42 "^" +
43 "(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2})" + // group 1 (datetime)
44 "(:\\d{2})?" + // group 2 (seconds)
45 "(\\.\\d{1,7})?" + // group 3 (nanoseconds)
46 "(Z)?" + // group 4 (tz, ignored - handles bad services)
47 "$");
48
49 private static final Pattern DATETIMEOFFSET_XML_PATTERN = Pattern.compile("" +
50 "^" +
51 "(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2})" + // group 1 (datetime)
52 "(\\.\\d{1,7})?" + // group 2 (nanoSeconds)
53 "(((\\+|-)\\d{2}:\\d{2})|(Z))" + // group 3 (offset) / group 6 (utc)
54 "$");
41 private static final Pattern DATETIME_XML_PATTERN = Pattern.compile("" +
42 "^" +
43 "(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2})" + // group 1 (datetime)
44 "(:\\d{2})?" + // group 2 (seconds)
45 "(\\.\\d{1,7})?" + // group 3 (nanoseconds)
46 "((?:(?:\\+|\\-)\\d{2}:\\d{2})|Z)?" +
47 "$");
我认为第46行的评论解释了一切:
…//第4组(tz,忽略-处理不良服务)
我将此理解为“任何时区信息都将被忽略-这将处理发送时区信息的坏服务(如Microsoft)”
在我看来,OData4j的作者们决定坚持自己的观点,只接受正确的Edm.DateTime
字符串格式
解决方案
如果您可以访问OData生产商代码,则修复非常简单:
private static void ProcessMessage(ODataMessage message)
{
.
.
.
conn.Open();
cmd.ExecuteNonQuery();
int returnCode = (int)cmd.Parameters["@result"].Value;
if (returnCode == 0)
{
message.Processed = true;
message.Date1 = DateTime.UtcNow;
}
.
.
.
}
改为使用属性。MSDN文档说明:
获取一个DateTime对象,该对象设置为此计算机上的当前日期和时间,表示为协调世界时(UTC)
如果您没有访问odataproducer的权限,我能看到的唯一解决方案就是更改OData4j代码。更改DATETIME\u XML\u模式的正则表达式模式
:
40
41 private static final Pattern DATETIME_XML_PATTERN = Pattern.compile("" +
42 "^" +
43 "(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2})" + // group 1 (datetime)
44 "(:\\d{2})?" + // group 2 (seconds)
45 "(\\.\\d{1,7})?" + // group 3 (nanoseconds)
46 "(Z)?" + // group 4 (tz, ignored - handles bad services)
47 "$");
48
49 private static final Pattern DATETIMEOFFSET_XML_PATTERN = Pattern.compile("" +
50 "^" +
51 "(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2})" + // group 1 (datetime)
52 "(\\.\\d{1,7})?" + // group 2 (nanoSeconds)
53 "(((\\+|-)\\d{2}:\\d{2})|(Z))" + // group 3 (offset) / group 6 (utc)
54 "$");
41 private static final Pattern DATETIME_XML_PATTERN = Pattern.compile("" +
42 "^" +
43 "(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2})" + // group 1 (datetime)
44 "(:\\d{2})?" + // group 2 (seconds)
45 "(\\.\\d{1,7})?" + // group 3 (nanoseconds)
46 "((?:(?:\\+|\\-)\\d{2}:\\d{2})|Z)?" +
47 "$");
结论
我认为这实际上是微软的一个错误。我确信他们发送Edm.DateTimeOffset
有一些复杂的理由,但我的MessageTable.edmx
文件将[Date1]
指定为Edm.DateTime
,因此我认为