Friday, December 9, 2011

WCF Delay when making multiple calls

We were having an issue with a delay that would only surface occasionally. I tracked it down to a service we have that holds the connection open until it has something to send to the client or 15 seconds and it sends a heartbeat back.
Every so often things would stop responding. I tracked it down to be occurring only while we were waiting for the blocking call to return. This did not happen all the time but we could repo it regularly by using the app.

I did a google search as always and found a wcf setting called MaxConnections. So I put it in and changed the value to 100. Tested it and voila!

We had some helper classes that would open connections and keep the services alive (inContact.WCFConnector)

http://msdn.microsoft.com/en-us/library/wcf.maxconnections(v=bts.10).aspx

system.net>>>connectionManagement>>>add address = "*" maxconnection = "100" />

Tuesday, November 22, 2011

RegEx for Dates including leap year with locale support

First of all when you are playing with regex it helps to have a tool that will let you see what is happening. For this I have found Expresso (http://www.ultrapico.com/Expresso.htm found here in 2011 and is a free tool).

While working on the localization of our entire suite of systems & applications we needed a regular expression that would validate user input for a date. So depending on the user locale/language the date format changes. We needed three: Day first(Europe) DD.MM.YYYY, Month first MM/DD/YYYY (US) and year first YYYY/MM/DD (chinese).

So we set the value of the Threads current context and used the DateFormatInfo class from there to determine which format to use.
Then we found a regEx that worked for US (ref.1) and modified it for out use.

^(?

(?

(?0?[1-9]|1[012])

[- /.]{1} #seperator

(?0?[1-9]|1\d|2[0-8])

|

(?0?[13456789]|1[012])

[- /.]{1} #seperator

(?29|30)

|

(?0?[13578]|1[02])

[- /.]{1} #seperator

(?31))

[- /.]{1} #seperator

(?19|[2-9]\d)

(?\d{2})

|

(?0?2)

[- /.]{1} #seperator

(?29)

[- /.]{1} #seperator

(?(?19|[2-9]\d)(?0[48]|[2468][048]|[13579][26])|(?(?[2468][048]|[3579][26])00)) # leap year 02 or 2 / 29

)$

|

#German

^(?

(?

(?0?[1-9]|1\d|2[0-8])

[- /.]{1} #seperator

(?0?[1-9]|1[012])

|

(?29|30)

[- /.]{1} #seperator

(?0?[13456789]|1[012])

|

(?31)

[- /.]{1} #seperator

(?0?[13578]|1[02])

)

[- /.]{1} #seperator

(?19|[2-9]\d)

(?\d{2})

|

(?29)

[- /.]{1} #seperator

(?0?2)

[- /.]{1} #seperator

(?

(?19|[2-9]\d)

(?0[48]|[2468][048]|[13579][26])

|

(?

(?[2468][048]|[3579][26])00)) # leap year 02 or 2 / 29

)$

|

#CHN

^(?

(?19|[2-9]\d)

(?\d{2})

[- /.]{1} #seperator

(?

(?0?[1-9]|1[012])

[- /.]{1} #seperator

(?0?[1-9]|1\d|2[0-8])

|

(?0?[13456789]|1[012])

[- /.]{1} #seperator

(?29|30)

|

(?0?[13578]|1[02])

[- /.]{1} #seperator

(?31))

|

(?(?19|[2-9]\d)(?0[48]|[2468][048]|[13579][26])|(?(?[2468][048]|[3579][26])00)) # leap year 02 or 2 / 29

[- /.]{1} #seperator

(?0?2)

[- /.]{1} #seperator

(?29)

)$



-------------------------------
Ref.1 - by Dany Lauener; http://regexlib.com/UserPatterns.aspx?authorId=81355952-f53d-4142-bc5c-aab2beae19f3; search for "MM/dd/yyyy with 100% leap years. Valid since year 1900"

Thursday, May 12, 2011

VS Remote debugging OMG

It really shouldn't be this difficult... I spent a couple days trying to get this running and finally, boom it's on!
The remote machine did not have a firewall running for us.
Start the debugger on the remote machine, you will see the name and who it is running as.
http://msdn.microsoft.com/en-us/library/ee126350.aspx
We had rules set up for inbound and outbound specifically for Devenv.exe after removing all rules then following the above like things magically worked.

Note: When connecting to the remote machine w/ VS make sure you enter credentials if necessary like /username@machine eg ucn/rob.ling@eng-ngpcl07

Problems we had: remote debugger would show that the connection was being made but then our VS connection would time out. I think this was fixed by adding the UDP rule.

And this is fun.
http://www.youtube.com/watch?v=sSUXTFceilo

Monday, March 7, 2011

Tasks and anonymous delegates in for loops

Today at work I found a problem with using annonamous delagates tasks and foreach. Below is the code

List waitingSkills = new List();
foreach (var si in AgentSkills)
{
var t = Task.Factory.StartNew(delegate
{
try
{
si.Value.Dispositions = GetDispositions(si.Value.SkillNo);
}
catch (Exception ex)
{ ...
}

});

waitingSkills.Add(t);
}

var done = false;

while (!done)
{
done = true;
for (int i = 0; i < waitingSkills.Count; i++)
{
if (!waitingSkills[i].IsCompleted)
{
done = false;
Thread.Sleep(100);
break;
}

}

}

---------------------------------
The problem is that the value of si is the local value or last value assigned before the task kicks off. In my case the value was always the last value in the AgentSkills collection.

Here is the refactor. I got there by using this example found in Introducing Visual C# 2010

public void ProcessUpdateSkillsEvent(UpdateAgentSkillsEvent e)
{
ReskillSkills = new Dictionary();
AgentSkills = new Dictionary();

e.ReskillSkills.Where(r => r.SkillType == "Inbound").ToList().ForEach(rs => ReskillSkills.Add(rs.ID, ConvertAgentSkillToISkillItem(rs)));
e.Skills.ToList().ForEach(rs => AgentSkills.Add(rs.ID, ConvertAgentSkillToISkillItem(rs)));

var listOfSkills = AgentSkills.Values.ToList();
var waitingSkills = new Task[AgentSkills.Count];

//Create a func so we can pass the skillItem to the method so we can load the dispositions in a seperate thread.
Func funcGetDispositions = FuncGetDispositions;
for (int i = 0; i < listOfSkills.Count; ++i)
{
waitingSkills[i] = Task.Factory.StartNew(funcGetDispositions, listOfSkills[i]);
}

Task.WaitAll(waitingSkills.ToArray());

if (OnAgentSkillsUpdated != null)
OnAgentSkillsUpdated(AgentSkills.Values.ToList());

if (OnReskillSkillsUpdated != null)
OnReskillSkillsUpdated(ReskillSkills.Values.ToList());
}

public SkillItem FuncGetDispositions(object obj)
{
var skill = (SkillItem) obj;
try
{
skill.Dispositions = GetDispositions(skill.SkillNo);
}
catch (Exception ex)
{...
}
return skill;

}

Wednesday, February 16, 2011

Moq Setting local variable using callbacks.

http://code.google.com/p/moq/wiki/QuickStart


// Set up the mock:

AgentLoginParams passedObject = null;

moduleMock.Setup(mm=>mm.Login(It.IsAny())).Callback(alp=> passedObject = alp);

// Do something you’re testing

controller.Login(station, userName, password);

// Assert that something was called with the correct data

Assert.IsNotNull(passedObject);

Assert.AreEqual(userName,passedObject.UserName);

Monday, February 7, 2011

TFS Task Control/App

Found by a coworker..

In trying to figure out an easier way to keep track of my tasks in TFS, I stumbled across this FREE tool from Telerik (registration required, or you can rename the attached file to an MSI, and install). It is a stand-alone app that connects to the TFS server, and provides a way to keep an eye on your tasks outside of Visual Studio. It also provides a task board, supports Sprint Planning with your team, and much more. It is used internally by Telerik as part of their AGILE shop, and is geared towards that.

For me, I can keep this open to monitor my tasks and untether myself from Visual Studio. This makes it easier as I have multiple instances of VS open at a time, and when I close one, sometimes lose all my tasks/query tabs, etc.

Basic query view:

Wednesday, February 2, 2011

WCF Faults and Exceptions

Having spent the whole day trying to send exception information back up to the client....

Make it easy on yourself and do not include the Exception class as a property of the FaultException class. But if you do look at the links below.


How to impliment the IErrorHandler
http://codeidol.com/csharp/wcf/Faults/Error-Handling-Extensions/

How to make Exception class serialize using IErrorHandler:
http://www.woutware.com/blog/?tag=/faultexception

Monday, January 31, 2011

Using WinMerge with TFS

The default merge and compare tool for TFS blows. This is a better alternative.

http://www.neovolve.com/post/2007/06/19/using-winmerge-with-tfs.aspx