0

I created WCF service with aspnetcompatibility and webHttpBinding. At the beginning of method marked with WebGet attribute I have HttpContext.Current but it becomes null after 1st await. I tried both options: with ConfigureAwait(false) and without. You can find test project here on github. How to fix it?

using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Threading;
using System.Threading.Tasks;

namespace WcfAsync
{
    [ServiceContract(SessionMode = SessionMode.NotAllowed)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    //[ServiceBehavior(UseSynchronizationContext = true)] - TRIED THIS, IT DOESN'T WORK
    public class Service1
    {
        [OperationContract, WebGet]
        public async Task<string> GetStr(bool configureAwait)
        {
            System.Web.HttpContext.Current.Items["threadid"] = Thread.CurrentThread.ManagedThreadId.ToString();
            if (configureAwait)
            {
                await Task.Delay(100);
            }
            else
            {
                await Task.Delay(100).ConfigureAwait(false);
            }
            return System.Web.HttpContext.Current == null
                ? "null httpcontext"
                : System.Web.HttpContext.Current.Items["threadid"] == null
                    ? $"new httpcontext, threadid =  {Thread.CurrentThread.ManagedThreadId}"
                    : $"original httpcontext, threadid = {System.Web.HttpContext.Current.Items["threadid"]}";
        }
    }
}

It's my web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.6.1"/>
    <httpRuntime targetFramework="4.6.1"/>
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs"
        type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701"/>
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb"
        type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"/>
    </compilers>
  </system.codedom>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="EndPointBehavior">
          <enableWebScript/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service name="WcfAsync.Service1" behaviorConfiguration="ServiceBehavior">
        <endpoint address="" binding="webHttpBinding" contract="WcfAsync.Service1" behaviorConfiguration="EndPointBehavior" />
      </service>
    </services>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
      multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
</configuration>


I saw similar question here but there is no answer. So I create this one with example project on github.

mtkachenko
  • 5,389
  • 9
  • 38
  • 68
  • 2
    You have been here long enough that the code needs posting here, not somewhere else. Please post your minimal viable example here. – BugFinder Nov 06 '17 at 13:25
  • What happens if you hold on to the context before the await and then access it after? – Nkosi Nov 06 '17 at 13:28
  • @Nikosi it works this way. – mtkachenko Nov 06 '17 at 13:28
  • @mtkachenko can you confirm your last statement. Was my suggestion an acceptable answer? – Nkosi Nov 06 '17 at 13:30
  • 2
    Ensure that you are targeting at least .NET 4.5 and using at least ASP.NET 4.5. – Evk Nov 06 '17 at 13:31
  • @Nikosi I khew it before posting this answer. I want to know whether it's possible to fix it properly. – mtkachenko Nov 06 '17 at 13:33
  • @mtkachenko What is there to fix if there is a way where it works? – Nkosi Nov 06 '17 at 13:34
  • Are you using IIS Express or normal IIS by the way? – Evk Nov 06 '17 at 14:13
  • @Nikosi The method you described is a workaround. I want to know why it works this way and whether it's possible to force it to work properly. – mtkachenko Nov 06 '17 at 16:29
  • @Evk I tried both. – mtkachenko Nov 06 '17 at 16:30
  • @Evk I added web.config as well. – mtkachenko Nov 06 '17 at 16:33
  • 1
    Well it seems that's just not supported, see here: https://social.msdn.microsoft.com/Forums/vstudio/en-US/558df0bf-4cac-47a6-9cdc-9f0d4f8dd534/alternative-to-the-operationcontext-when-using-asyncawait?forum=wcf. I assumed that if you run under asp.net 4.5 your WCF would use its synhronization context which has support for async\await, but it seems not the case. See also here: https://stackoverflow.com/questions/18520290/using-the-aspnetsynchronizationcontext-from-wcf-hosted-in-iis – Evk Nov 06 '17 at 17:04
  • Did you ever find a solution to this problem? – Bouke Dec 22 '21 at 21:01
  • @Bouke Since the question is still open - no, I haven't found a solution. – mtkachenko Dec 26 '21 at 16:02

0 Answers0