Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

3. PDF Generation and Email Delivery

Scenario: Generating PDF documents and sending via email for charging station work orders.


public async Task<WorkOrderFormResponse?> SendEmailToSonwin(WorkOrderFormResponse workOrder)
{
    // 1. Build email model with localized data
    EmailModel emailModel = new EmailModel
    {
        Tilmelding = new Registration
        {
            WorkOrderNumber = workOrder.WorkOrderNumber,
            GridCompanyName = workOrder.GridCompany.Name,
            // ... additional mapping
        },
        // ... other sections
    };
    
    // 2. Generate PDF using QuestPDF
    var pdf = Generate(emailModel, title: $"Blanket – {workOrder.WorkOrderNumber}");
    
    // 3. Send email with PDF attachment
    var sendmail = await _emailService.SendEmailAsync(email, subject, body, pdf, fileName);
    
    if (sendmail)
    {
        // Update work order status
        workOrder.WorkOrderStatusID = (int)Enums.WorkOrderStatus.RegistrationSent;
        await _dbContext.SaveChangesAsync();
    }
    
    return workOrder;
}


Key Technical Aspects:


•    Dynamic PDF Generation: QuestPDF for complex document layouts
•    Internationalization: Localized content in generated documents
•    Email Integration: SendGrid for reliable email delivery
•    File Management: Temporary file handling for attachments


4. Complex Query Optimization

Scenario: Retrieving work orders with extensive related data for display.


public async Task<IEnumerable<WorkOrderExtendedResponse>> GetWorkOrders()
{
    var consumptionCategories = await _dbContext.ConsumptionCategory
        .ToDictionaryAsync(cc => cc.ID, cc => cc.Name ?? "");
    
    return await _dbContext.WorkOrder
        .Select(wo => new WorkOrderExtendedResponse
        {
            ID = wo.ID,
            WorkOrderNumber = wo.WorkOrderNumber,
            LocationAddress = FormatLocationAddress(wo.Location),
            ConsumptionCategoryName = _dbContext.InstallationCategory
                .Where(ic => ic.WorkOrderID == wo.ID)
                .Select(ic => ic.ConsumptionCategoryID != null && 
                    consumptionCategories.ContainsKey(ic.ConsumptionCategoryID.Value) 
                    ? consumptionCategories[ic.ConsumptionCategoryID.Value] : "")
                .FirstOrDefault(),
            // ... complex projections
        }).ToListAsync();
}


Key Technical Aspects:
•    Query Optimization: Dictionary lookup to reduce database queries
•    Complex Projections: Direct projection to response models
•    Performance: AsNoTracking for read-only scenarios


5. Multi-Language Utilization Management


Scenario: Dynamic form rendering based on utilization item types with validation.


Key Technical Aspects:
•    Dynamic UI: Conditional rendering based on enum values
•    Validation: FluentValidation with localized error messages
•    State Management: Complex form state in Blazor components


6. Azure Blob Storage Integration


Scenario: File upload handling with size limits and validation.

public async Task<FileUploadResponse> UploadFileAsync(IFormFile file, string containerName)
{
    // Validation
    if (file.Length > 52_428_800) // 50MB
        throw new InvalidOperationException("File too large");
    
    // Upload to Azure Blob Storage
    var blobClient = _blobServiceClient.GetBlobContainerClient(containerName);
    await blobClient.CreateIfNotExistsAsync(PublicAccessType.Blob);
    
    var blob = blobClient.GetBlobClient(fileName);
    await blob.UploadAsync(file.OpenReadStream(), true);
    
    return new FileUploadResponse { Url = blob.Uri.ToString() };
}


Key Technical Aspects:
•    File Size Validation: Configurable limits for uploads
•    Container Management: Dynamic container creation
•    Stream Handling: Efficient file streaming to Azure