0

I've created a Web API application that's working on server. On the client side, for testing I have android application. It is pretty simple. User enters username and password and sends them with two more strings DeviceId and DeviceName. The user gets verified by already defined service and if everything goes well 3 things happens:

  1. User gets created and saved in database.
  2. Information e-mail is sent to a user.
  3. Access token is returned to client.

But after making some changes in my code, responses from server begin to take too long, and for mobile users timeout occurs too often.

I've notice that timeout started to happens after I've added one particular part of code:

Regex rgx = new Regex("[^a-zA-Z0-9 -]");
string deviceId = rgx.Replace(model.DeviceId, "");

This part is used to trim all non alpha-numeric characters from DeviceID string. This is important because before adding this code I've got JSON related error if user had slash or backslash in this variable.

So my question is: Is it possible that Regex class and its methods make some mess on the server and makes response from server takes too long?

If it is any of help, this is the code of an problematic call:

[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;
    }
}

P.S. One more thing. When I test this code on my machine, locally response time is not so long, and everything goes well. The problem is only when this code is published to a server, and it happens times to times.

nemo_87
  • 4,523
  • 16
  • 56
  • 102
  • I think regex is not to blame unless you have 1000 pings per second. The best practice (well, my best practice) is to use it as a private/public static readonly field with `RegexOptions.Compiled` option set. Try, and if problem persists, this will be certainly not a regex problem. – Wiktor Stribiżew Apr 23 '15 at 10:55

1 Answers1

0

I see two problems here:

Regex rgx = new Regex("[^a-zA-Z0-9 -]");
model.DeviceId = rgx.Replace(model.DeviceId, "");

First, by using the regex constructor you're forcing the system to create a new Regex object every time you apply it. If you use one of the static methods instead, the system automatically caches the Regex object the first time you use it. Or you can construct the Regex ahead of time and store it in a static variable.

Second, you're replacing the unwanted characters one at a time, which is grievously inefficient. Add a + to the end of your regex to match whole sequences of the undesired characters at a time.

model.DeviceId = Regex.Replace(model.DeviceId, "[^a-zA-Z0-9 -]+", "");
Alan Moore
  • 73,866
  • 12
  • 100
  • 156