我在WCF服务中作为参数使用复杂
JSON作为参数.
在Visual Studio 2008 SP1中使用Microsoft.Net 3.5 SP1
通过以下合同:
[ServiceContract] public interface IService1 { [OperationContract] [WebGet(UriTemplate="GetDataUsingDataContract?composite={composite}",BodyStyle=WebMessageBodyStyle.Wrapped,RequestFormat=WebMessageFormat.Json,ResponseFormat = WebMessageFormat.Json)] CompositeType GetDataUsingDataContract(CompositeType composite); // TODO: Add your service operations here } // Use a data contract as illustrated in the sample below to add composite types to service operations [DataContract] public class CompositeType { string boolValue = "true"; string stringValue = "Hello "; [DataMember] public string BoolValue { get { return boolValue; } set { boolValue = value; } } [DataMember] public string StringValue { get { return stringValue; } set { stringValue = value; } } }
使用以下URL:
http://localhost:1122/Service1.svc/GetDataUsingDataContract?composite={"BoolValue":"True","StringValue":"Hello"}
使用Enpoint配置:
<system.serviceModel> <services> <service name="WebHTTPBindingExample.Service1" behaviorConfiguration="WebHTTPBindingExample.Service1Behavior"> <host> <baseAddresses> <add baseAddress="http://localhost:8731/Design_Time_Addresses/WebHTTPBindingExample/Service1/"/> </baseAddresses> </host> <!-- Service Endpoints --> <!-- Unless fully qualified,address is relative to base address supplied above --> <!--<endpoint address="" binding="wsHttpBinding" contract="WebHTTPBindingExample.IService1"> --><!-- Upon deployment,the following identity element should be removed or replaced to reflect the identity under which the deployed service runs. If removed,WCF will infer an appropriate identity automatically. --><!-- <identity> <dns value="localhost"/> </identity> </endpoint>--> <endpoint address="Web" behaviorConfiguration="ChatAspNetAjaxBehavior" binding="webHttpBinding" name="ajaxEndpoint" contract="WebHTTPBindingExample.IService1"/> <!-- Metadata Endpoints --> <!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. --> <!-- This endpoint does not use a secure binding and should be secured or removed before deployment --> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="WebHTTPBindingExample.Service1Behavior"> <!-- To avoid disclosing Metadata information,set the value below to false and remove the Metadata endpoint above before deployment --> <serviceMetadata httpGetEnabled="True"/> <!-- To receive exception details in faults for debugging purposes,set the value below to true. Set to false before deployment to avoid disclosing exception information --> <serviceDebug includeExceptionDetailInFaults="False"/> </behavior> </serviceBehaviors> <endpointBehaviors> <behavior name="ChatAspNetAjaxBehavior"> <webHttp/> </behavior> </endpointBehaviors> </behaviors> </system.serviceModel>
我得到以下错误:
Operation 'GetDataUsingDataContract' in contract 'IService1' has a query variable named 'composite' of type 'WebHTTPBindingExample.CompositeType',but type 'WebHTTPBindingExample.CompositeType' is not convertible by 'QueryStringConverter'. Variables for UriTemplate query values must have types that can be converted by 'QueryStringConverter'.
解决方法
我不相信你可以使用这种WCF在查询字符串上传递复杂的类型.请参阅ASP.NET论坛中的Microsoft技术的
this response – 它与您的情况相似.
根据你如何扼杀你的服务方法,看起来像一个更合适的动词是POST或PUT,你可以把你的CompositeType有效载荷放在请求体内.但我猜你的意图.
我可以通过将查询字符串类型从CompositeType更改为String,然后使用ASP.NET JavaScriptSerializer类将JSON字符串反序列化为CompositeType,从而使您的代码工作并仍然使用GET. (你可以在这里使用你最喜欢的JSON助手类 – 我偏偏到JSON.NET,但是我也听到FlexJson也是非常好的)
我没有触摸你的web.config(除了让它在我的本地测试应用程序中工作).我唯一的改变是在服务方法签名和服务方法的实现.
[ServiceContract] public interface IService1 { [OperationContract] [WebGet(UriTemplate = "GetDataUsingDataContract?composite={composite}",BodyStyle = WebMessageBodyStyle.Wrapped,RequestFormat = WebMessageFormat.Json,ResponseFormat = WebMessageFormat.Json)] CompositeType GetDataUsingDataContract(String composite); // TODO: Add your service operations here } public class Service1 : IService1 { public CompositeType GetDataUsingDataContract(String composite) { //use the JavaScriptSerializer to convert the string to a CompositeType instance JavaScriptSerializer jscript = new JavaScriptSerializer(); CompositeType newComp = jscript.Deserialize<CompositeType>(composite); newComp.StringValue += " NEW!"; return newComp; } }
我希望这有帮助.如果您有其他问题,请告诉我们.