如果Model具有Int64,则放置/发布json不能与ODataController一起使用

时间:2014-08-18 16:18:27

标签: json rest odata

我有一个带有Int64列的数据对象:

[TableAttribute(Name="dbo.vw_RelationLineOfBusiness")]
[DataServiceKey("ProviderRelationLobId")] 
public partial class RelationLineOfBusiness
{

    #region Column Mappings
    private System.Guid _Lineofbusiness;
    private System.String _ContractNumber;
    private System.Nullable<System.Int32> _ProviderType;
    private System.String _InsuredProviderType;
    private System.Guid _ProviderRelationLobId;
    private System.String _LineOfBusinessDesc;
    private System.String _CultureCode;
    private System.String _ContractDesc;
    private System.Nullable<System.Guid> _ProviderRelationKey;
    private System.String _ProviderRelationNbr;
    **private System.Int64 _AssignedNbr;**

当我使用HttpClient和NewtsonSoft通过我的OData控制器发布/放置对象时:

partial class RelationLineOfBusinessController:ODataController {

public HttpResponseMessage PutRelationLineOfBusiness([FromODataUri] System.Guid key,Invidasys.VidaPro.Model.RelationLineOfBusiness entity)

实体对象为null,我的模型状态中出现错误:

&#34;无法将原始值转换为预期类型&#39; Edm.Int64&#39;。有关详细信息,请参阅内部异常。&#34;

我注意到当我使用以下网址获取对象时:

Invidasys.Rest.Service / VidaPro / RelationLineOfBusiness(GUID&#39; c6824edc-23b4-4f76-a777-108d482c0fee&#39)

我的json看起来如下 - 我注意到AssignedNbr被视为一个字符串。

{   &#34; odata.metadata&#34;:&#34; Invidasys.Rest.Service/VIDAPro/$metadata#RelationLineOfBusiness/@Element" ;,     &#34; Lineofbusiness&#34;:&#34; ba129c95-c5bb-4e40-993e-c28ca86fffe4&#34;&#34; ContractNumber&#34;:空,&#34; ProviderType&#34;:空, &#34; InsuredProviderType&#34;:&#34; PCP&#34;&#34; ProviderRelationLobId&#34;:&#34; c6824edc-23b4-4f76-a777-108d482c0fee&#34 ;, &#34; LineOfBusinessDesc&#34;:&#34; MEDICAID&#34;&#34; CultureCode&#34;:&#34; EN-US&#34;&#34; ContractDesc&#34;:无效, &#34; ProviderRelationKey&#34;:&#34; a2d3b61f-3d76-46f4-9887-f2b0c8966914&#34;&#34; ProviderRelationNbr&#34;:&#34; 4565454645&#34 ;, 的&#34; AssignedNbr&#34;:&#34; 1000000045&#34; 下,&#34; Ispar&#34;:真,&#34; ProviderTypeDesc&#34;:空,&#34 ; InsuredProviderTypeDesc&#34;:&#34;初级保健医生&#34;, &#34;起始日期&#34;:&#34; 2012-01-01T00:00:00&#34;&#34;结束日期&#34;:&#34; 2014-01-01T00:00:00&#34 ;,&#34;创建&#34;:&#34; 2014-06-13T10:59:33.567&#34 ;, &#34; CreatedBy&#34;:&#34;迈克尔&#34;&#34;已更新&#34;:&#34; 2014-06-13T10:59:33.567&#34;&#34; UpdatedBy& #34;:&#34;迈克尔&#34; }

当我使用httpclient进行PUT时,JSON出现在我的restful服务中,如下所示,AssignedNbr列的json不在引号中,导致restful服务无法将JSON构建回对象。我玩了JSON并将AssignedNbr放在引号中,请求正确。

{的&#34; AssignedNbr&#34;:1000000045 下,&#34; ContractDesc&#34;:空,&#34; ContractNumber&#34;:空,&#34;创建&# 34;:&#34; /日期(1402682373567-0700)/&#34 ;, &#34; CreatedBy&#34;:&#34;迈克尔&#34;&#34; CultureCode&#34;:&#34; EN-US&#34;&#34;结束日期&#34;:&#34 ; /日期(1388559600000-0700)/&#34;&#34; InsuredProviderType&#34;:&#34; PCP&#34 ;, &#34; InsuredProviderTypeDesc&#34;:&#34;初级保健医生&#34;,&#34; Ispar&#34;:true,&#34; LineOfBusinessDesc&#34;:&#34; MEDICAID&#34;, &#34; Lineofbusiness&#34;:&#34; ba129c95-c5bb-4e40-993e-c28ca86fffe4&#34;&#34; ProviderRelationKey&#34;:&#34; a2d3b61f-3d76-46f4-9887-f2b0c8966914&#34 ;, &#34; ProviderRelationLobId&#34;:&#34; c6824edc-23b4-4f76-a777-108d482c0fee&#34;&#34; ProviderRelationNbr&#34;:&#34; 4565454645&#34;&#34; ProviderType&# 34;:空, &#34; ProviderTypeDesc&#34;:空,&#34;起始日期&#34;:&#34; /日期(1325401200000-0700)/&#34;&#34;已更新&#34;:&#34; /日期(1408374995760-0700)/&#34;&#34; UpdatedBy&#34;:&#34; ED&#34;}

我们希望将业务模型公开为restful服务的原因是隐藏任何数据验证并以易于开发的格式公开我们所有的数据库。我查看了DataServiceContext以查看它是否可以正常工作,但它使用XML在restful服务和客户端之间进行通信。哪个可行,但DataServiceContext没有给出HttpRequestMessage / HttpResponseMessage给我的消息传递级别,用于通过帖子通知用户错误/缺失信息。

我们计划从我们的restful服务平台支持多个设备,但这需要我可以使用NewtonSoft Json以及Microsoft的DataContractJsonSerializer(如果需要)。

我的问题是为了一个宁静的服务立场 - 有没有办法我可以配置/编码宁静的服务,以便像JSON一样接受AssignedNbr,而不是引号。

或者从JSON的角度来看,他是一种可以在不进入序列化业务的情况下构建JSON的方式,如果他们想要针对我们的其他服务编写自己的应用程序,我也不希望我们的客户处理自定义序列化程序。 / p>

有什么建议吗?

感谢。

2 个答案:

答案 0 :(得分:5)

我认为您可以迁移到适用于OData V4的Web API 2.2。这是信息:

Announcing the Release of ASP.NET MVC 5.2, Web API 2.2 and Web Pages 3.2

OData V4 Spec说:

3.2控制数字表示

IEEE754Compatible = true格式参数表示服务必须将Edm.Int64和Edm.Decimal数字(包括odata.count,如果请求)序列化为字符串。如果未指定或指定为IEEE754Compatible = false,则所有数字必须序列化为JSON编号。

这样可以支持定义为64位二进制格式IEEE 754值[ ECMAScript ]的JavaScript编号(参见第4.3.1.9节),导致整数丢失精度超过15位数,并且小数由于从基数10到基数2的转换而失去精度。 将Edm.Int64和Edm.Decimal值格式化为字符串的OData JSON有效负载必须在Content-Type标头中返回的媒体类型中指定此格式参数。

因此,对于有效载荷:

@"{ 
    ""Lineofbusiness"": ""ba129c95-c5bb-4e40-993e-c28ca86fffe4"",
    ""AssignedNbr"": ""1000000045""
  }";

你应该设置:

request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json;IEEE754Compatible=true");

否则,你不应该。

答案 1 :(得分:3)

Sam Xu完全正确,应该标记为答案。

但是,我想准确添加您需要做的事情,以便将其添加到管道中。

首先,您可以设置此全局,每条路线等。您可以在此处找到该信息: http://www.asp.net/web-api/overview/advanced/http-message-handlers

下面你会找到一个可行的例子。

public static void Configuration(IAppBuilder builder)
    {
        HttpConfiguration config = new HttpConfiguration();       

        config.MessageHandlers.Add(new MethodOverrideHandler());
    }

public class MethodOverrideHandler : DelegatingHandler
{       
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json;IEEE754Compatible=true");

        return base.SendAsync(request, cancellationToken);
    }
}

或者,尝试将您发送到网络API的类型更改为数字而不是字符串

另外,请检查要发送的小数类型。如果它的类型&#39;字符串&#39;您可以将其更改为类型编号。对于我的服务,进行此更改不再引发错误。

//Gnuget Package Manager Install-Package numeral  

if (typeof newValue === 'string') 
{
newValue = numeral().unformat(newValue);
}

  odatajs.oData.request(
             {
                 requestUri: xxx,
                 method: "PATCH",
                 data: { PriceNull: newValue }
             }