【问题标题】:How to create a method in WCF RESTful service in the given scenario?如何在给定场景中在 WCF RESTful 服务中创建方法?
【发布时间】:2015-10-21 16:16:10
【问题描述】:

我必须创建一个 PUT RESTful WCF 服务,它的 URI 模板类似于:

/rs/close_copy/{user_token}?term={term}&brand={brandname}

向我们发送的请求具有这种格式的 JSON 正文:

“acc”: 
“counters”:[ 
{“format”: 
“ink”: 
“ctr”:
“duplex”: },
{…}]

但问题是,上面的"counters" 参数并不总是像预期的那样以 JSON 对象数组的形式出现。当"counter" 中只有一个元素时,请求以单个 JSON 对象的形式出现,而不是作为具有一个元素的 JSON 对象列表。

调用我们服务的是第三方,他们无法更改他们的请求。我在 WCF 中实现了如下内容:

[WebInvoke(Method = "PUT", ResponseFormat = WebMessageFormat.Json,
           RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare,
           UriTemplate = "/rs/close_copy/{user_token}?term={term}&brand={brandname}")]
JsonResponse EndSession(string user_token, string term, string brandname, EndSessionRequest request);

EndSessionRequest 在哪里:

[DataContract]
public class EndSessionRequest
{
    [DataMember]
    public string acc { get; set; }        

    [DataMember]
    public IEnumerable<PageDetails> counters { get; set; }
}

PageDetails 是:

[DataContract]
public class PageDetails
{
    [DataMember]
    public string format { get; set; }
    [DataMember]
    public string ink { get; set; }
    [DataMember]
    public int ctr { get; set; }
    [DataMember]
    public bool duplex { get; set; }
}

上述实现的问题是,当counters 有一个元素时,向我们提出请求:

{"acc":"ramaccnz","counters":{"ctr":"2","duplex":"false","format":"A4","ink":"bw"}}

但根据我们的实现,请求应为:

{"acc":"ramaccnz","counters":[{"ctr":"2","duplex":"false","format":"A4","ink":"bw"}]} 

在其他情况下,当请求包含多个元素时,我们的服务会按预期工作。

有没有办法在 WCF 实现中处理这个问题?

【问题讨论】:

  • 您的代码是正确的,问题是第三方客户端没有正确调用您的服务,尊重您的服务合同。

标签: c# wcf rest wcf-rest


【解决方案1】:

好的。这有点棘手。我目前也在开发 RESTful 服务。有一种叫做CollectionDataContract 的东西可能是实现您的目标的一种方法,但我是 WCF 的新手,所以我不能告诉您更多信息。 另一种方法是获取您请求的原始数据流,因此您必须使用JavaScriptSerializer 自己获取和反序列化 JSON 数据。在这种情况下,您可以自己处理传入的数据。喜欢..

 public JsonResponse ServiceCall(Stream dataStream, object parameter) {
     var dataBytes = dataStream.ReadToEnd();
     // use the required encoding to get the string data
     var dataString = Encoding.UTF8.GetString(dataBytes);
     var dataJson = default(EndSessionRequest);
     try { dataJson = new JavaScriptSerializer().Deserialize<EndSessionRequest>(); }
     catch {  
         // the request includes just one entry that's why
         // the serializer fails getting the object so
         // you could continue like..
         dataJson = new JavaScriptSerializer().Deserialize<EndSessionRequestWithSingleCounter>();
     }
     // handle request ...
 }

要在请求调用方法中使用原始流,只需删除参数类型规范 EndSessionRequest 并插入 Stream。你是 Web.config 在这种情况下也需要一些更改..

 <!-- insert into system.web tag -->
 <system.web>
     <httpRuntime targetFramework="4.5" maxRequestLength="2000000" />
     <!-- other stuff.. -->
 </system.web>
 <!-- insert into system.serviceModel > bindings -->
 <system.serviceModel>
     <bindings>
         <webHttpBinding>
             <binding 
                 name="YourBindingName"
                 maxBufferSize="65536"
                 maxreceiveMessageSize="2000000000"
                 transferMode="Streamed" />
         </webHttpBinding>
     </bindings>
 </system.serviceModel>

并且不要忘记将 bindingConfiguration="YourBindingName" 设置为您的服务行为。

但正如 @Ricardo Pontual 已经提到的那样。是第三方以错误的方式调用您的服务..

【讨论】:

  • 我同意@Jan Unld,获取原始数据流。然后,您可以获取原始 json 字符串作为计数器的参数。使用 newtonsoft 反序列化,然后分析您拥有的数组或字典对象。这是一个很大的痛苦,但我已经做到了,如果你愿意,可以发布更多代码。
【解决方案2】:

我可以通过使用OperationContext 获取JSON 格式的请求字符串,然后使用DataContractJsonSerializer 手动处理请求来做到这一点。下面是我的代码sn-p:

[DataContract]
public class EndSessionRequestMany
{
    [DataMember]
    public string acc { get; set; }
    [DataMember]
    public List<PageDetails> counters { get; set; }
}

public JsonResponse EndSession(string user_token, string term, string brandname)
{
    string JSONstring = OperationContext.Current.RequestContext.RequestMessage.ToString();

    XmlReader reader = XmlReader.Create(new StringReader(JSONstring));
    EndSessionRequestMany objEndSessionMany = (EndSessionRequestMany)new DataContractJsonSerializer(typeof(EndSessionRequestMany)).ReadObject(reader);
}

【讨论】:

    猜你喜欢
    • 2010-12-25
    • 2016-03-17
    • 1970-01-01
    • 2011-08-12
    • 2017-11-21
    • 2011-02-12
    • 2017-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多