Arhn - архитектура программирования

Метод WCF POST получает ошибку 400 Плохой запрос

Я использую метод WCF POST, как только я добавил параметр POST в службу, он возвращает ошибку 400 Bad Request, если я оставил параметр пустым, он может получить доступ к моей службе.

Это мой интерфейс:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Web;
using System.IO;
namespace SampleArticle
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IRestService" in both code and config file together.
    [ServiceContract(Namespace="IRestService/JSONData")]
    public interface IRestService
    {

        [OperationContract]
        [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,UriTemplate = "authorize")]
        Stream authorize(Stream streamdata);

    }
}

Это мой Web.config

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

  <appSettings>

    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />

  </system.web>

  <system.serviceModel>


    <services>
      <service name="SampleArticle.RestService" behaviorConfiguration="serviceBehavior">
        <endpoint address="" binding="webHttpBinding" contract="SampleArticle.IRestService" behaviorConfiguration="web"></endpoint>        
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>

        <behavior name="serviceBehavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>

      </serviceBehaviors>

      <endpointBehaviors>
        <behavior name="web">
          <webHttp />
        </behavior>
      </endpointBehaviors>

    </behaviors>

    <protocolMapping>
      <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>


    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>


 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
   <directoryBrowse enabled="true" />

  </system.webServer>

</configuration>

Я использую Msxml2.ServerXMLHTTP для POST

Dim objXmlHttpMain , URL

URL="http://localhost/SampleArticle/RestService.svc/authorize" 

strJSONToSend = "{""acctId"": ""Test10001"","
strJSONToSend = strJSONToSend & """language"": 200,"
strJSONToSend = strJSONToSend & """Code"": ""Test"","
strJSONToSend = strJSONToSend & """token"": ""abcd123412341234"","
strJSONToSend = strJSONToSend & """serialNo"": ""20161020160455982841""}"

// if i set the parameter to empty i can access to the service
'strJSONToSend  = ""
Set objXmlHttpMain = CreateObject("Msxml2.ServerXMLHTTP") 
'on error resume next 
objXmlHttpMain.open "POST",URL, False 

// if i change the  "application/json" to "application/x-www-form-urlencoded" it works 
'objXmlHttpMain.setRequestHeader "Content-Type", "application/json"
objXmlHttpMain.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"

objXmlHttpMain.send strJSONToSend 


//check for output
S = objXmlHttpMain.responseText
response.write S

set objJSONDoc = nothing 
set objResult = nothing

Сообщение журнала сервера

Входящее сообщение для операции «авторизация» (контракт «IRestService» с пространством имен «IRestService / JSONData») содержит нераспознанное значение формата тела http «Json». Ожидаемое значение формата тела - «Raw». Это может быть связано с тем, что для привязки не настроен WebContentTypeMapper. Дополнительную информацию см. В документации WebContentTypeMapper.

если я изменю Content-Type «application / json» на «application / x-www-form-urlencoded», он будет работать, но мне нужны данные в формате JSON. Есть ли какая-то настройка, с которой мне не хватает? Пожалуйста посоветуй.

