简体   繁体   中英

HttpClient & WebAPI Unpredictable Redirect 302

I have a WPF app that uses HttpClient to call a Web API method on another server. Everything works fine, however, sometimes, especially when the client app wakes up (from power suspend), the call to the same server method returns Found: 302 instead of OK: 200.

The Web API method doesn't really do anything, and it just has an [Authorize] attribute to make sure the user is authenticated. Normally, if the user is not authenticated, it would return 404. BTW, I'm not using ASP.NET forms authentication explicitly, but the redirect is sending the client to login.aspx, which doesn't exist.

Here's the code: Web API Method (.NET 4.5):

[HttpGet]
public HttpStatusCodeResult IsAuthenticated()
{
    return new HttpStatusCodeResult(System.Net.HttpStatusCode.OK);
}

WPF App client code (.NET 4.0):

public async Task<bool> IsAuthenticated()
{
    try
    {
        Uri address = new Uri(AuthUrl);

        var cookieJar = ReadCookiesFromDisk(COOKIE_FILE);
        if (cookieJar.Count == 0)
            return false;
        var handler = new HttpClientHandler
        {
            CookieContainer = cookieJar,
            UseCookies = true,
            UseDefaultCredentials = false,
            AllowAutoRedirect = false
        };

        var client = new HttpClient(handler)
        {
            BaseAddress = address
        };

        int timeout = 15000;
        var task = client.GetAsync(address.ToString());
        Task[] tasks = new Task[1];
        tasks[0] = task;
        if (Task.WaitAny(tasks, timeout) != -1)
        {
            // task completed within timeout
            // checking for redirect, but this should not happen!!!
            HttpResponseMessage response = task.Result;
            if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Redirect)
                return true;
            else
                return false;
        }
        else
        {
            // timeout logic
            return false;
        }
    }
    catch (Exception e)
    {
        EventLogger.Log(e);
        return false;
    }
}

Client Authentication Code:

public async Task<string> Login(string data)
        {
            try
            {
                Uri address = new Uri(LoginUrl);
                HttpContent content = new StringContent(data, Encoding.UTF8);

                content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
                var cookieJar = ReadCookiesFromDisk(COOKIE_FILE);
                var handler = new HttpClientHandler
                {
                    CookieContainer = cookieJar,
                    UseCookies = true,
                    UseDefaultCredentials = false,
                    AllowAutoRedirect = false
                };

                var client = new HttpClient(handler)
                {
                    BaseAddress = address
                };
                HttpResponseMessage response = await client.PostAsync(address.ToString(), content);
                response.EnsureSuccessStatusCode();
                string body = await response.Content.ReadAsStringAsync();

                Uri uri = new Uri(UrlBase);
                var responseCookies = cookieJar.GetCookies(uri);
                if (responseCookies[".ASPXAUTH"] != null)
                    WriteCookiesToDisk(COOKIE_FILE, cookieJar);
                return body;
            }
            catch (Exception e)
            {
                return e.ToString();
            }
        }

Server:

public JsonResult LogOn(string userInfo)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            LogOnModel model = serializer.Deserialize<LogOnModel>(userInfo);
            JsonMessage error = null;
            if (ModelState.IsValid)
            {
                try
                {
                    if (WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
                    {
                        if (WebSecurity.IsConfirmed(model.UserName))
                        {
                            if (model.RememberMe)
                                Response.Cookies[0].Expires = DateTime.Now.AddDays(30);
                            else
                                Response.Cookies[0].Expires = DateTime.Now.AddDays(7);

                            var person = Dc.People.FirstOrDefault(x => x.UserName == model.UserName);
                            string fullName = string.Empty;
                            string email = string.Empty;
                            if (person != null)
                            {
                                fullName = string.Format("{0} {1}", person.FirstName, person.LastName);
                                email = person.Email;
                                //fill the session to create the session cookie
                                Session["1"] = 1;
                            }
                            var message = new { FailCount = 0, Message = WebSecurity.GetUserId(model.UserName).ToString(), Success = true, SuccessCount = 0, RedirectUrl = "#/conversations/priority", Name = fullName, UserEmail = email, UserHandle = model.UserName, UserAvatar = person.Avatar };
                            return Json(message);
                        }
                        else
                        {
                            error = new JsonMessage { FailCount = 0, Message = "Your aren't authorised to login", Success = false, SuccessCount = 0 };
                            TempData["Error"] = "Your are not authorised to login";
                            return Json(error);

                        }
                    }
                    else
                    {

                        TempData["Error"] = "The user name or password provided is incorrect.";
                        error = new JsonMessage { FailCount = 0, Message = "The user name or password provided is incorrect.", Success = false, SuccessCount = 0 };
                        return Json(error);
                    }
                }
                catch (Exception ex)
                {
                    TempData["Error"] = ex.Message;
                    error = new JsonMessage { FailCount = 0, Message = ex.Message, Success = false, SuccessCount = 0 };
                }
            }

            return Json(error);
        }

Change following code

 HttpResponseMessage response = await client.PostAsync(address.ToString(), content);

to

 HttpResponseMessage response = await client.PostAsync(address.ToString(), content).ConfigureAwait(false);

above statement sometime show deadlock issues when using ASync. so when you configure await to false for Async Task, it will work in correct manner.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM