Azure App ServiceのWCF SOAPがHTTPSだけ404になる原因と解決策|basicHttpsBindingとprotocolMappingで直す完全ガイド

Azure App Service 上の WCF SOAP が HTTP では動くのに HTTPS だけ 404 になる――この現象は、IIS/WCF のバインディング解決と発行後の web.config 変換が絡むと発生しやすい落とし穴です。原因の見極めと確実な修正方法を、実運用を想定して手順・検証ポイントまで詳しく解説します。

日程Fit。無料・登録不要。「いつ空いてる?」を、ひとつのリンクで。リンクを送って、○△×でかんたん日程調整。無料で日程を作る。
目次

Azure App Service に配置した WCF SOAP サービスで「HTTPS のみ 404」になる原因と解決ガイド

以下の条件で発生する「HTTPS に切り替えた瞬間だけ 404」問題について、原因の仕組み、設定例、検証手順、運用での注意点までを網羅します。この記事は ASP.NET(.NET Framework)上の WCF SOAP を前提にしていますが、IIS のハンドラ解決と WCF のプロトコル・バインディングの関係を理解することで、類似の事象にも応用できます。

発生する現象

  • https://<site>.azurewebsites.net/MySVC.svc?wsdl はブラウザで表示できる(WSDL が取得できる)。
  • しかし SOAP クライアント(または自作の HttpClient)から HTTPS でメソッド呼び出しを行うと HTTP 404 を返す。
  • 同じエンドポイントを HTTP で呼ぶと成功する。
  • ローカル IIS Express では HTTP/HTTPS ともに正常。

環境の前提

項目内容
ホスティングAzure App Service(Windows、IIS 管理)
ドメイン/証明書*.azurewebsites.net(無料証明書)
アプリ種別ASP.NET Web アプリ(WCF SOAP サービスを同居)
通信HTTP は成功、HTTPS は 404
コード属性[WebInvoke] が付いているが SOAP エンドポイントとして利用
設定配布発行後に web.config は手動変更なし(CI/CD による Transform の可能性あり)

なぜ「HTTPS だけ 404」になるのか(しくみの整理)

Azure App Service ではフロントで TLS 終端が行われ、アプリ側(IIS/WCF)には 「HTTPS スキームのリクエストとして到達」します。WCF は受け取ったスキーム(http/https)に対して、<protocolMapping>エンドポイントのバインディング設定を手がかりに、どの binding を用いるかを解決します。

ここで https スキームに対応する binding が解決できない、あるいは 構成の定義位置が不適切で無効になっていると、IIS は当該リクエストを正しくサービスへ委譲できず 404 を返すことがあります。ローカル環境では Visual Studio のテンプレートや IIS Express の既定が補ってくれるため再現しないことがあり、App Service に発行して初めて露見します。

結論:<protocolMapping> で https→basicHttpsBinding を明示する

HTTPS の要求に対して SOAP バインディングを正しく選択させるには、system.serviceModel 内で次の関連付けを追加(または正しい位置に移動)します。

&lt;system.serviceModel&gt;
  &lt;protocolMapping&gt;
    &lt;add binding="basicHttpsBinding" scheme="https" /&gt;
  &lt;/protocolMapping&gt;

  &lt;!-- 既存設定 --&gt;
  &lt;behaviors&gt;
    &lt;serviceBehaviors&gt;
      &lt;behavior name="ServiceBehavior"&gt;
        &lt;serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /&gt;
        &lt;serviceDebug includeExceptionDetailInFaults="false" /&gt;
      &lt;/behavior&gt;
    &lt;/serviceBehaviors&gt;
  &lt;/behaviors&gt;

  &lt;serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /&gt;
&lt;/system.serviceModel&gt;
  • scheme="https"basicHttpsBinding にマッピングすることで、HTTPS リクエストが正しく SOAP バインディングにルーティングされます。
  • 記述位置が重要です。<serviceHostingEnvironment> より後方やファイル末尾に置くと、環境や構成の読み込み順によっては無効化されることがあります。なるべく <system.serviceModel> 冒頭付近に記述してください。

HTTP/HTTPS のバインディングを整理する

スキーム推奨バインディング補足
httpbasicHttpBinding開発・検証用途。運用は HTTPS を推奨。
httpsbasicHttpsBindingWCF 4.5+ で追加。basicHttpBinding+Transport でも類似構成は可能だが、HTTPS では basicHttpsBinding 推奨

