我有一个WPF应用程序,它使用HttpClient在另一台服务器上调用Web API方法。一切正常,但有时,特别是当客户端应用程序唤醒时(从电源暂停),对同一服务器方法的调用返回Found:302而不是OK:200。
Web API方法实际上并没有做任何事情,它只有一个[Authorize]
属性来确保用户通过身份验证。通常,如果用户未经过身份验证,则会返回404。
顺便说一句,我没有明确地使用ASP.NET表单身份验证,但是重定向是将客户端发送到login.aspx,这不存在。
这是代码: Web API方法(.NET 4.5):
[HttpGet]
public HttpStatusCodeResult IsAuthenticated()
{
return new HttpStatusCodeResult(System.Net.HttpStatusCode.OK);
}
WPF App客户端代码(.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;
}
}
客户端验证码:
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();
}
}
服务器:
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);
}
答案 0 :(得分:-1)
更改以下代码
HttpResponseMessage response = await client.PostAsync(address.ToString(), content);
到
HttpResponseMessage response = await client.PostAsync(address.ToString(), content).ConfigureAwait(false);
以上语句有时会在使用ASync时显示死锁问题。因此,当您为异步任务配置await为false时,它将以正确的方式工作。