Сложная ошибка ввода JSON WCF (не конвертируется QueryStringConverter) - PullRequest
11 голосов
/ 09 марта 2011

У меня проблема с получением Complex JSON, работающего в качестве параметра в моей службе WCF.

Использование Microsoft.Net 3.5 SP1 в Visual Studio 2008 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>

I Получаю следующую ошибку:

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'.

Ответы [ 3 ]

12 голосов
/ 09 марта 2011

Я не верю, что вам разрешено передавать сложные типы в строке запроса, используя WCF таким образом.Посмотрите этот ответ от Microsoft на форумах ASP.NET - он похож на вашу ситуацию.

Исходя из того, как вы заглушили свой метод обслуживания, он кажется более подходящимглагол для использования будет POST или PUT, и вы можете поместить свою CompositeType полезную нагрузку в тело запроса.Но я догадываюсь о вашем намерении.

Я смог заставить ваш код работать и по-прежнему использовать GET, изменив тип строки запроса с CompositeType на String и затем десериализовав строку JSON вCompositeType с использованием класса ASP.NET JavaScriptSerializer.(Вы можете использовать свой любимый класс помощника 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;
    }

}

Надеюсь, это поможет.Дайте мне знать, если у вас есть другие вопросы с этим.

0 голосов
/ 16 сентября 2014

Просто используйте атрибут WebGet без параметров:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [WebGet]
    CompositeType GetDataUsingDataContract(CompositeType composite);
}

В файле Web.config используйте enableWebScript и webHttpBinding:

<configuration>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="jsonBehavior">
          <enableWebScript />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service name="Application.Service1">
        <endpoint address="json" behaviorConfiguration="jsonBehavior" binding="webHttpBinding" contract="Application.IService1" />
        <endpoint address="soap" binding="basicHttpBinding" contract="Application.IService1" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

Тогда вы можете назвать свой JSON REST следующим образом:

http://localhost:29075/Service1.svc/json/GetDatausingDataContract?composite={ "BoolValue": true, "StringValue":  "Akira"}

Примечание: с этой конфигурацией вы можете использовать как JSON REST, так и SOAP.

0 голосов
/ 21 марта 2012

David Hoerster - ваша ссылка с 2009 года, которая сегодня недействительна.

Если вы посмотрите следующую документацию: http://msdn.microsoft.com/en-us/library/bb412179(v=vs.90).aspx

Вы можете видеть, что для вызова

 MyOperation(int number,Person p)

вы можете сделать следующее:

http://example.com/myservice.svc/MyOperation?number=7&p={"name":"John","age":42}

Предложения Дэвидса, возможно, упрощают многое на стороне программирования, НО это противоречит всем правилам REST, которые касаются сигнатур методов, которые сами документируют.

Кроме того, убедитесь, что ваша привязка имеет вид webHttpBinding для преобразования изМЫЛО ОТДЫХАТЬ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...