2009-11-12 13 views
9

RESTful WCFサービスを使用してHttpContext.Currentにアクセスする必要があります。私は、設定に以下を追加することによって、これを達成することができています知っている:設定方法ServiceHostingEnvironment.AspNetCompatibilityEnabled = true(コードでは設定されていません).NET/C#

<serviceHostingEnvironment aspNetCompatibilityEnabled=”true” /> 

と私のサービス上で以下の属性を使用して:ここで

[AspNetCompatibilityRequirements(RequirementsMode 
    = AspNetCompatibilityRequirementsMode.Required)] 

は私の問題であり、私が「スピンアップ」する必要がありますユニットテストのためのコードでサービスのインスタンスとなるため、サービスファイルを指定するために設定ファイルを使用することはできません。 私のコードは次のようになりますが、ウェブを精査しても、 ServiceHostingEnvironmentクラスを設定し、configを使用せずにAspNetCompatibilityEnabledプロパティをtrueに設定します。

string serviceUrl = "http://localhost:8082/MyService.svc"; 

_host = new ServiceHost(typeof(MyService), new Uri[] { new Uri(serviceUrl) }); 

ServiceEndpoint serviceEndpoint 
    = _host.AddServiceEndpoint(typeof(IMyService), new WebHttpBinding(), string.Empty); 

serviceEndpoint.Behaviors.Add(new WebHttpBehavior()); 

// Here's where I'm stuck, i need something like... 
ServiceHostingEnvironmentSection shes = new ServiceHostingEnvironmentSection(); 
shes.AspNetCompatibilityEnabled = true; 
_host.Add(shes); 

_host.Open(); 

ご協力いただきありがとうございます。

答えて

-2

:-(設定を通してのように見えますあなたが単体テスト中にスタブアウトすることができるインターフェース。

HttpContext.Currentは、あなたのwcfサービスがasp.net Webアプリケーション内でホストされている場合にのみ定義されています - いつか通常のwcfサービスとしてホストする必要がある場合は、HttpContext現在は利用できません。

+5

これは、彼の質問の95%ほどであったAspNetCompatibilityEnabledを設定する方法にも触れません。 –

0

は、それはあなたがSystem.ServiceModelに静的 ServiceHostingEnvironmentクラスで設定できるのAppDomain全体の設定です:

ServiceHostingEnvironment.AspNetCompatibilityEnabled = true; 

あなたがサービスホストを作成し、開く前にこれを実行する必要があります。

は素敵だったでしょう - しかし、それは読み取り専用の設定だし、それを設定する唯一の方法は、背後HttpContext.Currentを明示的に使用して因数分解を検討

+0

残念なことに、このプロパティにはセッターがありません。 –

+0

これには対応策がありますか?この特別な場合を除いて、WCFをプログラムでほぼ完全に構成できることは驚くべきことです。私はこれをWCFのバグと呼びます。あなたのサービスに少なくともあなたのためにそれをするように指示する方法はありますか? –

+0

@marc_s:あなたはサービスファクトリを設定するだけです(私の答えを参照してください)。ただし、これはサイト全体ではなく、サービス全体のものです。 –

4

あなたはこれを完全に行うことができますが、私はこれらの他の答えについてはわかりませんが、彼らは離れています!これは、それが存在する場合、既存の動作を削除し、その後、お好みのモードを持つ新しい振る舞いを追加 を編集 -

_host = new ServiceHost(...); 
// Remove existing behavior as it is readOnly 
for (int i = 0; i < _host.Description.Behaviors.Count; i++) 
{ 
    if (_host.Description.Behaviors[i] is AspNetCompatibilityRequirementsAttribute) 
    { 
     _host.Description.Behaviors.RemoveAt(i); 
     break; 
    } 
} 
// Replace behavior with one that is configured the way you desire. 
_host.Description.Behaviors.Add(new AspNetCompatibilityRequirementsAttribute { RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed }); 
_host.Open(); 

は、同じように何かをします。私の例ではそれを.Allowedに設定していますが、もちろんあなたが望むモードに設定することができます。オースティン・ハリスの答えについては詳しく説明し

+0

これは、サービス自体がホストではなく、aspnetとの互換性を必要とする場合に設定します。どのようにそれは本当の 'AspNetCompatibilityEnabled'プロパティを設定します –

+0

? – drowa

0

:あなたはのServiceHostの動作を変更する必要が


属性は読み取り専用なので、ServiceHostに動作を削除し、readdする必要があります。
コンソールアプリケーションまたはWindowsサービスをお持ちの場合は、このサービスホストを定義します。このような

何か:(彼は可代わりに必要な書かれていなかった場合は...)オースティンハリスのコードは十分であろう

public static void Main() 
{ 
    using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService))) 
    { 
    try 
    { 
     // Open the ServiceHost to start listening for messages. 
     serviceHost.Open(); 

     // The service can now be accessed. 
     Console.WriteLine("The service is ready."); 
     Console.WriteLine("Press <ENTER> to terminate service."); 
     Console.ReadLine(); 

     // Close the ServiceHost. 
     serviceHost.Close(); 
    } 
    catch (TimeoutException timeProblem) 
    { 
     Console.WriteLine(timeProblem.Message); 
     Console.ReadLine(); 
    } 
    catch (CommunicationException commProblem) 
    { 
     Console.WriteLine(commProblem.Message); 
     Console.ReadLine(); 
    } 
    } 
} 

その場合には。

