Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

rest

c#

.net

wcf

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:

<serviceHostingEnvironment aspNetCompatibilityEnabled=”true” />

and using the following attribute on my service:

[AspNetCompatibilityRequirements(RequirementsMode 
    = AspNetCompatibilityRequirementsMode.Required)]

Here is my issue, I need to "spin up" an instance of the service in code for unit testing and therefore I cannot use config files to specify service bebaviours etc. At the moment my code looks like follows, but despite scouring the web I have been unable to work out how I set up a ServiceHostingEnvironment class and set the AspNetCompatibilityEnabled property to true without using config, can anyone help?

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

Any help is much appreciated and thanks in advance.

like image 864
Oliver Pearmain Avatar asked Nov 12 '09 10:11

Oliver Pearmain


2 Answers

You can totally do this, I don't know what these other answers are about, but they are way off!

Just do something like:

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

-- Edit This removes the existing behavior if it exists, and then adds a new behavior that has the mode you prefer. My example sets it to .Allowed, but you could of course set it to the mode you desire.

like image 153
Austin Harris Avatar answered Sep 30 '22 05:09

Austin Harris


After digging around with Reflector, I was able to set the AspNetCompatibilityEnabled flag using reflection. This approach has obvious drawbacks, but it did the job for me:

        // 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)));
like image 26
Adi Avatar answered Sep 30 '22 03:09

Adi