如何在给定场景中的 WCF RESTful 服务中创建方法?
How to create a method in WCF RESTful service in the given scenario?
我必须创建一个 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 实现中处理这个问题?
好的。这有点棘手。我目前也在开发 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 已经提到的那样。是第三方错误地调用了你的服务..
我能够通过使用 OperationContext
获取 JSON 格式的请求字符串,然后使用 DataContractJsonSerializer
手动处理请求来做到这一点。下面是我的代码片段:
[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);
}
我必须创建一个 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 实现中处理这个问题?
好的。这有点棘手。我目前也在开发 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 已经提到的那样。是第三方错误地调用了你的服务..
我能够通过使用 OperationContext
获取 JSON 格式的请求字符串,然后使用 DataContractJsonSerializer
手动处理请求来做到这一点。下面是我的代码片段:
[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);
}