# ViewEngine.Client Usage Examples ## Table of Contents - [Basic Usage](#basic-usage) - [ASP.NET Core Integration](#aspnet-core-integration) - [Console Application](#console-application) - [Advanced Scenarios](#advanced-scenarios) ## Basic Usage ### Simple Web Page Retrieval ```csharp using ViewEngine.Client; using ViewEngine.Client.Models; // Create client var client = new ViewEngineClient("ak_your-api-key-here"); // Retrieve a page var request = new SubmitRetrievalRequest { Url = "https://example.com" }; var pageData = await client.RetrieveAndWaitAsync(request); Console.WriteLine($"Title: {pageData.Title}"); Console.WriteLine($"Body: {pageData.Body}"); Console.WriteLine($"Found {pageData.Routes.Count} navigation links"); ``` ### Manual Polling ```csharp // Submit request var submitResponse = await client.SubmitRetrievalAsync(new SubmitRetrievalRequest { Url = "https://example.com", TimeoutSeconds = 60, Priority = 5 }); Console.WriteLine($"Request ID: {submitResponse.RequestId}"); Console.WriteLine($"Status: {submitResponse.Status}"); // Poll for completion while (true) { var status = await client.GetRetrievalStatusAsync(submitResponse.RequestId); Console.WriteLine($"Current status: {status.Status}"); if (status.Status == "complete") { var content = await client.GetPageContentAsync(submitResponse.RequestId); Console.WriteLine($"Title: {content.Title}"); break; } else if (status.Status == "failed") { Console.WriteLine($"Failed: {status.Error}"); break; } await Task.Delay(2000); // Poll every 2 seconds } ``` ## ASP.NET Core Integration ### Minimal API Example **Program.cs:** ```csharp using ViewEngine.Client; using ViewEngine.Client.Extensions; using ViewEngine.Client.Models; var builder = WebApplication.CreateBuilder(args); // Add ViewEngine client from configuration builder.Services.AddViewEngineClient(builder.Configuration); var app = builder.Build(); // Simple endpoint app.MapGet("/retrieve/{url}", async (string url, ViewEngineClient client) => { var request = new SubmitRetrievalRequest { Url = url }; var pageData = await client.RetrieveAndWaitAsync(request); return Results.Ok(new { pageData.Title, pageData.Url, LinkCount = pageData.Routes.Count + pageData.BodyRoutes.Count }); }); // Endpoint with custom parameters app.MapPost("/retrieve", async (SubmitRetrievalRequest request, ViewEngineClient client) => { var pageData = await client.RetrieveAndWaitAsync(request); return Results.Ok(pageData); }); app.Run(); ``` **appsettings.json:** ```json { "ViewEngine": { "ApiKey": "ak_your-api-key-here", "BaseUrl": "https://www.viewengine.io/api/v1", "TimeoutSeconds": 120, "MaxRetries": 3, "DefaultPollingIntervalMs": 2000 } } ``` ### Controller Example ```csharp using Microsoft.AspNetCore.Mvc; using ViewEngine.Client; using ViewEngine.Client.Models; [ApiController] [Route("api/[controller]")] public class WebPagesController : ControllerBase { private readonly ViewEngineClient _client; private readonly ILogger _logger; public WebPagesController(ViewEngineClient client, ILogger logger) { _client = client; _logger = logger; } [HttpPost("retrieve")] public async Task> RetrievePage([FromBody] SubmitRetrievalRequest request) { try { _logger.LogInformation("Retrieving page: {Url}", request.Url); var pageData = await _client.RetrieveAndWaitAsync(request); return Ok(pageData); } catch (Exception ex) { _logger.LogError(ex, "Failed to retrieve page: {Url}", request.Url); return StatusCode(500, new { error = ex.Message }); } } [HttpGet("status/{requestId}")] public async Task> GetStatus(Guid requestId) { var status = await _client.GetRetrievalStatusAsync(requestId); return Ok(status); } } ``` ## Console Application ### Full Featured Console App ```csharp using System; using System.Threading.Tasks; using ViewEngine.Client; using ViewEngine.Client.Models; class Program { static async Task Main(string[] args) { // Get API key from environment variable or args var apiKey = Environment.GetEnvironmentVariable("VIEWENGINE_API_KEY") ?? args.FirstOrDefault() ?? throw new Exception("API key required"); using var client = new ViewEngineClient(apiKey); Console.WriteLine("ViewEngine Client Demo"); Console.WriteLine("======================"); while (true) { Console.Write("\nEnter URL to retrieve (or 'quit' to exit): "); var url = Console.ReadLine(); if (string.IsNullOrWhiteSpace(url) || url.Equals("quit", StringComparison.OrdinalIgnoreCase)) break; await RetrievePageAsync(client, url); } } static async Task RetrievePageAsync(ViewEngineClient client, string url) { try { Console.WriteLine($"\nRetrieving: {url}"); var request = new SubmitRetrievalRequest { Url = url, TimeoutSeconds = 60, Priority = 5 }; var submitResponse = await client.SubmitRetrievalAsync(request); Console.WriteLine($"Request ID: {submitResponse.RequestId}"); Console.WriteLine($"Status: {submitResponse.Status}"); // Poll for completion RetrievalStatusResponse status; do { await Task.Delay(2000); status = await client.GetRetrievalStatusAsync(submitResponse.RequestId); Console.WriteLine($"Status: {status.Status} - {status.Message}"); } while (status.Status == "queued" || status.Status == "processing"); if (status.Status == "complete") { var pageData = await client.GetPageContentAsync(submitResponse.RequestId); Console.WriteLine($"\n--- Page Data ---"); Console.WriteLine($"Title: {pageData.Title}"); Console.WriteLine($"URL: {pageData.Url}"); Console.WriteLine($"Meta Description: {pageData.MetaDescription}"); Console.WriteLine($"Body Length: {pageData.Body?.Length ?? 0} characters"); Console.WriteLine($"\n--- Navigation Links ({pageData.Routes.Count}) ---"); foreach (var link in pageData.Routes.Take(5)) { Console.WriteLine($" [{link.Rank}] {link.Text} -> {link.Url}"); } Console.WriteLine($"\n--- Body Links ({pageData.BodyRoutes.Count}) ---"); foreach (var link in pageData.BodyRoutes.Take(5)) { var adMarker = link.IsPotentialAd ? "[AD] " : ""; Console.WriteLine($" {adMarker}[{link.Rank}] {link.Text} -> {link.Url}"); } } else { Console.WriteLine($"\nRetrieval failed: {status.Error}"); } } catch (Exception ex) { Console.WriteLine($"\nError: {ex.Message}"); } } } ``` ## Advanced Scenarios ### Client Management ```csharp // Add a new client var addRequest = new AddClientRequest { Email = "feeder@example.com", Alias = "Production Feeder #1", CustomUserId = "prod-feeder-001", DailyMaximum = 1000 }; var client = await viewEngineClient.AddClientAsync(addRequest); Console.WriteLine($"Added client: {client.Id}"); // Route job to this specific client var retrievalRequest = new SubmitRetrievalRequest { Url = "https://example.com", ClientId = client.Id // Use the client's ID }; // Or use custom user ID var retrievalRequest2 = new SubmitRetrievalRequest { Url = "https://example.com", CustomUserId = "prod-feeder-001" }; // List all clients var clients = await viewEngineClient.GetClientsAsync(); foreach (var c in clients) { Console.WriteLine($"{c.Alias}: {(c.FeederOnline ? "Online" : "Offline")}"); Console.WriteLine($" Jobs today: {c.JobsProcessedToday}/{c.DailyMaximum}"); } // Get client statistics var stats = await viewEngineClient.GetClientStatsAsync(client.Id); Console.WriteLine($"Total jobs: {stats.TotalJobsProcessed}"); Console.WriteLine($"Success rate: {stats.SuccessRate:F2}%"); Console.WriteLine($"Avg processing time: {stats.AverageProcessingTimeMs:F0}ms"); // Update client settings await viewEngineClient.UpdateClientAsync(client.Id, new UpdateClientRequest { DailyMaximum = 2000, Alias = "Production Feeder #1 (Updated)" }); // Suspend client await viewEngineClient.SuspendClientAsync(client.Id); // Reactivate await viewEngineClient.ActivateClientAsync(client.Id); // Delete client await viewEngineClient.DeleteClientAsync(client.Id); ``` ### Platform-Specific Retrieval ```csharp // Request page to be rendered on specific platform var request = new SubmitRetrievalRequest { Url = "https://example.com", PreferredPlatform = "Windows" // or "Android", "iOS" }; var pageData = await client.RetrieveAndWaitAsync(request); ``` ### High Priority Jobs ```csharp var request = new SubmitRetrievalRequest { Url = "https://example.com", Priority = 10, // Highest priority (1-10) TimeoutSeconds = 300 // Max 5 minutes }; ``` ### Batch Processing ```csharp var urls = new[] { "https://example.com", "https://another-example.com", "https://third-example.com" }; // Submit all requests var submitTasks = urls.Select(url => client.SubmitRetrievalAsync(new SubmitRetrievalRequest { Url = url, Priority = 5 })); var submitResponses = await Task.WhenAll(submitTasks); // Wait for all to complete var tasks = submitResponses.Select(async response => { while (true) { var status = await client.GetRetrievalStatusAsync(response.RequestId); if (status.Status == "complete") { return await client.GetPageContentAsync(response.RequestId); } else if (status.Status == "failed") { throw new Exception($"Failed to retrieve {status.Url}"); } await Task.Delay(2000); } }); var results = await Task.WhenAll(tasks); foreach (var pageData in results) { Console.WriteLine($"{pageData.Title} - {pageData.Url}"); } ``` ### Error Handling ```csharp try { var pageData = await client.RetrieveAndWaitAsync(request); } catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.Unauthorized) { Console.WriteLine("Invalid API key"); } catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.TooManyRequests) { Console.WriteLine("Rate limit exceeded"); } catch (InvalidOperationException ex) when (ex.Message.Contains("failed")) { Console.WriteLine($"Retrieval failed: {ex.Message}"); } catch (OperationCanceledException) { Console.WriteLine("Request was canceled"); } catch (Exception ex) { Console.WriteLine($"Unexpected error: {ex.Message}"); } ``` ### Custom Timeout and Retry Settings ```csharp var options = new ViewEngineOptions { ApiKey = "ak_your-api-key-here", TimeoutSeconds = 180, // 3 minutes MaxRetries = 5, BaseDelayMs = 500, DefaultPollingIntervalMs = 1000 // Poll every second }; using var client = new ViewEngineClient(options); ``` ### Dependency Injection with Multiple Clients ```csharp // Configure multiple named clients builder.Services.AddHttpClient("Primary") .ConfigureHttpClient((sp, client) => { client.BaseAddress = new Uri("https://www.viewengine.io/api/v1"); client.DefaultRequestHeaders.Add("X-API-Key", "ak_primary_key"); }); builder.Services.AddHttpClient("Secondary") .ConfigureHttpClient((sp, client) => { client.BaseAddress = new Uri("https://www.viewengine.io/api/v1"); client.DefaultRequestHeaders.Add("X-API-Key", "ak_secondary_key"); }); ```