Imported from enduracode/enterprise-web-library (
AGENTS.md). Install upstream withnpx skills add enduracode/enterprise-web-library. Copyright stays with the author.
IMPORTANT: Review Critical Development Rules before performing any tasks. Subagents are invoked via the task tool with subagent_type.
Project Overview
Enterprise Web Library (EWL) is an opinionated .NET framework for building web-based enterprise software.
The solution is C# targeting net10.0, using ASP.NET Core with EWL's own
component-based web framework layered on top (no Razor views). Source control is
Mercurial. If a .hg directory is present, load the ewl-mercurial skill
before running any version control commands.
Key Projects
| Project | Purpose |
|---|---|
Core\ |
Main EWL library (NuGet package) |
Library\ |
System-specific library; references Core plus providers |
Website\ |
Demo ASP.NET Core web application |
Tests\ |
NUnit test project |
Development Utility\ |
CLI tool for code generation and build ops |
Providers\ |
Pluggable provider implementations |
Solution file: Enterprise Web Library.sln
Build Commands
# Restore packages
dotnet restore "Enterprise Web Library.sln"
# Build (Debug, the default)
dotnet build "Enterprise Web Library.sln"
# Build (Release) -- note: Tests project is excluded from Release
dotnet build "Enterprise Web Library.sln" -c Release
Code Generation (Development Utility)
The EWL Development Utility (DU) performs code generation, populating
Generated Code\ folders in every project. It does not run automatically
during builds; it must be run explicitly.
Use Solution Files\Update Dependent Logic.ps1, which installs the latest
published EWL Development Utility dotnet tool and runs the DU from it. Only use
the local DU when making changes to code generation logic:
dotnet run --project "Development Utility/Development Utility.csproj" -- sync
Build Server Flow
The build server (EWL System Manager ISU) builds EWL using only the released DU from the latest published NuGet package:
- Clone the repository and
dotnet restore. - Install the latest
Ewl.DevelopmentUtilitydotnet tool and run its DU withsync. dotnet restore --force(picks up regeneratedDirectory.Build.props).- Run the released DU again with
export-logic(builds and packages).
All code generation and building is done by the DU from the latest published package. This means any changes pushed to EWL must compile against code generated by the currently released DU. Changes to code generation logic typically need to be pushed and published first, then changes that depend on the new generation can be pushed afterward.
Other Helper Scripts
Solution Files\Export EWL to Local Feed.ps1-- exports EWL as a NuGet package to a local feed
Test Commands
Test framework: NUnit 4.4.0. Test project: Tests\Tests.csproj.
The Tests project does NOT build in Release configuration; always use Debug.
dotnet test "Tests\Tests.csproj"
dotnet test "Tests\Tests.csproj" --filter "FullyQualifiedName~Tests.DoubleTools.ToMoneyString.Test"
Code Inspection
After making functional changes to C# or XML/XSD files, run both inspection subagents in the order below.
Abstraction Review
If any changed files are C# files, invoke the ewl-abstraction-review subagent
with the list of changed C# files. It reviews diffs for cases where manual code
could be replaced with TEWL or EWL abstractions. Fix any findings it reports.
ReSharper Format/Inspect
Invoke the ewl-cleanup subagent with the list of changed files. Ask it to
format and inspect but not commit. If the abstraction review produced fixes
above, those files are included here automatically since they are part of the
same changed-file set. When the cleanup agent reports fixes (e.g., "Issues
fixed", "Typography corrections"), these are already applied -- do not re-apply
them. Only address "Remaining issues".
Shell and Path Handling
The Bash tool runs Git Bash (MSYS2), not cmd.exe. Key implications:
- Use
rm, notdel, for file deletion.delis a CMD builtin that does not exist in bash and fails silently when stderr is suppressed. - Many paths in this environment contain spaces and non-ASCII characters
(e.g.
Revision Control\EwlBill,Enterprise Web Library.sln,EnduraCode's TEWL). Always double-quote paths in shell commands. Be aware that some Windows tools (e.g.findstr) misparse arguments when the working directory path contains spaces, even for piped input. Prefer Unix-style tools (grep,sed,awk) over Windows equivalents (findstr,find).
Critical Development Rules
- Before editing any C# or XML/XSD files, invoke the
ewl-cleanupsubagent with the list of files you plan to edit. Ask it to format only (not inspect) and to commit the formatting changes if any are made. Treat this as an explicit exception to any general instruction not to create commits unless the user requests them. - After making functional changes, run the inspection subagents described in Code Inspection.
- Never edit files in any
Generated Code\folder, the.opencode\folder, EWL-prefixed skill directories under.agents\skills\, the.claude\folder, or.mcp.json. They are fully regenerated by the Development Utility. Your changes will be overwritten. See thesyncoperation in the DU for how these are generated. After changing source files, follow rule 4 below. - After changing DU code or any source files that feed into code generation
(e.g. files in
Library\Files\, database schema, page classes, configuration XML, or the DU itself), you must:- Run the DU
syncoperation. - Build the solution to confirm everything compiles.
- Inspect the relevant generated output files to verify they reflect your changes correctly.
- Run the DU
- Tabs for indentation in C# files, never spaces.
- Configuration lives in XML files validated against XSD schemas in
Configuration\folders. - UI is built with EWL's component model (methods returning component collections), not Razor.
- Page classes use EWL's code-generation-based URL routing, inheriting from generated bases.
- Data access uses EWL's generated data-access layer from database schema.
Code Style Guidelines
Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Namespaces | PascalCase matching dirs | EnterpriseWebLibrary.Caching |
| Classes / Interfaces | PascalCase | AppMemoryCache, SystemUser |
| Public methods | PascalCase | GetCacheValue(), InitStatics() |
| Private methods | camelCase | tick(), getControls() |
| Internal readonly fields | PascalCase | internal readonly string Host; |
| Private fields | camelCase | currentTimeGetter, nonsecurePort |
| Local variables | camelCase | outputFolder, singleTestRow |
| Parameters | camelCase | valueCreator, configurationFolderPath |
| Private constants | camelCase | private const int tickInterval = 10000; |
File Structure
- File-scoped namespaces (no braces):
namespace EnterpriseWebLibrary; usingdirectives at the top:Systemnamespaces first, then everything else in alphabetical order; oneusingper line; no blank lines between groups
Formatting
- Preserve non-ASCII characters like curly quotes -- do not convert to
straight quotes. LLMs may not be able to output some Unicode characters;
use PowerShell (e.g.
[char]0x201C) when needed. - Tabs for indentation
- Spaces inside parentheses:
( value ),( "text" ),( state ) - Spaces inside attribute brackets:
[ Test ],[ TestFixture ],[ DllImport( "kernel32" ) ] - Spaces inside angle brackets for generics are NOT used:
Func<Instant>,IReadOnlyCollection<T> - Opening brace on same line as declaration:
public class Foo { - Expression-bodied members for single-expression methods:
internal static Instant GetCurrentTime() => currentTimeGetter!(); - Multi-line argument lists: closing paren/brace on same line as last arg, or each arg on its own line indented with a tab
Type Patterns
- Nullable reference types enabled:
string?,Func<Instant>? - Strings should not be nullable unless
nullrepresents something distinct from the empty string. Usestringwith""as the default/empty value. Parameters that are optional strings should default to"", notnull. varused liberally for local variablespartial classused extensively for code-gen integrationIReadOnlyCollection<T>preferred overList<T>for return types- Tuples for multi-return values:
( bool secure, string host, int port, string path ) - Extension methods used heavily:
.ToCollection(),.Materialize(),.Any()
Error Handling
throw new Exception( "message" )for unexpected / invalid states- Custom exceptions:
UserCorrectableException,UnexpectedValueException,DoNotEmailOrLogException - Cleanup-on-failure pattern:
try { ... } catch { CleanUpStatics(); throw; } - Null-forgiving operator (
!) used when internal state is guaranteed post-init:currentTimeGetter!(). Also used on fields captured in lambdas before assignment to avoid nullable type inference:field!.ToCollection() - Do not replace calls to EWL/TEWL helper methods such as
.ToCollection(),.Materialize(),.Any()with raw language constructs likenew T[]or LINQ equivalents. Prefer fixing nullability with!or?on the receiver.
Comments
- XML doc comments (
///) on public API members with<summary>and<param>tags - Inline
//comments to explain "why", not "what" - Block comments (
/* */) used sparingly, mainly in tests
Project Dependencies
Dependencies are defined in Core\Core.csproj (for the main library) and in
each of the Providers\ projects.
The Ewl.Tools NuGet package (assembly name Tewl) provides low-level
utilities used throughout EWL such as IoMethods and
StringTools. Its source is at https://github.com/enduracode/tewl (integration branch).
Local TEWL Development
TEWL source: C:\Users\willi\Revision Control\EWL Dependencies\EnduraCode's TEWL\.
The outer directory is Mercurial; Shared\ is a git repo.
- Export to local feed: run
"Solution Files/Export Package to Local Feed.bat"in the outer TEWL directory - Local feed:
C:\Enterprise Web Library\Local NuGet Feed - After exporting, update the
Ewl.Toolsversion inCore\Core.csproj