Cast as int in CASE expression in SQL
Why are you casting the substring as an int in the first place? The consumer is going to expect that column to output as a string in every other case. So my suggestion: Just remove the cast. 

If you only want a value to appear in the resultset when it is a valid int, and you're on &lt; 2012 where TRY_CAST() is not possible, then you can say:

else case when isnumeric(SUBSTRING(l.id, 0, charindex('-', l.id, 0))) = 1
  THEN CAST SUBSTRING(l.id, 0, charindex('-', l.id, 0)) AS int END


Note: ISNUMERIC() is not a perfect validation that it is specifically an integer, but is probably fine here, since you don't really need an int, just a string that is formatted like an int.

Update What you can do now that I understand the requirements better is convert to an int and then back to a string. Since you are on 2014 you can use TRY_CONVERT():

ELSE CONVERT(varchar(12), 
  TRY_CONVERT(int, SUBSTRING(l.id, 0, charindex('-', l.id, 0)))) 
END


You might also consider fixing the design so that you don't have to parse these important bits of information out of bigger pieces of information, or at least move your CASE expression to a computed column or a view so you don't have to put all that logic in all (or any!) of your queries.