Parameter Sniffing: Why Does This Become An Issue?

Basically what happens is, when SQL Server sees a query that it needs to compile, it is going to use the first-time-called parameters to generate the execution plan. This may or may not be a good thing, but it is what happens.

For instance, say you have a table of fruit (100 rows). There are 98 rows that are Apple, and only 2 rows that contain the fruit Orange. If you query that table for Apple, then the plan will most likely compile with a Scan. This is a good thing, as it is optimized for that Apple query. But then when you want to query for the Orange, that Scan is inefficient. But it is the stored plan that is being used.

The fact of the matter is that it happens. It happens all the time. It's typically not an outstanding issue, but in some cases it can be a pretty big problem. A solution to an ongoing bad parameter sniffing problem is that you can utilize the OPTIMIZE FOR query hint to force SQL Server to use certain parameter values when generating the execution plan upon initial compilation.

...but executed quickly when run from SSMS (took 5 seconds)

Rather annoyingly, the SSMS default is for SET ARITHABORT ON whereas the majority of client libraries (ADO .Net, ODBC, OLE DB) specify SET ARITHABORT OFF. Likely you had a plan "go bad" but when you attempted to replicate via SSMS, the difference in ARITHABORT resulted in a different plan being used, which was "good".

Slow in the Application, Fast in SSMS? is a great reference for this.

Why did this happen?

Most likely a recompilation was triggered and unfortunately a non-typical set of inputs were used for the compilation.