I've written this code more times than I can count:
var isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
var isEmpty = list == null || list.Count == 0;
string json;
try
{
json = JsonConvert.SerializeObject(user);
}
catch
{
json = "{}";
}
And the PowerCSharp version of the same three things:
var isWeekend = date.IsWeekend();
var isEmpty = list.IsNullOrEmpty();
var json = JsonHelper.SafeSerialize(user); // never throws, "{}" on failure
None of that is clever. That's the point — it's boilerplate, and boilerplate is exactly what's worth centralizing once you've written it in enough different projects.
The one in this set that's actually worth pausing on is path handling:
// Vulnerable — fileName = "../../etc/passwd" escapes uploadDir
var fullPath = Path.Combine(uploadDir, fileName);
// PowerCSharp
try
{
var safePath = PathExtensions.CombineAndValidate(uploadDir, fileName);
SaveFile(safePath, content);
}
catch (SecurityException)
{
// reject, log, return 403
}
CombineAndValidate canonicalizes the combined path and checks the result is still inside uploadDir before handing it back — the same base-directory containment check Veracode recommends for CWE-73 (path traversal). It's one method doing one job; if your threat model needs more than path containment, that's a separate conversation, and I'd rather say that up front than let anyone assume this is a full defense-in-depth stack.
Also in the Extensions package: runtime LINQ from strings.
var predicate = "Age > 18 && Name.Contains('John')".GetExpressionDelegate<Person>();
var filtered = people.Where(predicate);
Genuinely useful for search boxes and query-parameter filters. Also genuinely an injection surface — a string like "Age > 0 || 1 == 1" bypasses whatever filter you meant to apply. Treat it like SQL built from user input: allow-list the properties and operators you accept before the string reaches GetExpressionDelegate. PowerCSharp gives you the parsing, not a validation layer — I'd rather be explicit about that than have someone assume otherwise and find out the hard way.
Package map, so you know what to actually install:
| Package | What it's for | Reach for it when |
|---|---|---|
PowerCSharp.Core |
Shared interfaces, no logic | You're using any other package (it's the dependency) |
PowerCSharp.Extensions |
100+ extension methods (string/DateTime/collections/LINQ/HTTP/JSON) | Almost always |
PowerCSharp.Extensions.AspNetCore |
ASP.NET Core-specific extensions (Uri.AddParameter, config binding) |
You're in an ASP.NET Core project |
PowerCSharp.Utilities |
FileHelper, MathHelper
|
File I/O or math edge cases |
PowerCSharp.Helpers |
JsonHelper, CryptoHelper, EnvironmentHelper
|
Safe JSON/hashing/env access |
PowerCSharp.Compatibility |
.NET Framework bridges (AsyncHelper.RunSync, ValidationHelper) |
You're still on .NET Framework/System.Web |
Install only what you need — they're independently versioned on purpose.

Top comments (0)