ASP.NET v4.0 に基づいてフォーム認証で保護された、作成済みの IIS 7.5 Web サイトで、REST フル WCF 4.0 サービスをホストしたいと考えています。そのため、混合モード認証 (aspNetCompatibilityEnabled="false") を使用して WCF スタックを構成しようとし、セキュリティをまったく使用しないようにサービス ホストを構成しましたが、長い間、私の努力はすべて完全に失敗しました。しばらくしてからブラウザからサービスを呼び出そうとすると、ホストへの接続が応答なしで閉じられ、ブラウザはターゲット Webstie への接続が応答なしで閉じられたことを示すエラーを発生させます。
ただし、FormsAuthentication.Authenticate を使用してフォーム認証モジュールでダミー ユーザーを認証するために Application_BeginRequest にダミー コードを記述するか、認証済みブラウザー セッションでサービスを呼び出すと、すべて正常に機能し、サービスが正常に呼び出されます。
WCF トレースを使用して、この奇妙な動作を引き起こしている問題を見つけようとしました。結果の svclog ファイルから私が見つけたのは、次の例外です。
メッセージ:オブジェクト参照がオブジェクトのインスタンスに設定されていません。
スタックトレース:
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.get_LogonUserIdentity() System.ServiceModel.Channels.HttpChannelListener.ValidateAuthentication(IHttpAuthenticationContext authenticationContext) System.ServiceModel.Channels.HttpRequestContext.ProcessAuthentication() System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceived(HttpRequestContext)コンテキスト、アクション コールバック)
問題について何か考えはありますか?
更新: Web サイトの認証モードを「なし」に設定し、匿名ユーザーを許可しました。それでも同じ結果です。何も変わっていません。問題は、認証されていない WCF RESTfull サービスを ASP.NET Web サイトで aspNetCompatibilityEnabled="false" で使用できるかということです。
より具体的には、私がやろうとしたことは次のとおりです。
- .svc ファイルの形式で WCF サービスを実装しました
- web.config ファイルで WCF を次のように構成しました (AspNetCompatibilityEnabled="false" に注意してください)。
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="false" />
</system.serviceModel>
- 次のように、独自の ServiceHostFactory を作成して使用しました。
public class MyServiceHostFactory : ServiceHostFactoryBase
{
#region Methods
public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
{
var type = Type.GetType(constructorString);
var host = new WebServiceHost(type, baseAddresses);
var serviceBehavior = host.Description.Behaviors.OfType<ServiceBehaviorAttribute>().Single();
serviceBehavior.ConcurrencyMode = ConcurrencyMode.Multiple;
serviceBehavior.MaxItemsInObjectGraph = int.MaxValue;
var metadataBehavior = host.Description.Behaviors.OfType<ServiceMetadataBehavior>().SingleOrDefault();
if (metadataBehavior == null)
{
metadataBehavior = new ServiceMetadataBehavior();
host.Description.Behaviors.Add(metadataBehavior);
}
var debugBehavior = host.Description.Behaviors.OfType<ServiceDebugBehavior>().SingleOrDefault();
if (debugBehavior == null)
{
debugBehavior = new ServiceDebugBehavior();
host.Description.Behaviors.Add(debugBehavior);
}
metadataBehavior.HttpGetEnabled = true;
debugBehavior.IncludeExceptionDetailInFaults = true;
var binding = new WebHttpBinding { MaxBufferPoolSize = int.MaxValue, MaxReceivedMessageSize = int.MaxValue };
binding.Security.Mode = WebHttpSecurityMode.None;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
WebHttpBehavior webHttpBehavior = new WebHttpBehavior { HelpEnabled = true };
foreach (var contract in type.GetInterfaces().Where(i => i.GetCustomAttributes(typeof(ServiceContractAttribute), true).Length > 0))
{
var endpoint = host.AddServiceEndpoint(contract, binding, "");
endpoint.Behaviors.Add(webHttpBehavior);
}
host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
return host;
}
#endregion
}