23.10.2016

  • Вы, наверное, делаете плохой запрос :) - вам действительно стоит показать, как вы звоните в службу. См. минимальный воспроизводимый пример для руководства по размещению кода. 23.10.2016
  • Вы уверены, что у strJSONToSend правильный формат JSON? 23.10.2016
  • я так думаю ... есть предложения? 24.10.2016
  • Да, ваш JSON правильный: {"acctId": "Test10001","language": 200, "Code": "Test", "token": "abcd123412341234","serialNo": "20161020160455982841" }? 24.10.2016
  • измените тип возвращаемого значения authorize и снова протестируйте его только для проверки. 24.10.2016
  • @ Ария, извини, что ты имеешь в виду под изменением типа авторизации? 24.10.2016
  • Добро пожаловать, ваш authorize метод вернет Stream данные, измените ваш метод так, чтобы он возвращал строковые данные вместо Stream, и протестируйте его. 24.10.2016
  • @Aria Я попробовал ваше предложение, он все еще не может получить доступ к моей службе. Если я оставил свой strJSONToSend пустым, он может получить доступ, означает ли это что-то не так с моими данными JSON? но с той же кодировкой я могу получить доступ к своей веб-службе для клиентов. Понятия не имею, нужно ли делать какие-либо настройки в Web.config или ват ... 25.10.2016
  • хорошо, я думаю, вам нужно отправить strJSONToSend как поток, а не строку JSON, или изменить BodyStyle на WebMessageBodyStyle.Bare, попробуйте это и дайте мне знать, каков результат. 25.10.2016
  • @Aria, я попробовал сменить BodyStyle на WebMessageBodyStyle.Bare, но все равно не повезло. Возможная проблема с Web.config? 25.10.2016
  • Вы передали свой JSON как поток, если это не решение, нужно изменить дизайн web.config. 25.10.2016
  • @Aria спасибо за столько терпения, я тоже новичок в C #, как изменить JSON как поток? И я подумываю переделать web.config, но код, который я опубликовал, уже был простым. Понятия не имею, правда ... 25.10.2016
  • Вы wlc, не волнуйтесь, это будет окончательно решено, чтобы сделать Stream из вашей строки JSON с помощью C # var jsonStream= new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(strJSONToSend )); 25.10.2016
  • @Aria, я обновил журнал сервера, есть идеи по этому поводу? 25.10.2016
  • Удалите пространство имен из вашего DataContract, например [DataContract(Namespace="")] 25.10.2016
  • @Aria такая же ошибка. Это что-то связано с WebContentTypeMapper? Потому что об этом упоминается в журнале сервера. 25.10.2016
  • да, нужно принудительно возвращать Raw всегда следует использовать пользовательский WebContentTypeMapper взгляните на здесь 25.10.2016
  • @Aria, можно ли установить что-то подобное в Web.config? 25.10.2016
  • Поскольку вы устанавливаете BodyStyle на Wrapped, ваши данные JSON должны быть примерно такими, как { "streamdata": { "acctid": "123"} };, но для WebContentTypeMapper вы должны настроить их и немного изменить конфигурацию. 25.10.2016
  • @ H.Kai. Вы решили проблему? 26.10.2016
  • @Aria Да, я уже решил это, добавив пользовательский WebContentTypeMapper, большое вам спасибо! 27.10.2016

Ответы:


1

Я решил свой вопрос, добавив пользовательский WebContentTypeMapper. Вот мой пример кодировки:

Создайте новый класс, чтобы разрешить получение данных в формате RAW

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace SampleArticle
{
    public class MyWebContentTypeMapper : WebContentTypeMapper
    {
        public override WebContentFormat GetMessageFormatForContentType(string contentType)
        {

            return WebContentFormat.Raw;
        }
    }
}

Web.Config добавляет настраиваемую привязку к сервису

<system.serviceModel>
    <services>
        <service name="SampleArticle.RestService" behaviorConfiguration="serviceBehavior">
            <endpoint address="" binding="customBinding" bindingConfiguration="RawReceiveCapable" contract="SampleArticle.IRestService" behaviorConfiguration="web"></endpoint>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="serviceBehavior">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
            <behavior name="">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
        <endpointBehaviors>
            <behavior name="web">
                <webHttp/>
            </behavior>
        </endpointBehaviors>
    </behaviors>


    <bindings>
        <customBinding>
            <binding name="RawReceiveCapable">
                <webMessageEncoding webContentTypeMapperType="SampleArticle.MyWebContentTypeMapper, SampleArticle, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
                <httpTransport manualAddressing="true" maxReceivedMessageSize="524288000" transferMode="Streamed"/>
            </binding>
        </customBinding>
    </bindings>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
</system.serviceModel>

Это решило мою проблему, надеюсь, это поможет и другим. Спасибо за помощь

27.10.2016
  • Хорошая работа, как вы видели, я сказал в одном из своих комментариев к вашему вопросу, что нужно всегда принудительно возвращать Raw, поэтому должен быть реализован пользовательский WebContentTypeMapper. 27.10.2016
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..