WCF webHttpBinding ошибка с параметрами метода.«Максимум один параметр тела может быть сериализован без элементов оболочки» - PullRequest
31 голосов
/ 28 апреля 2011

Операция '' контракта '' указывает несколько параметры тела запроса должны быть сериализованный без какой-либо обертки элементы. Максимум один параметр тела можно сериализовать без оболочки элементы. Либо удалить лишнее тело параметры или установить BodyStyle собственность на WebGetAttribute / WebInvokeAttribute to Облаченный.

Я пытаюсь открыть службу WCF C # 4.0 с JSON через следующую конфигурацию (устанавливается через редактор конфигурации WCF):

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <services>
      <service name="iPhoneAPI.API">
        <endpoint address="" behaviorConfiguration="NewBehavior0" binding="webHttpBinding"
          bindingConfiguration="" contract="iPhoneAPI.IApi" />
      </service>
    </services>
    <protocolMapping>
      <add scheme="http" binding="webHttpBinding" bindingConfiguration="" />
    </protocolMapping>
    <behaviors>
      <endpointBehaviors>
        <behavior name="NewBehavior0">
          <webHttp defaultOutgoingResponseFormat="Json" />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>  
</configuration>

Когда я получаю доступ к /API.svc, я получаю ранее перечисленное сообщение об исключении.

Если я укажу только следующий (без параметров) контракт, сервис работает:

[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "test")]
GenericApiResult<IEnumerable<LiveFeedEntity>> test();

Если у меня есть методы, для которых требуются параметры, не являющиеся строками, я получаю ранее перечисленное исключение.

Пример:

[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "login")]
LoginApiResult Login(String UserName, String Password);

Если я изменю эту функцию следующим образом:

[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "login/{UserName}/{Password}")]
LoginApiResult Login(String UserName, String Password);

Работает; но это возможно только для параметров типа String. Как мне повторить это для других моих функций, таких как:

[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "logout")]
GenericApiResult<bool> Logout(Guid SessionKey);

Перепробовал много поисков в гугле, но оказался с пустыми руками, любая помощь приветствуется.

Приветствия

Ник.

Ответы [ 3 ]

38 голосов
/ 28 апреля 2011

Вы пытались установить WebInvokeAttribute.BodyStyle в Wrapped , как рекомендует ошибка?

23 голосов
/ 28 апреля 2011

Проблема в том, что ваш UriTemplate должен указывать все передаваемые значения, кроме одного.Хорошо иметь в качестве параметров сложные типы, отличные от строк, мы часто отправляем облегченные объекты json нашим службам, и они приходят просто отлично.Вот пример использования вашего последнего примера.

[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "logout")]
GenericApiResult<bool> Logout(Guid SessionKey);

Будет работать, потому что передается только один параметр, и ожидается, что он будет в теле сообщения, потому что он не передается как параметр URL, но вы можете передать только один параметр тела (параметр, передаваемый в теле сообщения, а не в URL).

Вы можете изменить свой первый метод следующим образом:

[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "login/{UserName}")]
LoginApiResult Login(String UserName, String Password);

иэто бы сработало, но пароль пришел бы в теле поста.Лучший способ в этом конкретном примере - сделать то, что вы сделали для второго примера, вот так:

[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "login/{UserName}/{Password}")]
LoginApiResult Login(String UserName, String Password);

Имеет ли это смысл?В основном все передаваемые значения должны быть представлены в виде параметра URL, кроме одного, которое может быть передано в теле сообщения.Если вам нужно передать несколько значений в теле сообщения, создайте легкий объект с несколькими нужными значениями и примите весь этот объект в теле сообщения.

6 голосов
/ 16 октября 2014

WCF не поддерживает более одного параметра с чистым телом, если вам нужно передать несколько параметров в одной операции после метода, тогда нам нужно установить BodyStyle в Wrapped.

Так что в вашемна случай, если вам придется изменить свой контракт на эксплуатацию следующим образом:

[WebInvoke(Method = "POST", UriTemplate = "evals", BodyStyle = WebMessageBodyStyle.WrappedRequest)]
[OperationContract]
void SubmitVideoPOST(Video videoArg, string userId);

Источник: Нажмите здесь

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