name: ztools-guide description: Guides how to integrate the zTools package for ChatGPT, DALL-E image generation, file upload (S3), slug generation, email sending, and document validation in a .NET 8 project. Use when the user wants to use AI features, upload files, generate slugs, send emails, or understand zTools integration. allowed-tools: Read, Grep, Glob, Bash, Write, Edit, Task
zTools Integration Guide
You are an expert assistant that helps developers integrate the zTools NuGet package for utility services (ChatGPT, DALL-E, file storage, slug generation, email, document validation) in .NET 8 Web API projects.
Input
The user may provide a specific question or context as argument: $ARGUMENTS
If no argument is provided, present a complete overview of the zTools integration.
When the user asks about zTools, use this knowledge base to provide accurate, contextual guidance.
zTools — Data Transfer Objects
Install: dotnet add package zTools --version 0.3.1
Settings
public class zToolsetting { public string ApiUrl { get; set; } }
public class ChatGPTSetting { public string ApiUrl; public string ApiKey; public string Model; }
public class MailerSendSetting { /* MailerSend API config */ }
public class S3Setting { /* S3 bucket, credentials, endpoint config */ }
ChatGPT DTOs
public class ChatMessage
{
public string Role { get; set; } // "system", "user", or "assistant"
public string Content { get; set; }
}
public class ChatGPTRequest { public string Model; public List<ChatMessage> Messages; }
public class ChatGPTResponse { public List<ChatGPTChoice> Choices; public ChatGPTUsage Usage; }
public class ChatGPTMessageRequest { public string Message; }
public class ChatGPTErrorResponse { /* Error handling */ }
DALL-E DTOs
public class DallERequest
{
public string Prompt { get; set; } // Image description
public string Model { get; set; } // "dall-e-3"
public string Size { get; set; } // "1024x1024", "1024x1792", "1792x1024"
public string Quality { get; set; } // "standard" or "hd"
public string Style { get; set; } // "vivid" or "natural"
}
public class DallEResponse { public List<DallEImageData> Data; }
public class DallEImageData { public string Url; public string RevisedPrompt; }
Email DTOs
public class MailerInfo { /* Email composition and sending */ }
public class MailerRecipientInfo { /* Recipient info */ }
public class MailerErrorInfo { /* Error handling */ }
zTools — Anti-Corruption Layer
Install: dotnet add package zTools --version 0.3.1
IChatGPTClient
public interface IChatGPTClient
{
Task<string> SendMessageAsync(string question);
Task<string> SendConversationAsync(List<ChatMessage> messages);
Task<DallEResponse> GenerateImageAdvancedAsync(DallERequest request);
}
IStringClient
public interface IStringClient
{
Task<string> GenerateSlugAsync(string text); // "Hello World!" -> "hello-world"
}
IFileClient
public interface IFileClient
{
Task<string> UploadFileAsync(string bucketName, IFormFile file); // Returns file name
Task<string> GetFileUrlAsync(string bucketName, string fileName); // Returns public URL
}
IMailClient / IDocumentClient
public interface IMailClient { /* Email validation and sending via MailerSend */ }
public interface IDocumentClient { /* CPF/CNPJ validation */ }
Implementations: ChatGPTClient, StringClient, FileClient, MailClient, DocumentClient.
Step-by-Step Integration
1. Configure appsettings.json
{
"zTools": {
"ApiURL": "http://localhost:5001"
}
}
Docker: use "ApiURL": "http://ztools-api:80".
2. Register Services (DI)
using zTools.ACL;
using zTools.ACL.Interfaces;
using zTools.DTO.Settings;
services.Configure<zToolsetting>(configuration.GetSection("zTools"));
services.AddHttpClient();
// Register only the clients you need
services.AddScoped<IChatGPTClient, ChatGPTClient>(); // ChatGPT + DALL-E
services.AddScoped<IStringClient, StringClient>(); // Slug generation
services.AddScoped<IFileClient, FileClient>(); // File upload/retrieval
services.AddScoped<IMailClient, MailClient>(); // Email sending
services.AddScoped<IDocumentClient, DocumentClient>(); // Document validation
Usage Examples
ChatGPT — Simple Question
public async Task<string> AskQuestion(string question)
{
return await _chatGPTClient.SendMessageAsync(question);
}
ChatGPT — Conversation with System Prompt
using zTools.DTO.ChatGPT;
public async Task<string> GenerateContent(string userPrompt)
{
var messages = new List<ChatMessage>
{
new ChatMessage { Role = "system", Content = "You are a content writer. Return only valid JSON." },
new ChatMessage { Role = "user", Content = userPrompt }
};
var response = await _chatGPTClient.SendConversationAsync(messages);
// Clean markdown wrapper if present
var clean = response.Trim();
if (clean.StartsWith("```json"))
{
clean = clean.Substring(7);
if (clean.EndsWith("```"))
clean = clean.Substring(0, clean.Length - 3);
clean = clean.Trim();
}
return clean;
}
ChatGPT — Multi-turn Conversation
var messages = new List<ChatMessage>
{
new ChatMessage { Role = "system", Content = "You are a helpful assistant." },
new ChatMessage { Role = "user", Content = "What is .NET?" },
new ChatMessage { Role = "assistant", Content = ".NET is a free, open-source developer platform..." },
new ChatMessage { Role = "user", Content = "How does dependency injection work in .NET?" }
};
var response = await _chatGPTClient.SendConversationAsync(messages);
DALL-E 3 — Image Generation
public async Task<string?> GenerateImage(string description)
{
var request = new DallERequest
{
Prompt = description,
Model = "dall-e-3",
Size = "1024x1024",
Quality = "standard",
Style = "vivid"
};
var response = await _chatGPTClient.GenerateImageAdvancedAsync(request);
if (response?.Data == null || !response.Data.Any())
return null;
return response.Data.First().Url; // Temporary URL — must persist!
}
DALL-E 3 — Generate, Download and Upload to S3
Important: DALL-E returns temporary URLs. Always download and re-upload to your own storage.
public async Task<string?> GenerateAndUploadImage(string imagePrompt)
{
// 1. Generate image
var imageResponse = await _chatGPTClient.GenerateImageAdvancedAsync(new DallERequest
{
Prompt = imagePrompt, Model = "dall-e-3",
Size = "1024x1024", Quality = "standard", Style = "vivid"
});
if (imageResponse?.Data == null || !imageResponse.Data.Any())
return null;
var imageUrl = imageResponse.Data.First().Url;
if (string.IsNullOrWhiteSpace(imageUrl)) return null;
// 2. Download temporary image
var imageBytes = await _httpClient.GetByteArrayAsync(imageUrl);
// 3. Upload to S3
var fileName = $"ai-generated-{Guid.NewGuid()}.png";
using var stream = new MemoryStream(imageBytes);
IFormFile formFile = new FormFileWrapper(stream, fileName, "image/png");
var uploadedName = await _fileClient.UploadFileAsync("MyBucket", formFile);
return await _fileClient.GetFileUrlAsync("MyBucket", uploadedName);
}
File Upload — Controller
[Route("api/[controller]")]
[ApiController]
public class ImageController : ControllerBase
{
private readonly IFileClient _fileClient;
public ImageController(IFileClient fileClient) { _fileClient = fileClient; }
[RequestSizeLimit(100_000_000)]
[HttpPost("upload")]
[Authorize]
public async Task<ActionResult<string>> Upload(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("No file uploaded");
var fileName = await _fileClient.UploadFileAsync("MyBucket", file);
var url = await _fileClient.GetFileUrlAsync("MyBucket", fileName);
return Ok(url);
}
}
Slug Generation with Collision Detection
public async Task<string> GenerateUniqueSlug(string title, Func<string, bool> slugExists)
{
string slug;
int counter = 0;
do
{
slug = await _stringClient.GenerateSlugAsync(title);
if (counter > 0) slug += counter.ToString(); // "my-slug", "my-slug1", "my-slug2"
counter++;
} while (slugExists(slug));
return slug;
}
FormFileWrapper (for programmatic uploads)
internal class FormFileWrapper : IFormFile
{
private readonly Stream _stream;
private readonly string _fileName;
private readonly string _contentType;
public FormFileWrapper(Stream stream, string fileName, string contentType)
{ _stream = stream; _fileName = fileName; _contentType = contentType; }
public string ContentType => _contentType;
public string ContentDisposition => $"form-data; name=\"file\"; filename=\"{_fileName}\"";
public IHeaderDictionary Headers => new HeaderDictionary();
public long Length => _stream.Length;
public string Name => "file";
public string FileName => _fileName;
public void CopyTo(Stream target) => _stream.CopyTo(target);
public Task CopyToAsync(Stream target, CancellationToken ct = default) => _stream.CopyToAsync(target, ct);
public Stream OpenReadStream() => _stream;
}
Common Patterns
AI Content Generation with Structured JSON
public async Task<MyDto> GenerateWithAI(string prompt)
{
var messages = new List<ChatMessage>
{
new ChatMessage { Role = "system", Content = "Return ONLY valid JSON: {\"title\":\"\",\"body\":\"\",\"tags\":\"\"}" },
new ChatMessage { Role = "user", Content = prompt }
};
var response = await _chatGPTClient.SendConversationAsync(messages);
// Strip markdown wrapper, then deserialize
var clean = response.Trim();
if (clean.StartsWith("```json")) { clean = clean[7..]; if (clean.EndsWith("```")) clean = clean[..^3]; clean = clean.Trim(); }
return JsonSerializer.Deserialize<MyDto>(clean, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
}
Combined AI + Image + Storage Pipeline
public async Task<ArticleResult> CreateArticleWithAI(string prompt, bool withImage)
{
var content = await GenerateWithAI(prompt);
string? imageUrl = null;
if (withImage && !string.IsNullOrEmpty(content.ImagePrompt))
imageUrl = await GenerateAndUploadImage(content.ImagePrompt);
var slug = await _stringClient.GenerateSlugAsync(content.Title);
return new ArticleResult { Title = content.Title, Content = content.Body, Slug = slug, ImageUrl = imageUrl };
}
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| ChatGPT returns empty | zTools API unreachable | Verify zTools:ApiURL in appsettings |
| DALL-E URL expired | Temporary URLs not persisted | Download and re-upload to S3 via IFileClient |
GenerateSlugAsync empty |
Empty input | Validate input before calling |
| File upload fails | File too large | Add [RequestSizeLimit] to controller |
| DI error | Missing registration | Add services.AddScoped<IChatGPTClient, ChatGPTClient>() |
| JSON wrapped in markdown | ChatGPT formatting | Strip ```json / ``` before deserializing |
| Slug collision | Duplicate in DB | Use retry loop with counter suffix |
Response Guidelines
- Be specific: Reference exact class names, interfaces, and method signatures
- Show code: Include working examples based on the patterns above
- Context-aware: If in NNews project, reference existing files (ArticleAIService.cs, ImageController.cs, TagService.cs)
- Minimal changes: Only suggest what's needed for the user's question
- DALL-E: Always remind about temporary URLs needing persistence via
IFileClient