Web API中的SendAsync返回null

时间:2014-06-03 14:17:55

标签: c# asp.net-web-api

当用户尝试在授权令牌过期时调用服务或者他们的令牌无效时,我正在尝试返回相应的错误消息。

我遇到的问题是第一次调用它时,消息被正确发送,但是第一次调用SendAsync方法4次后,消息数据返回null。

我很困惑为什么它循环4次,我试着单步执行它,但我无法在代码中得到任何进一步的信息。

以下是代码:

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
                                                           CancellationToken cancellationToken)
    {
        if (request.Headers != null)
        {

             // ....

             if (request.Headers.GetValues(CustomTokenHeader).FirstOrDefault() == null)
             {
                  //unauthorized response(401)
                  return FromResult(_unauthorizedResponse);
             }
             var authHeader = request.Headers.GetValues(CustomTokenHeader).FirstOrDefault();
             if (String.IsNullOrWhiteSpace(authHeader))
             {
                 //unauthorized response(401)
                 return FromResult(_unauthorizedResponse);
             }

             //authenticate token
             return HandleTokenAuthentication(request, cancellationToken, authHeader);
        }
    }

    static Task<T> FromResult<T>(T t)
    {
        var tcs = new TaskCompletionSource<T>();
        tcs.SetResult(t);
        return tcs.Task;
    }


    private Task<HttpResponseMessage> HandleTokenAuthentication(HttpRequestMessage request, CancellationToken cancellationToken, string authHeader)
    {
        //parse token
        var token = ParseToken(authHeader);
        if (String.IsNullOrWhiteSpace(token))
        {
            //unauthorized response(401)
            return FromResult(_unauthorizedResponse);
        }

        //decrypt token
        var tokenInfo = DecryptToken(token);
        if (tokenInfo == null)
        {
            //unauthorized response(401)
            return FromResult(_unauthorizedResponse);
        }

        //validate token
        var claims = ValidateToken(tokenInfo, token);
        if (claims == null)
        {
            //unauthorized response(401)
            return FromResult(_unauthorizedTokenExpired);
        }
        var principal = CheckCustomAuthorization(claims);
         if (principal == null)
        {
            //unauthorized response(401)
            return FromResult(_unauthorizedResponse);
        }
        if (!principal.Identity.IsAuthenticated)
        {

            var loginFailureMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized)
            {
                Content = new StringContent(((AgencyClaims)principal.Identity).LoginFailureReason)
            };

            return FromResult(loginFailureMessage);
        }
        //assign principal
        Thread.CurrentPrincipal = principal;

        return base.SendAsync(request, cancellationToken)
                               .ContinueWith(task => AuthorizedResponse(request, task.Result));
    }

    static HttpResponseMessage AuthorizedResponse(HttpRequestMessage request, HttpResponseMessage response)
    {
        if ((request.Method == HttpMethod.Get && response.StatusCode == HttpStatusCode.OK
            && !response.Headers.Contains(CustomTokenHeader))
            || (request.Method == HttpMethod.Post && response.StatusCode == HttpStatusCode.Created
            && !response.Headers.Contains(CustomTokenHeader)))
        {
            var token = ((AgencyClaims) Thread.CurrentPrincipal.Identity).Token;
            response.Headers.Add(CustomTokenHeader, Convert.ToBase64String(Encoding.ASCII.GetBytes(token)));
        }
        return response;
    }

readonly HttpResponseMessage _unauthorizedResponse =
        new HttpResponseMessage(HttpStatusCode.Unauthorized) { Content = new StringContent("PROPER ERROR MESSAGE")};

成功回应:

 <data contentType="text/plain; charset=utf-8" contentLength="21"><![CDATA[Authentication failed]]></data>

以下是第一次成功回复后的回复:

<data contentType="null" contentLength="0"><![CDATA[]]></data>

以下是请求的一部分:

GET http://localhost:20559/api/Service?Name=Jack HTTP/1.1

1 个答案:

答案 0 :(得分:0)

好的,我能够解决这个问题。 _unauthorizedResponse类变量以某种方式允许代码成功运行一次,但不是第二次。此问题与readonly修饰符无关,因为没有它它仍然无法正常工作。我不确定这是如何工作的(也许这里有人可以解释),但是通过将它们移动到方法中的局部范围内,它每次都能正确运行。