Kudu で発行後の web.config を必ず確認する

CI/CD(パイプラインの Transform、スロット設定、パラメータ化など)が介在すると、発行先の web.config がローカルと異なる内容になることがあります。Azure Portal の 「高度なツール(Kudu)」 から site/wwwroot/web.config を直接開き、上記の <protocolMapping> が正しく反映されているかを確認します。

確認の要点

  • <system.serviceModel> の直下付近に <protocolMapping>...basicHttpsBinding... があるか。
  • 余計な Transform により、<protocolMapping> が削除・移動されていないか。
  • ステージング/本番スロットで web.config が一致しているか。
  • <handlers><modules> の差分で .svc ハンドラが無効化されていないか。

完全な構成サンプル(HTTP/HTTPS 併用・SOAP 専用)

以下は、HTTP と HTTPS の両方を公開しつつ、運用は HTTPS 利用を前提としたサンプルです。SOAP 専用を意図しているため、REST 用の [WebInvoke] は省いています(後述の注意参照)。

&lt;configuration&gt;
  &lt;system.web&gt;
    &lt;compilation debug="false" targetFramework="4.8" /&gt;
    &lt;httpRuntime targetFramework="4.8" /&gt;
  &lt;/system.web&gt;

  &lt;system.serviceModel&gt;
    &lt;protocolMapping&gt;
      &lt;add binding="basicHttpsBinding" scheme="https" /&gt;
      &lt;add binding="basicHttpBinding" scheme="http" /&gt;
    &lt;/protocolMapping&gt;

    &lt;bindings&gt;
      &lt;basicHttpsBinding&gt;
        &lt;binding name="httpsBinding" maxReceivedMessageSize="5242880"&gt;
          &lt;readerQuotas maxDepth="32" maxStringContentLength="1048576" /&gt;
          &lt;security mode="Transport" /&gt;
        &lt;/binding&gt;
      &lt;/basicHttpsBinding&gt;
      &lt;basicHttpBinding&gt;
        &lt;binding name="httpBinding" maxReceivedMessageSize="5242880"&gt;
          &lt;security mode="None" /&gt;
        &lt;/binding&gt;
      &lt;/basicHttpBinding&gt;
    &lt;/bindings&gt;

    &lt;services&gt;
      &lt;service name="MyNamespace.MyService" behaviorConfiguration="ServiceBehavior"&gt;
        &lt;endpoint address="" binding="basicHttpsBinding" bindingConfiguration="httpsBinding" contract="MyNamespace.IMyService" /&gt;
        &lt;endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" /&gt;
        &lt;!-- http 用の mex が必要なら mexHttpBinding を追加 --&gt;
      &lt;/service&gt;
    &lt;/services&gt;

    &lt;behaviors&gt;
      &lt;serviceBehaviors&gt;
        &lt;behavior name="ServiceBehavior"&gt;
          &lt;serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /&gt;
          &lt;serviceDebug includeExceptionDetailInFaults="false" /&gt;
        &lt;/behavior&gt;
      &lt;/serviceBehaviors&gt;
    &lt;/behaviors&gt;

    &lt;serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /&gt;
  &lt;/system.serviceModel&gt;

  &lt;system.diagnostics&gt;
    &lt;sources&gt;
      &lt;source name="System.ServiceModel" switchValue="Warning,ActivityTracing"&gt;
        &lt;listeners&gt;
          &lt;add name="xml" /&gt;
        &lt;/listeners&gt;
      &lt;/source&gt;
    &lt;/sources&gt;
    &lt;sharedListeners&gt;
      &lt;add name="xml" type="System.Diagnostics.XmlWriterTraceListener" initializeData="D:\home\LogFiles\WCF.svclog" /&gt;
    &lt;/sharedListeners&gt;
    &lt;trace autoflush="true" /&gt;
  &lt;/system.diagnostics&gt;
&lt;/configuration&gt;

サービス コードの最小例

namespace MyNamespace
{
  [ServiceContract]
  public interface IMyService
  {
    [OperationContract]
    string Echo(string value);
  }

public class MyService : IMyService
{
public string Echo(string value) => $"Echo:{value}";
}
} 

