How to set ServiceHostingEnvironment.AspNetCompatibilityEnabled = true in Code (not in config) .NET/C#

前端 未结 5 1741
南笙
南笙 2021-02-03 11:09

I have a requirement to access the HttpContext.Current from with-in a RESTful WCF service. I know I am able to achieve this by adding the following to config:

&         


        
5条回答
  •  半阙折子戏
    2021-02-03 11:33

    To Elaborate on Austin Harris's answer:

    You need to alter the behaviour of ServiceHost.
    Because the attribute is read-only, you need to remove, and readd the behaviour to ServiceHost.
    If you have a console application or Windows Service, you'll have this servicehost defined.

    Something like this:

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

    in which case Austin Harris' code would suffice (if he hadn't written Allowed instead of Required...).

    However, if you have the WCF-Service integrated into an ASP.NET application, the tricky part is to get the ServiceHost.

    The key is the factory attribute in the YOUR_SERVICE.svc markup file.

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

    Then you need to write your own factory.
    The below code is VB.NET, I'll leave it to the reader to translate it into C# (you'll need to set WITH_FORMS_AUTHENTICATION to true by the way, and 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 )  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 
    

提交回复
热议问题