あなたはWCF-サービスは、ASP.NETアプリケーションに統合している場合は、トリッキーな部分はのServiceHostを取得することです。

キーはYOUR_SERVICE.svcマークアップファイル内の工場出荷時の属性です。

<%@ ServiceHost Factory="ApertureImportBelegung.DerivedFactory" Language="VB" Debug="true" Service="ApertureImportBelegung.ImportBelegung" CodeBehind="Service1.svc.vb" %> 

あなた自身の工場を書く必要があります。
以下のコードはVB.NETで、私はC#に翻訳するために、読者にそれを残しておきます(あなたが道でtrueにWITH_FORMS_AUTHENTICATIONを設定する必要があり、およびC#のPSます:http://converter.telerik.com

'Imports System.ServiceModel 
Imports System.ServiceModel.Description 
'Imports System.ServiceModel.Dispatcher 
'Imports System.ServiceModel.Channels 

'Imports System.ServiceModel.Configuration 
Imports System.ServiceModel.Activation ' Add reference to assembly System.ServiceModel.Activation.dll 



Public Class DerivedHost 
    Inherits ServiceHost 


    Public Sub New(t As Type, ParamArray baseAddresses() As Uri) 
     MyBase.New(t, baseAddresses) 
    End Sub 


    Protected Overrides Sub OnOpening() 
     'Me.Description.Behaviors.Add(New mys) 
     'Me.Description.Add(New MyServiceBehavior()) 

     'Me.Description.Behaviors.Add(New WcfMessageLoggerExtension()) 
     MyBase.OnOpening() 
    End Sub 


End Class ' DerivedHost 



' http://msdn.microsoft.com/en-us/library/aa702697(v=vs.110).aspx 
Public Class DerivedFactory 
    Inherits ServiceHostFactory 


    Protected Overrides Function CreateServiceHost(t As Type, baseAddresses As Uri()) As ServiceHost 
     Return New DerivedHost(t, baseAddresses) 
    End Function ' CreateServiceHost 


    'Then in the CreateServiceHost method, we can do all of the 
    'things that we can do in a self-hosted case: 
    Public Overrides Function CreateServiceHost(service As String, baseAddresses As Uri()) As ServiceHostBase 
     Application.ConfigData.ReadConfigData() 

     ' The service parameter is ignored here because we know our service. 
     Dim serviceHost As New ServiceHost(GetType(ImportBelegung), baseAddresses) 
     ' System.ServiceModel.ServiceHostingEnvironment.AspNetCompatibilityEnabled = True 

     ' http://stackoverflow.com/questions/13597408/wcf-message-inspector-is-not-working 
     'Dim serviceHost As New System.ServiceModel.ServiceHost(GetType(ImportBelegung)) 
     'serviceHost.Description.Behaviors.Add(New WcfMessageLoggerExtension()) 


     ' http://stackoverflow.com/questions/5907791/how-to-programatically-create-a-wcf-service-and-its-metadata-on-the-same-url 
     ' http://msdn.microsoft.com/en-us/library/system.servicemodel.servicehost(v=vs.110).aspx 


     ' host.Open() 
     'This example iterates through all the ServiceEndpoint objects and adds ConsoleMessageTracing as an endpoint behavior: 
     For Each endpoint As ServiceEndpoint In serviceHost.Description.Endpoints 
      'endpoint.Behaviors.Add(New WcfMessageLoggerExtension()) 
      'endpoint.Behaviors.Add(New ConsoleOutputBehaviorExtensionElement) 

      endpoint.Behaviors.Add(New MessageInspector.ConsoleOutputBehavior) 
      endpoint.Behaviors.Add(New HeaderInspector.ConsoleOutputHeaderBehavior) 
     Next endpoint 


     ' Ensure (in <system.serviceModel>) aspNetCompatibilityEnabled="true" --> <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" /> 
#Const WITH_FORMS_AUTHENTICATION = False 

#If WITH_FORMS_AUTHENTICATION Then 

     For i As Integer = 0 To serviceHost.Description.Behaviors.Count - 1 Step 1 
      If TypeOf serviceHost.Description.Behaviors(i) Is AspNetCompatibilityRequirementsAttribute Then 
       serviceHost.Description.Behaviors.RemoveAt(i) 
       Exit For 
      End If 
     Next i 

     serviceHost.Description.Behaviors.Add(New AspNetCompatibilityRequirementsAttribute() With {.RequirementsMode = AspNetCompatibilityRequirementsMode.Required}) 

#End If 



     Return serviceHost 
    End Function ' CreateServiceHost 


End Class ' DerivedFactory 
0

リフレクターの周り掘り後、私は、リフレクションを使用してAspNetCompatibilityEnabledフラグを設定することができました。このアプローチには明白な欠点がありますが、それは私の仕事でした:

 // get the ServiceHostingEnvironmentSection by calling an internal static method 
     var section = (ServiceHostingEnvironmentSection)typeof(ServiceHostingEnvironmentSection).GetMethod("UnsafeGetSection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static).Invoke(null, null); 
     // set the read-only flag to false so values can be updated 
     typeof(ServiceHostingEnvironmentSection).BaseType.BaseType.GetField("_bReadOnly", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(section, false); 
     // set the AspNetCompatibilityEnabled value 
     section.AspNetCompatibilityEnabled = true; 

     // now one can add a Service Route 
     routes.Add(new ServiceRoute("MyRoutePrefix", new ServiceHostFactory(), typeof(MyService))); 
関連する問題