検証手順(HTTP → HTTPS 切替で差分を確認)

  1. ブラウザで https://<site>.azurewebsites.net/MySVC.svc?wsdl にアクセスして WSDL 表示を確認。
  2. SOAP クライアント(SoapUI など)で HTTP 呼び出しを試し、成功を確認。
  3. HTTPS に切り替えて同じメソッドを呼び出し、404 が再現するか確認。
  4. <protocolMapping> を追加/修正して再発行。
  5. Kudu で発行後の web.config に反映されているか確認。
  6. 再度 HTTPS で呼び出し、200 応答と SOAP ボディを確認。

PowerShell での最小呼び出し例

簡易確認用に、HTTP/HTTPS へ SOAP エンベロープを投げる例を載せます。

$uri = "https://&lt;site&gt;.azurewebsites.net/MySVC.svc"
$envelope = @"
&lt;s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"&gt;
  &lt;s:Body&gt;
    &lt;Echo xmlns="http://tempuri.org/"&gt;
      &lt;value&gt;hello&lt;/value&gt;
    &lt;/Echo&gt;
  &lt;/s:Body&gt;
&lt;/s:Envelope&gt;
"@
Invoke-WebRequest -Uri $uri -Method Post -ContentType "text/xml; charset=utf-8" `
  -Headers @{"SOAPAction"="http://tempuri.org/IMyService/Echo"} `
  -Body $envelope -UseBasicParsing

よくある落とし穴と対策

[WebInvoke] と SOAP の混在

[WebInvoke] は本来 REST(WebHttpBehavior)向けです。SOAP 専用であれば [OperationContract] のみで十分です。混在させる場合は endpointwebHttpBinding(REST)と basicHttpsBinding(SOAP)で分け、それぞれの behaviorConfiguration を明確に切り分けます。混在が中途半端だと、HTTPS だけ 404/405 になることがあります。

protocolMapping の記述位置

<protocolMapping><serviceHostingEnvironment> より後や、別の構成セクションの外に置くと無視されることがあります。必ず <system.serviceModel> の先頭付近に置いてください。

Transform による意図しない変更

Release 用の Web.Release.configxdt:Transform="Replace" を使うと、開発環境で入れていた <protocolMapping> が丸ごと削除されるケースがあります。Replace を避け、SetAttributesInsertIfMissing を使う、あるいは protocolMapping セクションを別ファイル化して configSource で参照するなど、変更範囲を限定しましょう。

ハンドラ/モジュールの無効化

<system.webServer><handlers> で .svc のハンドラが無効化されていると 404 になります。App Service では既定で有効ですが、誤って無効化していないか確認します。

トラブルシューティングの観点一覧

観点確認ポイント期待状態
プロトコル→バインディング解決<protocolMapping>https/basicHttpsBindingHTTPS リクエストが SOAP に到達
メタデータ公開serviceMetadata httpsGetEnabled="true"WSDL が HTTPS で取得可
エンドポイントcontract/binding の対応が正しいか契約とバインディングが一致
Transform発行後の web.config を Kudu で確認差分なし/意図どおり
証明書*.azurewebsites.net 利用時は追加不要独自ドメイン時のみバインド要
ログWCF Trace(svclog)、App Service 診断ログ404/500 の原因追跡が可能

WCF トレースと App Service ログで根因を特定する

再現が断続的な場合、ログを併用して差分を可視化します。

  • WCF トレース:前掲の System.ServiceModel トレースを D:\home\LogFiles\WCF.svclog に出力。Kudu からダウンロードして SvcTraceViewer で解析。
  • アプリケーション ログD:\home\LogFiles\Application に .NET の例外情報を出力(web.configsystem.diagnosticstrace を活用)。
  • HTTP ログ:App Service の「診断設定」で HTTP ログを有効化し、404 のリクエスト PATH/ヘッダを確認。

REST と SOAP を両立させる設計の例

同一アプリで REST と SOAP を併用する場合は、エンドポイントを明確に分離します。

<services>
  <service name="MyNamespace.MyService" behaviorConfiguration="ServiceBehavior">
    <!-- SOAP -->
    <endpoint address="soap" binding="basicHttpsBinding" contract="MyNamespace.IMyService" />
    <!-- REST -->
    <endpoint address="rest" binding="webHttpBinding" behaviorConfiguration="restBehavior" contract="MyNamespace.IRestApi" />
  </service>
