- Регистрация
- 9 Май 2015
- Сообщения
- 1,477
- Баллы
- 155
This is probably the most exciting web update we’ve had in WebBroker since Delphi 6. The WebStencils enhancements in RAD Studio 13.0 Florence are so significant, I’d almost call this a 2.0 version.
If you’ve been building web applications with RAD Studio’s WebStencils template engine, you’re going to love what we’ve packed into this release. We’ve taken community feedback and added features that make web development with Delphi and C++Builder more productive and enjoyable than ever.
Table of Contents
What is WebStencils?
For the ones who haven’t heard about it yet, WebStencils is Embarcadero’s template engine that works with both WebBroker and RAD Server, letting you build dynamic web applications using familiar Delphi or C++ syntax alongside HTML templates. The beauty is in its simplicity: you get the power of server-side rendering without learning entirely new frameworks.
The Major New Features
Complete Session Management & Authentication
As discussed in our , this was the most requested feature from the community. introduces a complete session and authentication system that works out of the box with just three components:
New Components:
Drop these three components on your WebModule, and you handle all website security with almost zero code. The authentication flow is straightforward:
Session data automatically becomes available in templates through the @session object:
@if session.Authenticated { <div>Welcome back, @session.UserName!</div> } @if session.UserHasRole('admin') { <a href="/admin">Admin Panel</a> }
The TWebSessionManager gives you full control:
Role-based authorization zones are just as simple:
// Protect admin areas - only users with 'admin' role can access /admin/* Zone.PathInfo := '/admin*'; Zone.Kind := zkProtected; Zone.Roles := 'admin';
Database-Driven UI Generation
This feature fundamentally changes how you can build web forms. WebStencils now gives you access to dataset properties and field metadata, meaning your database schema can generate your UI:
<!-- Dynamic forms that adapt to any dataset --> @foreach field in customers.fields { <div class="form-group"> <label>@field.DisplayLabel</label> @switch(field.dataType) { @case "ftString" { <input type="text" name="@field.FieldName" maxlength="@field.Size" class="form-control"> } @case "ftInteger" { <input type="number" name="@field.FieldName" class="form-control"> } @case "ftDate" { <input type="date" name="@field.FieldName" class="form-control"> } } </div> }
Imagine changing a field’s Visible property in FireDAC Field Editor and having it automatically appear in your web form, without touching a line of HTML.
Built-in Security
The new security whitelist system prevents accidental exposure of sensitive data. By default, a list of common safe properties is already whitelisted for the classes TStrings and TDataset, but this is easily customizable based on the project requirements.
// Add custom properties to the whitelist TWebStencilsProcessor.Whitelist.Configure(TMyClass,['SafeProperty'], nil, False); // Block specific properties TWebStencilsProcessor.Whitelist.Configure(TDataSet, nil, ['ConnectionString'], False);
The @switch Operator
The new @switch operator makes conditional rendering cleaner, avoiding messy nested @if statements:
@switch(user.role) { @case "admin" { <div class="admin-panel"> <h2>Admin Dashboard</h2> </div> } @case "moderator" { <div class="mod-tools"> <h2>Moderator Tools</h2> </div> } @default { <div class="user-content"> <h2>Welcome, User!</h2> </div> } }
Custom Data Access
Add custom variables using anonymous methods for better adaptability:
// Add custom variables using a simple dictionary type TMap = TDictionary<string, string>; ... LDict := TMap.Create; LDict.Add('APP_VERSION', '1.0.0'); LDict.Add('DEBUG_MODE', 'True'); WebStencilsEngine.AddVar('env', LDict, True, function(AVar: TWebStencilsDataVar; const APropName: string; var AValue: string): Boolean begin Result := TMap(AVar.TheObject).TryGetValue(APropName.ToUpper, AValue); end);
Then in templates:
<h1>@env.APP_NAME - @env.APP_VERSION</h1> @if env.DEBUG_MODE { <div class="alert-warning">Debug mode is active</div> }
Additional Enhancements
Check out our updated featuring:
The demos work with SQLite and in-memory data sources, showing WebStencils’ versatility across different storage strategies.
Ready to test it?
The learning curve is gentle, and existing WebStencils templates work unchanged. New features are additive, so you can adopt them at your own pace while immediately benefiting from automatic session integration and security improvements.
Get started with RAD Studio 13.0 Florence (Delphi or C++Builder), clone the , and explore the examples. We’re looking forward to seeing what you build with these new features.
Questions or feedback? The section is the best place to reach us. Star the repo and let us know what you think!
If you’ve been building web applications with RAD Studio’s WebStencils template engine, you’re going to love what we’ve packed into this release. We’ve taken community feedback and added features that make web development with Delphi and C++Builder more productive and enjoyable than ever.
Table of Contents
What is WebStencils?
For the ones who haven’t heard about it yet, WebStencils is Embarcadero’s template engine that works with both WebBroker and RAD Server, letting you build dynamic web applications using familiar Delphi or C++ syntax alongside HTML templates. The beauty is in its simplicity: you get the power of server-side rendering without learning entirely new frameworks.
The Major New Features
Complete Session Management & Authentication
As discussed in our , this was the most requested feature from the community. introduces a complete session and authentication system that works out of the box with just three components:
New Components:
- TWebSessionManager – Manages session lifecycle with configurable options
- TWebFormsAuthenticator – HTML form-based authentication with automatic redirects
- TWebAuthorizer – Role-based access control with authorization zones
Drop these three components on your WebModule, and you handle all website security with almost zero code. The authentication flow is straightforward:
- Unauthenticated requests ➜ Redirect to LoginURL
- User POSTs credentials ➜ OnAuthenticate event validates
- Success ➜ Redirect to original URL or HomeURL
- Failure ➜ Redirect to FailedURL
Session data automatically becomes available in templates through the @session object:
@if session.Authenticated { <div>Welcome back, @session.UserName!</div> } @if session.UserHasRole('admin') { <a href="/admin">Admin Panel</a> }
@if session.Authenticated { <div>Welcome back, @session.UserName!</div> @if session.UserHasRole('admin') { <a href="/admin">Admin Panel</a> |
The TWebSessionManager gives you full control:
- Session ID Storage: Cookies (default), headers, or query parameters
- Session Scope: Per request, per user, or per user+IP
- Security: Built-in shared secret for user-scoped sessions
- Timeout: Configurable expiration (default: 1 hour)
Role-based authorization zones are just as simple:
// Protect admin areas - only users with 'admin' role can access /admin/* Zone.PathInfo := '/admin*'; Zone.Kind := zkProtected; Zone.Roles := 'admin';
// Protect admin areas - only users with 'admin' role can access /admin/* Zone.PathInfo := '/admin*'; Zone.Kind := zkProtected; Zone.Roles := 'admin'; |
This feature fundamentally changes how you can build web forms. WebStencils now gives you access to dataset properties and field metadata, meaning your database schema can generate your UI:
<!-- Dynamic forms that adapt to any dataset --> @foreach field in customers.fields { <div class="form-group"> <label>@field.DisplayLabel</label> @switch(field.dataType) { @case "ftString" { <input type="text" name="@field.FieldName" maxlength="@field.Size" class="form-control"> } @case "ftInteger" { <input type="number" name="@field.FieldName" class="form-control"> } @case "ftDate" { <input type="date" name="@field.FieldName" class="form-control"> } } </div> }
<!-- Dynamic forms that adapt to any dataset --> @foreach field in customers.fields { <div class="form-group"> <label>@field.DisplayLabel</label> @switch(field.dataType) { @case "ftString" { <input type="text" name="@field.FieldName" maxlength="@field.Size" class="form-control"> } @case "ftInteger" { <input type="number" name="@field.FieldName" class="form-control"> } @case "ftDate" { <input type="date" name="@field.FieldName" class="form-control"> } </div> |
Imagine changing a field’s Visible property in FireDAC Field Editor and having it automatically appear in your web form, without touching a line of HTML.
Built-in Security
The new security whitelist system prevents accidental exposure of sensitive data. By default, a list of common safe properties is already whitelisted for the classes TStrings and TDataset, but this is easily customizable based on the project requirements.
// Add custom properties to the whitelist TWebStencilsProcessor.Whitelist.Configure(TMyClass,['SafeProperty'], nil, False); // Block specific properties TWebStencilsProcessor.Whitelist.Configure(TDataSet, nil, ['ConnectionString'], False);
// Add custom properties to the whitelist TWebStencilsProcessor.Whitelist.Configure(TMyClass,['SafeProperty'], nil, False); // Block specific properties TWebStencilsProcessor.Whitelist.Configure(TDataSet, nil, ['ConnectionString'], False); |
The new @switch operator makes conditional rendering cleaner, avoiding messy nested @if statements:
@switch(user.role) { @case "admin" { <div class="admin-panel"> <h2>Admin Dashboard</h2> </div> } @case "moderator" { <div class="mod-tools"> <h2>Moderator Tools</h2> </div> } @default { <div class="user-content"> <h2>Welcome, User!</h2> </div> } }
@switch(user.role) { @case "admin" { <div class="admin-panel"> <h2>Admin Dashboard</h2> </div> @case "moderator" { <div class="mod-tools"> <h2>Moderator Tools</h2> </div> @default { <div class="user-content"> <h2>Welcome, User!</h2> </div> |
Add custom variables using anonymous methods for better adaptability:
// Add custom variables using a simple dictionary type TMap = TDictionary<string, string>; ... LDict := TMap.Create; LDict.Add('APP_VERSION', '1.0.0'); LDict.Add('DEBUG_MODE', 'True'); WebStencilsEngine.AddVar('env', LDict, True, function(AVar: TWebStencilsDataVar; const APropName: string; var AValue: string): Boolean begin Result := TMap(AVar.TheObject).TryGetValue(APropName.ToUpper, AValue); end);
// Add custom variables using a simple dictionary TMap = TDictionary<string, string>; LDict := TMap.Create; LDict.Add('APP_VERSION', '1.0.0'); LDict.Add('DEBUG_MODE', 'True'); WebStencilsEngine.AddVar('env', LDict, True, function(AVar: TWebStencilsDataVar; const APropName: string; var AValue: string): Boolean Result := TMap(AVar.TheObject).TryGetValue(APropName.ToUpper, AValue); |
Then in templates:
<h1>@env.APP_NAME - @env.APP_VERSION</h1> @if env.DEBUG_MODE { <div class="alert-warning">Debug mode is active</div> }
<h1>@env.APP_NAME - @env.APP_VERSION</h1> @if env.DEBUG_MODE { <div class="alert-warning">Debug mode is active</div> |
- Better Layout System: Nested @ExtraHeader support for complex layout hierarchies
- Improved @page Object: Access to request_path and request_segment for better URL handling
- Docker Support: Ready-to-go containerization with automatic database initialization
Check out our updated featuring:
- Complete authentication system with role-based navigation
- Dynamic form generation from database metadata
- Session-based flash messaging
- Advanced search and pagination using FireDAC
- Examples in both Delphi and C++Builder
The demos work with SQLite and in-memory data sources, showing WebStencils’ versatility across different storage strategies.
Ready to test it?
The learning curve is gentle, and existing WebStencils templates work unchanged. New features are additive, so you can adopt them at your own pace while immediately benefiting from automatic session integration and security improvements.
Get started with RAD Studio 13.0 Florence (Delphi or C++Builder), clone the , and explore the examples. We’re looking forward to seeing what you build with these new features.
Questions or feedback? The section is the best place to reach us. Star the repo and let us know what you think!
Источник: