465 lines
12 KiB
Markdown
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");
|
|
});
|
|
```
|