0

I have a web service call in my function Verify. The code is as follows:

public async Task<ActionResult> Index()
{
    ....
    
    UserContext.LoginUser = null;

    if (!string.IsNullOrEmpty(etoken))
    {
        SSOLogin ssoLogin = new SSOLogin();
        LoginUser user = await ssoLogin.Verify(etoken);
        UserContext.LoginUser = user;
        if (UserContext.LoginUser == null)
            return RedirectToAction("UnAuthorized", "Login");
        else
        {
            Session["authenticated"] = true;
            userId = UserContext.LoginUser.UserId;
            domain = UserContext.LoginUser.Domain;
        }
    }
}

public async Task<LoginUser> Verify(string etoken)
{
    string publicKey = "xxx";

    LoginUser loginUser = null;

    WSVerifyAccessToken wsVerifyAccessToken = new WSVerifyAccessToken();
    string verifyResponse = await wsVerifyAccessToken.VerifyAccessToken(etoken); // Inside, this is a web service call

    if (!string.IsNullOrEmpty(verifyResponse))
    {
        /* Some processing here */
    }


    return loginUser;
}

The problem is that, the UserContext becomes null after the Verify function

LoginUser user = await ssoLogin.Verify(etoken);

Hence when I assign

UserContext.LoginUser = user;

gives me the error System.NullReferenceException: Object reference not set to an instance of an object..

I tried to make the function to be synchronous

LoginUser user = await ssoLogin.Verify(etoken).Result;

but then the web service call will just hang there and never finishes.

Any solution?

rcs
  • 6,713
  • 12
  • 53
  • 75

1 Answers1

0

This is a known issue when the runtime target framework is 4.0, and not 4.5 or above, in the web.config file. This can differ from the target framework your project is set up for. Make sure that the runtime target framework is 4.5 or higher.

Additionally: The UserContext is bound to the Thread initializing the Request. Therefore, you should return the callback of your awaited call to the original context. Even though the ConfigureAwait(true) is the default value, you should ensure the correct context is used in the callback by specifying the following:

UserContext.LoginUser = await ssoLogin.Verify(etoken).ConfigureAwait(true);

See a more detailed description regarding the configure await method here

Thomas Luijken
  • 657
  • 5
  • 13
  • 1
    Isn't `.ConfigureAwait(true);` the default? – mjwills Jul 22 '20 at 11:13
  • @mjwills, ah yes, you are correct. My Roslyn analyzers have driven me to the point where I'm always explicit about this :). – Thomas Luijken Jul 22 '20 at 11:20
  • @rcs, also, check your runtime target framework in the web.config settings. I've updated my answer with references. This could differ from the framework version of your project. – Thomas Luijken Jul 22 '20 at 11:21
  • What if I'm using 4.7? I try not to downgrade my .net framework version – rcs Jul 22 '20 at 11:24
  • There is a difference between the Target version and the Runtime version. Just make sure the RUNTIME version isn't set to 4.0 by any chance. – Thomas Luijken Jul 22 '20 at 11:27
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/218353/discussion-between-thomas-luijken-and-rcs). – Thomas Luijken Jul 22 '20 at 11:40
  • I added this `` in the Web.config and it solves the problem. No need the `ConfigureAwait(true)` – rcs Jul 23 '20 at 00:45
  • Hi @rcs, I'm happy to hear adding the runtime targetFramework setting helped! Please mark this anwser as the correct answer. I would help other users get on the right track. I'll update the anwer accordingly. – Thomas Luijken Jul 23 '20 at 09:33