Как установить ServiceHostingEnvironment.AspNetCompatibilityEnabled = true в коде (не в конфигурации) .NET / C # - PullRequest
9 голосов
/ 12 ноября 2009

У меня есть требование для доступа к HttpContext.Current из-за RESTful службы WCF. Я знаю, что могу добиться этого, добавив в конфигурацию следующее:

<serviceHostingEnvironment aspNetCompatibilityEnabled=”true” />

и используя следующий атрибут в моем сервисе:

[AspNetCompatibilityRequirements(RequirementsMode 
    = AspNetCompatibilityRequirementsMode.Required)]

Вот моя проблема, мне нужно «раскрутить» экземпляр службы в коде для модульного тестирования, и поэтому я не могу использовать файлы конфигурации для указания поведения службы и т. Д. На данный момент мой код выглядит следующим образом, но, несмотря на просмотр веб-страниц, я не смог понять, как настроить класс ServiceHostingEnvironment и установить для свойства AspNetCompatibilityEnabled значение true, не используя config, может кто-нибудь помочь?

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();

Любая помощь высоко ценится и заранее спасибо.

Ответы [ 5 ]

4 голосов
/ 11 декабря 2013

Вы можете сделать это полностью, я не знаю, о чем эти другие ответы, но они еще далеко!

Просто сделайте что-то вроде:

_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 голосов
/ 06 сентября 2017

После копания в Reflector я смог установить флаг 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)));
0 голосов
/ 08 октября 2014

Чтобы прояснить ответ Остина Харриса:

Вам необходимо изменить поведение ServiceHost.
Поскольку атрибут доступен только для чтения, вам необходимо удалить и снова прочитать поведение в ServiceHost.
Если у вас есть консольное приложение или служба 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 # (кстати, для WITH_FORMS_AUTHENTICATION необходимо установить значение true, а 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 голосов
/ 16 ноября 2009

Подумайте об исключении явного использования HttpContext.Current за интерфейсом, который вы можете отключить во время модульного тестирования.

HttpContext.Current определяется только в том случае, если ваша служба wcf в любом случае размещена в веб-приложении asp.net - если когда-нибудь вам потребуется разместить ее как обычную службу wcf, HttpContext.Current не будет доступен.

0 голосов
/ 12 ноября 2009

Это настройка для всего AppDomain, которую вы можете установить для статического ServiceHostingEnvironment класса в System.ServiceModel:

 ServiceHostingEnvironment.AspNetCompatibilityEnabled = true;

Это следует сделать перед созданием и открытием хостов службы.

Было бы неплохо - но это настройка только для чтения, и единственный способ установить ее - через конфигурацию :-(

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...