viewengine.client/Examples.md

465 lines
12 KiB
Markdown

# 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<WebPagesController> _logger;
public WebPagesController(ViewEngineClient client, ILogger<WebPagesController> logger)
{
_client = client;
_logger = logger;
}
[HttpPost("retrieve")]
public async Task<ActionResult<PageData>> 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<ActionResult<RetrievalStatusResponse>> 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<ViewEngineClient>("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<ViewEngineClient>("Secondary")
.ConfigureHttpClient((sp, client) =>
{
client.BaseAddress = new Uri("https://www.viewengine.io/api/v1");
client.DefaultRequestHeaders.Add("X-API-Key", "ak_secondary_key");
});
```