Сводка
У меня есть внутренняя служба WCF, работающая в службе приложений Azure, и я разрабатываю прокси-сервер, который будет использовать тот же интерфейс, но манипулировать некоторыми сообщениями для совместимости с системой клиента.Я знаю, что это немного расплывчато, но детали не важны.
Проблема в том, что когда прокси-сервер, работающий в IIS Express из Visual Studio 17, вызывает бэкэнд, он делает это неправильно, иБэкэнд отклоняет запрос.(Любопытно, что точный характер отклонения отличается между реальным сервисом и минимальным воспроизводимым контрольным примером, который я создал для этого поста, но разница достаточно поздняя, и я не считаю, что это актуально).
Добавив прослушиватели трассировки в System.Net
, я могу заметить, что вызов, сделанный прокси-сервером для внутреннего интерфейса, имеет тело в JSON, но заголовки, утверждающие, что это XML:
System.Net Verbose: 0 : [4140] Data from ConnectStream#29742526::Write
System.Net Verbose: 0 : [4140] 00000000 : 7B 22 42 61 72 22 3A 22-42 2D 50 72 6F 78 69 65 : {"Bar":"B-Proxie
System.Net Verbose: 0 : [4140] 00000010 : 64 22 2C 22 46 6F 6F 22-3A 22 41 22 7D : d","Foo":"A"}
System.Net Verbose: 0 : [4140] Exiting ConnectStream#29742526::Write()
System.Net Verbose: 0 : [4140] Entering ConnectStream#29742526::Close()
System.Net Verbose: 0 : [4140] Exiting ConnectStream#29742526::Close()
System.Net Verbose: 0 : [4140] Entering HttpWebRequest#45658036::GetResponse()
System.Net Information: 0 : [4140] HttpWebRequest#45658036 - Request: POST /DemoService.svc/DoTheThing HTTP/1.1
System.Net Information: 0 : [4140] ConnectStream#29742526 - Sending headers
{
Content-Type: application/xml; charset=utf-8
Host: wcfproxydemo.azurewebsites.net
Content-Length: 29
Expect: 100-continue
Accept-Encoding: gzip, deflate
Connection: Close
}.
Могу ли я изменитькакая-то конфигурация, чтобы заставить его отправлять JSON с правильным заголовком Content-Type? Я бы предпочел не переключать все на XML.
Подробности
Мой минимальный воспроизводимый тестчехол доступен на Github .Единственное, что я выбрал, - это профиль публикации, чтобы перенести бэкэнд в Azure.
Различные проекты имеют общий интерфейс, и нет автоматически сгенерированной ссылки на службу.(Это может быть возможным способом продвижения вперед, но он кажется довольно тяжелым, поэтому я бы предпочел решение на основе конфигурации).Конфигурация WCF для трех компонентов:
Backend
<system.serviceModel>
<bindings>
<customBinding>
<binding name="rest-https-nokeepalive">
<webMessageEncoding />
<httpsTransport manualAddressing="true" allowCookies="false" keepAliveEnabled="false" maxBufferSize="10000000" maxReceivedMessageSize="10000000" maxBufferPoolSize="10000000" />
</binding>
</customBinding>
</bindings>
<services>
<service name="Backend.DemoService" behaviorConfiguration="ServiceBehaviour">
<endpoint binding="customBinding" bindingConfiguration="rest-https-nokeepalive" contract="Interface.IDemoService" behaviorConfiguration="web" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Proxy
<system.serviceModel>
<bindings>
<customBinding>
<binding name="rest-https-nokeepalive">
<webMessageEncoding />
<httpsTransport manualAddressing="true" allowCookies="false" keepAliveEnabled="false" maxBufferSize="10000000" maxReceivedMessageSize="10000000" maxBufferPoolSize="10000000" />
</binding>
</customBinding>
</bindings>
<services>
<service name="Proxy.DemoService" behaviorConfiguration="ServiceBehaviour">
<endpoint binding="customBinding" bindingConfiguration="rest-https-nokeepalive" contract="Interface.IDemoService" behaviorConfiguration="web" />
</service>
</services>
<client>
<endpoint name="Backend" address="https://wcfproxydemo.azurewebsites.net/DemoService.svc" binding="customBinding" bindingConfiguration="rest-https-nokeepalive" contract="Interface.IDemoService" behaviorConfiguration="web" />
</client>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" maxMessagesToLog="3000" maxSizeOfMessageToLog="2000" />
</diagnostics>
</system.serviceModel>
Тестовый интерфейс
<system.serviceModel>
<bindings>
<customBinding>
<binding name="rest-https-nokeepalive">
<webMessageEncoding />
<httpsTransport manualAddressing="true" allowCookies="false" keepAliveEnabled="false" maxBufferSize="10000000" maxReceivedMessageSize="10000000" maxBufferPoolSize="10000000" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint name="Direct" address="https://wcfproxydemo.azurewebsites.net/DemoService.svc" binding="customBinding" bindingConfiguration="rest-https-nokeepalive" contract="Interface.IDemoService" behaviorConfiguration="web" />
<endpoint name="Proxied" address="https://localhost:44388/DemoService.svc" binding="customBinding" bindingConfiguration="rest-https-nokeepalive" contract="Interface.IDemoService" behaviorConfiguration="web" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" maxMessagesToLog="3000" maxSizeOfMessageToLog="2000"/>
</diagnostics>
</system.serviceModel>
Прямое подключение отинтерфейс к бэкэнду работает нормально.Прокси-соединение не удается, потому что сервер не удовлетворен запросом, который он получает от прокси-сервера, по очевидным причинам.