Для отправки ответа серверу требуется слишком много времени - ошибка тайм-аута в ASP.NET Web API
Я создал приложение Web API, которое работает на сервере. На стороне клиента для тестирования у меня есть приложение для Android. Это довольно просто. Пользователь вводит имя пользователя и пароль и отправляет их с двумя строками DeviceId и DeviceName. Пользователь проверяется уже определенным сервисом, и если все идет хорошо, происходит 3 вещи:
- Пользователь создается и сохраняется в базе данных.
- Информация по электронной почте отправляется пользователю.
- Токен доступа возвращается клиенту.
Но после внесения некоторых изменений в мой код ответы от сервера начинают занимать слишком много времени, и для мобильных пользователей время ожидания слишком велико.
Я заметил, что тайм-аут начал происходить после того, как я добавил одну конкретную часть кода:
Regex rgx = new Regex("[^a-zA-Z0-9 -]");
string deviceId = rgx.Replace(model.DeviceId, "");
Эта часть используется для обрезки всех не буквенно-цифровых символов из строки DeviceID. Это важно, потому что перед добавлением этого кода у меня появляется ошибка, связанная с JSON, если у пользователя есть косая черта или обратная косая черта в этой переменной.
Поэтому мой вопрос: возможно ли, чтобы класс Regex и его методы создавали некоторую путаницу на сервере и заставляли ответ от сервера занимать слишком много времени?
Если это какая-то помощь, это код проблемного вызова:
[Route("registration/request")]
public async Task<HttpResponseMessage> RegistrationRequest(Registration model)
{
try
{
MatrixLogManager.Info("Starting token creating.");
var request = HttpContext.Current.Request;
var tokenServiceUrl = request.Url.GetLeftPart(UriPartial.Authority) + request.ApplicationPath + "/Token";
MatrixLogManager.Info("Checking if model is valid.");
if (!ModelState.IsValid)
{
return Request.CreateResponse(BadRequest(ModelState));
}
using (MatrixServiceLayerLogin login = new MatrixServiceLayerLogin())
{
if (login.LoginUser(model.UserName, model.Password, true, true))
{
var personId = login.GetPersonId();
MatrixLogManager.Debug("User " + model.UserName + " successfully logged in on MatrixSTS.");
try
{
using (var authRepo = new AuthRepository())
{
MatrixLogManager.Info("Changing deviceID format.");
Regex rgx = new Regex("[^a-zA-Z0-9 -]");
model.DeviceId = rgx.Replace(model.DeviceId, "");
MatrixLogManager.Debug(model.DeviceId);
MatrixLogManager.Debug("Saving user: " + model.DeviceId);
ApplicationUser appUser = new UserFactory().CreateApplicationUser(model, personId);
IdentityResult result = await authRepo.RegisterUser(appUser);
EMailService.SendEmail(appUser);
IHttpActionResult errorResult = GetErrorResult(result);
MatrixLogManager.Debug("Saved user: " + model.DeviceId);
if (errorResult != null)
{
return Request.CreateResponse(errorResult);
}
using (var client = new HttpClient())
{
var requestParams = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", appUser.UserName),
new KeyValuePair<string, string>("password", "0000")
};
var requestParamsFormUrlEncoded = new FormUrlEncodedContent(requestParams);
var tokenServiceResponse = await client.PostAsync(tokenServiceUrl, requestParamsFormUrlEncoded);
var responseString = await tokenServiceResponse.Content.ReadAsStringAsync();
var responseCode = tokenServiceResponse.StatusCode;
var responseMsg = new HttpResponseMessage(responseCode)
{
Content = new StringContent(responseString, Encoding.UTF8, "application/json")
};
responseMsg.Headers.Add("PSK", appUser.PSK);
return responseMsg;
}
}
}
catch (Exception ex)
{
MatrixLogManager.Error("Error: ", ex);
throw ex;
}
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid username or password.");
}
}
}
catch (Exception ex)
{
MatrixLogManager.Error(string.Format("Error while trying registring user: Exception = {0} InnerException {1}", ex.Message, ex.InnerException.Message));
throw;
}
}
PS Еще одна вещь. Когда я тестирую этот код на моей машине, локально время отклика не так велико, и все идет хорошо. Проблема только в том, что этот код публикуется на сервере, и это происходит время от времени.
1 ответ
Я вижу две проблемы здесь:
Regex rgx = new Regex("[^a-zA-Z0-9 -]");
model.DeviceId = rgx.Replace(model.DeviceId, "");
Во-первых, используя конструктор regex, вы заставляете систему создавать новый объект Regex каждый раз, когда вы его применяете. Если вместо этого вы используете один из статических методов, система автоматически кэширует объект Regex при первом его использовании. Или вы можете заранее создать Regex и сохранить его в статической переменной.
Во-вторых, вы заменяете нежелательных персонажей по одному, что крайне неэффективно. Добавить +
до конца вашего регулярного выражения, чтобы соответствовать целые последовательности нежелательных символов одновременно.
model.DeviceId = Regex.Replace(model.DeviceId, "[^a-zA-Z0-9 -]+", "");