0

In my Asp.Net web service i use below 2 method to change an existing client's status form a global list oblject named ClientStatus here. This global list is modified from several client side but in a safe way (lock).

private static List<ActiveClient> ClientStatus = new List<ActiveClient>();
public static void SetClinetStatus(string ClientID, int clinetstatus)
{
    ActiveClient activeClient=null;
    try
    {
            activeClient = GetClient(ClientID);
            if (activeClient != null)
            {
                activeClient.statuschanged = true;
                activeClient.status = clinetstatus;
            }
    }
    catch (Exception ex)
    {
        WebserviceLog.Debug(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType + "::" + System.Reflection.MethodBase.GetCurrentMethod().ToString() + ":" + ex.Message);
    }

}

public static ActiveClient GetClient(string clientID)
{
    ActiveClient activeClient = null;
    try
    {
        lock (ClientStatus)
        {
            activeClient = ClientStatus.Find(c => c.clinetID == clientID);
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
    return activeClient;
}

I used below code to pass the value to SetClinetStatus(string ClientID, int clinetstatus) method

string errorData = Encoding.Default.GetString(data);
string[] tokens = errorData.Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries);
if (tokens.Length == 2)
    {                         
     SessionVariables.SetClinetStatus(tokens[0],Convert.ToInt32(tokens[1]));
    }

But sometimes (not every times) i get

Object reference not set to an instance of an object

form

activeClient = GetClient(ClientID);

i don't understand why it is happening and don't see any problem there.

does anyone see any problem there that is responsible for such kind of exception.

EDIT

In the global list i only add client through below method and here clientID will come from direct webservice method. and in another end (from where the client ID comes) i added a check for not to null or empty the clientID.

 public static void AddClient(string clientID)
        {
            try
            {
                lock (ClientStatus)
                {
                    ClientStatus.Add(new ActiveClient { clinetID = clientID });
                }

            }
            catch (Exception ex)
            {
                WebserviceLog.Debug(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType + "::" + System.Reflection.MethodBase.GetCurrentMethod().ToString() + ":" + ex.Message);
            }

        }

and the ActiveClient class structure is

public class ActiveClient
    {
        public ActiveClient()
        {
            clinetID = string.Empty;
            status = 0;
            statuschanged = false;
        }
        public string clinetID { get; set; }
        public int status { get; set; }
        public bool statuschanged { get; set; } 
    }
Rezoan
  • 1,745
  • 22
  • 51
  • 2
    `throw ex;` is a very bad practice usually, consider switching to `throw;`. – Andrei Jul 09 '13 at 10:45
  • 1
    Where/When is ClientStatus initialized? – Riv Jul 09 '13 at 10:47
  • `ClientStatus` is probably the issue here, but there is no indication in your code where this is set. @Andrei just to add to that, it's also not a good idea to catch `Exception` either... – James Jul 09 '13 at 10:48
  • Is the ClientID ever null? – doctorlove Jul 09 '13 at 10:48
  • @Rezoan, no, problem is elsewhere, but this is a place for improvement anyway. [Read this](http://stackoverflow.com/questions/1697216/the-difference-between-try-catch-throw-and-try-catche-throw-e?lq=1) for further details. – Andrei Jul 09 '13 at 10:49
  • @doctorlove looking at the code, even if it was `null` it wouldn't throw an NRE. – James Jul 09 '13 at 10:49
  • I think ClientStatus in not the problem here. i set a log after activeClient = GetClient(ClientID); and this log is never printed when this exception is occured @James – Rezoan Jul 09 '13 at 10:50
  • James ClientStatus List is initialized globally as private static List ClientStatus = new List(); – Rezoan Jul 09 '13 at 10:52
  • i used 2 public mathod to get and set ActiveCliet to it in a thread safe manner @james – Rezoan Jul 09 '13 at 10:53
  • @Rezoan if you're *adamant* that `ClientStatus` isn't null then the only other thing I can think of is possibly an item in the list is `null`. It's really not a good idea to be using the list itself as the locking object either... – James Jul 09 '13 at 11:11
  • there is no possiblity for null clientID @doctorlove – Rezoan Jul 09 '13 at 11:15
  • @Rezoan, the reason @Andrei mentioned it is bad-practice to `throw ex;` is that you lose the stack trace. `throw;` preserves it. – Moo-Juice Jul 09 '13 at 11:16
  • Also for the love of god, please correct the typos in your code! - Oh, and have you tried debugging? – Moo-Juice Jul 09 '13 at 11:17
  • @Rezoan create a `static` object and use that for locking instead. It's also really not a good idea to be using a static list in a multi-threaded environment, it's generally the cause of these sort of problems. – James Jul 09 '13 at 11:18
  • @Rezoan "*this log is never printed when this exception is occurred*" - interesting, that gives me the impression that the issue is in your catch then i.e. `WebserviceLog` is null. – James Jul 09 '13 at 11:19
  • This problem happen sometimes so it is not possible to find using debugging i think. i set some log before and after of some code line where i think the problem can occure and i found the exception occcured at activeClient = GetClient(ClientID); @Moo-Juice – Rezoan Jul 09 '13 at 11:24
  • James i say that i set a log after activeClient = GetClient(ClientID); which is not printed but the log in catch block is printed. – Rezoan Jul 09 '13 at 11:26
  • @Rezoan ah ok, well for me the issue is probably in the list itself. Is there a scenario where an item in the list could be set to null? – James Jul 09 '13 at 11:33
  • No jemes see the edit – Rezoan Jul 09 '13 at 12:33

1 Answers1

0

Try

public static void SetClinetStatus(string ClientID, int clinetstatus)
{
    ClientID = ClientID.Trim();

    // Cannot run unless there is a ClientID submitted
    if(string.IsNullOrEmpty(ClientID))
    {
        // Log handling of event
        return;
    }

    ActiveClient activeClient=null;
    try
    {
        activeClient = GetClient(ClientID);
        if (activeClient != null)
        {
            activeClient.statuschanged = true;
            activeClient.status = clinetstatus;
        }
    }
    catch (Exception ex)
    {
        WebserviceLog.Debug(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType + "::" + System.Reflection.MethodBase.GetCurrentMethod().ToString() + ":" + ex.Message);
    }

}

You should also ensure the clientID is in the ClientStatus

public static ActiveClient GetClient(string clientID)
{
    // Cannot continue without a ClientStatus
    if(ClientStatus == null) 
    {
        return null;
    }

    ActiveClient activeClient = null;
    try
    {
        lock (ClientStatus)
        {
            // Test if there are any matching elements
            if(ClientStatus.Any(c => c.clinetID == clientID))
            {
                activeClient = ClientStatus.Find(c => c.clinetID != null && c.clinetID == clientID);
            }
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }

    // This will return null if there are no matching elements
    return activeClient;
}
Eric Herlitz
  • 25,354
  • 27
  • 113
  • 157
  • But i see the ClientID is not null or empty while this exception occured. cause i set the log for checking. @Eric Herlitz – Rezoan Jul 09 '13 at 10:56
  • I USED below code before setting the ClientID string[] tokens = errorData.Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length == 2) { SessionVariables.SetClinetStatus(tokens[0],Convert.ToInt32(tokens[1])); } – Rezoan Jul 09 '13 at 10:57
  • Maybe ClientID needs to be trimmed?, added ClientID = ClientID.Trim(); – Eric Herlitz Jul 09 '13 at 10:59
  • Also added ClientStatus check to GetClient – Eric Herlitz Jul 09 '13 at 11:01
  • before sending the ClientID form ClientEnd i trimmed this @Eric Herlitz – Rezoan Jul 09 '13 at 11:05
  • is there any possiblity for ClientStatus.Find(c => c.clinetID == clientID); to through exception if clientID not found @Eric Herlitz – Rezoan Jul 09 '13 at 11:08
  • Well I prefer using Where() or First() instead of Find(), worth a shot. – Eric Herlitz Jul 09 '13 at 11:09
  • I am dam sure the client ID is exist before i perform any Find operation and as far as i know ClientStatus.Find(c => c.clinetID == clientID); should return null if there is no match found. am i wrong? – Rezoan Jul 09 '13 at 11:10
  • Maybe Find is a bad boy not taking null values of the object properties into consideration? Hence a null check may be required ClientStatus.Find(c => c.clinetID != null && c.clinetID == clientID); – Eric Herlitz Jul 09 '13 at 11:12
  • ok Eric im adding this condition and checking but it may need one or two day to get this exception again if it is happen – Rezoan Jul 09 '13 at 11:28
  • `Find` isn't the problem here and calling `Any` *and* `Find` is just wasteful. If there is supposed to be only 1 item in the list matching the id the OP should be calling `SingleOrDefault` or `FirstOrDefault` otherwise they should use `Where`. – James Jul 09 '13 at 11:36
  • But jemes also Find will get the first occurrence of the object isn't it? – Rezoan Jul 09 '13 at 11:58