</services>







 

これにより、/MySVC.svc/soap が SOAP、/MySVC.svc/rest が REST と明確化され、404/405 の混乱を避けられます。

CI/CD で安全に構成を反映するコツ

  • 構成の分割protocolMappingbindingsconfigSource で外部化し、環境別ファイルで管理。
  • Transform の粒度最小化Replace 乱用を避け、必要最小限の属性変更に限定。
  • ステージングで検証:スロットに発行してからスワップ。Kudu での差分チェックをパイプラインに自動化。

HTTP 404/405/500 の見分け方

コード典型原因対処
404ハンドラ未解決、エンドポイント不一致、protocolMapping 無効protocolMapping とエンドポイント定義、ハンドラ設定を点検
405メソッド(POST/GET)不一致、REST/SOAP の混在SOAP は基本 POST。REST は webHttpBinding を専用化
500シリアライザ例外、バインディング側最大値超過maxReceivedMessageSizereaderQuotas を調整

独自ドメインやクライアント証明書を使う場合の補足

  • 独自ドメイン:App Service の TLS/証明書バインドを行えば、構成は同じく basicHttpsBinding で動作します。
  • クライアント証明書(mTLS):App Service でクライアント証明書を受け取り、WCF 側では Transport セキュリティと clientCredentialType="Certificate" を設定します(本記事の 404 問題とは別レイヤー)。

チェックリスト(最短で直す)

  • <system.serviceModel> 直下に <protocolMapping><add scheme="https" binding="basicHttpsBinding"/></protocolMapping> を追加。
  • serviceMetadatahttpsGetEnabled="true" を確認。
  • エンドポイントの binding="basicHttpsBinding"contract 名の一致を確認。
  • Kudu で発行先 web.config を確認(Transform による改変の有無)。
  • 必要に応じて WCF トレースと HTTP ログを有効化。

FAQ

WSDL は HTTPS で表示できるのに、呼び出しだけ 404 になるのはなぜ?

WSDL の配信は メタデータ公開 の設定(serviceMetadata)が担います。一方、実処理の呼び出しは エンドポイント+バインディング の解決が必要です。後者が HTTPS で正しく解決できないと 404 になります。

basicHttpBindingsecurity mode="Transport" を設定すれば十分では?

動作は可能です。ただし近年は basicHttpsBinding がシンプルで確実です。protocolMapping で https→basicHttpsBinding を明示しておくと、構成の見通しと保守性が上がります。

App Service のフロントで TLS 終端されるなら、アプリ側は HTTP と見なされる?

App Service はアプリに対し HTTPS スキームとしてリクエストを渡します(X-Forwarded-Proto: https 等)。よって WCF では https スキームとしてのバインディング解決が必要になります。

ローカルでは再現しないのに本番だけ 404 です

多くは Transform や配置順の差異が原因です。発行後の web.config を Kudu で直接確認し、差分を潰してください。

まとめ

Azure App Service で WCF SOAP を HTTPS で公開する際の 404 は、ほとんどが https スキームと SOAP バインディングの関連付け不足構成の無効化(配置位置の問題や Transform)によって起きます。<protocolMapping> による https → basicHttpsBinding の明示、Kudu での発行後チェック、ログによる根因追跡の三点を徹底すれば、安定して HTTPS でも 200 応答を返せるはずです。既存システムの延命のみならず、運用の見える化・再現性を高める観点でも有効です。

実装テンプレート(貼り付け用)

<system.serviceModel>
  <protocolMapping>
    <add scheme="https" binding="basicHttpsBinding" />
    <add scheme="http" binding="basicHttpBinding" />
  </protocolMapping>


























 

適用後の確認ポイント(再掲)

確認期待する結果
WSDL の取得(HTTPS)WSDL が表示できる
SOAP 呼び出し(HTTPS)200 と有効な SOAP 応答
Kudu で web.config<protocolMapping> が所定位置にある
ログsvclog と HTTP ログに異常がない

これで直った(事例の要約)

実際に、<protocolMapping> の追加(または正しい位置への移動)を行い、Kudu でデプロイ先 web.config を確認したところ、HTTPS での呼び出しも正常応答となり 404 は解消されました。HTTP と HTTPS の双方で一貫したエンドポイント設計と構成管理が、再発防止の鍵です。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次