Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: CI

on:
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'

- name: Cache NuGet packages
uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
restore-keys: |
${{ runner.os }}-nuget-

- name: Restore dependencies
run: dotnet restore
working-directory: src

- name: Check formatting
run: dotnet format --verify-no-changes --verbosity diagnostic
working-directory: src

- name: Build
run: dotnet build --no-restore
working-directory: src

- name: Test
run: dotnet test --no-build --verbosity normal
working-directory: src
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ Learn more on our [Anvil developer page](https://www.useanvil.com/developers/).
Using the `dotnet` CLI:

```bash
$ dotnet add package Anvil --version 0.5.0
$ dotnet add package Anvil --version 0.6.0
```

Add as a package reference:

```xml
<ItemGroup>
<PackageReference Include="Anvil" Version="0.5.0" />
<PackageReference Include="Anvil" Version="0.6.0" />
</ItemGroup>
```

Expand Down Expand Up @@ -109,9 +109,9 @@ class Program

Fills a PDF template with your JSON data.

First, you will need to have [uploaded a PDF to Anvil](https://useanvil.com/docs/api/fill-pdf#creating-a-pdf-template). You can find the PDF template's id on the `API Info` tab of your PDF template's page:
First, you will need to have [uploaded a PDF to Anvil](https://useanvil.com/docs/api/fill-pdf#creating-a-pdf-template). You can find the PDF template's ID on your PDF template's page:

<img width="725" alt="pdf-template-id" src="https://user-images.githubusercontent.com/69169/73693549-4a598280-468b-11ea-81a3-5df4472de8a4.png">
![Find your PDF Template ID](./images/template%20eid.webp)

An example:

Expand Down
Binary file added images/template eid.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 8 additions & 3 deletions src/Anvil/Anvil.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

<PropertyGroup>
<Authors>useanvil.com, Allan Almazan</Authors>
<TargetFrameworks>net5.0;netstandard2.0;net461</TargetFrameworks>
<PackageVersion>0.5.0</PackageVersion>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageVersion>0.6.0</PackageVersion>
<PackageId>Anvil</PackageId>
<Version>0.5.0</Version>
<Version>0.6.0</Version>
<Company>useanvil.com</Company>
<PackageTags>PDF;Anvil</PackageTags>
<Description>.NET/C# API client for Anvil. https://www.useanvil.com/docs</Description>
Expand All @@ -18,10 +18,15 @@
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<InternalsVisibleTo Include="AnvilTests" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="GraphQL.Client" Version="4.0.2" />
<PackageReference Include="GraphQL.Client.Serializer.Newtonsoft" Version="4.0.2" />
<PackageReference Include="GraphQL.Client.Serializer.SystemTextJson" Version="4.0.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<None Include="../../README.md" Pack="true" PackagePath="/" />
<None Include="../../images/icon.png" Pack="true" PackagePath="/images" />
</ItemGroup>
Expand Down
10 changes: 10 additions & 0 deletions src/Anvil/Client/BaseClient.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
using System;
using System.Collections.Generic;
using System.Net;

namespace Anvil
{
public class AnvilClientException : Exception
{
public HttpStatusCode? HttpStatusCode { get; set; }
public Dictionary<string, IEnumerable<string>>? ResponseHeaders { get; set; }
public string? ResponseContent { get; set; }

public AnvilClientException(string message) : base(message)
{
}

public AnvilClientException(string message, Exception innerException) : base(message, innerException)
{
}
}

public abstract class BaseClient
Expand Down
86 changes: 71 additions & 15 deletions src/Anvil/Client/GraphQLClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
Expand All @@ -16,9 +17,10 @@

namespace Anvil.Client
{
public class GraphQLClient : BaseClient
public class GraphQLClient : BaseClient, IDisposable
{
private readonly GraphQLHttpClient _graphQlHttpClient;
private bool _disposed;

public GraphQLClient(string apiKey)
{
Expand Down Expand Up @@ -96,37 +98,82 @@ private async Task<TResponse> SendQuery<TResponse>(GraphQLHttpRequest request)
var response = await _graphQlHttpClient.SendQueryAsync<TResponse>(request);
if (response.Errors != null && response.Errors.Length > 0)
{
var message = new StringBuilder();
var count = 1;
var exc = new AnvilClientException(
string.Join("; ", Array.ConvertAll(response.Errors, e => e.Message))
);
foreach (var e in response.Errors)
{
message.Append(e.Message);
exc.Data.Add($"Message{count}", e.Message);
count++;
}

throw new AnvilClientException(message.ToString());
throw exc;
}

return response.Data;
}
catch (GraphQLHttpRequestException ex)
{
if (ex.Content != null)
throw WrapGraphQLException(ex);
}
}

internal static AnvilClientException WrapGraphQLException(GraphQLHttpRequestException ex)
{
var messages = new List<string>();

if (ex.Content != null)
{
try
{
var errorResponse = (JObject)JsonConvert.DeserializeObject(ex.Content);
var errors = (JArray)errorResponse["errors"];
var content = new StringBuilder();
foreach (var e in errors)
var errorResponse = JsonConvert.DeserializeObject(ex.Content) as JObject;
if (errorResponse != null)
{
content.Append(e["message"]);
var errors = errorResponse["errors"] as JArray;
if (errors != null)
{
foreach (var e in errors)
{
var msg = e["message"]?.ToString();
if (msg != null) messages.Add(msg);
}
}
}
}
catch (JsonException)
{
// Response is not JSON — raw content is captured below
}
}

if (ex.Message.Contains("Unauthorized"))
{
throw new GraphQLHttpRequestException(ex.StatusCode, ex.ResponseHeaders, content.ToString());
}
var message = messages.Count > 0
? string.Join("; ", messages)
: $"Error: {ex.StatusCode}";

var anvilEx = new AnvilClientException(message, ex)
{
HttpStatusCode = ex.StatusCode,
ResponseContent = ex.Content
};

if (ex.ResponseHeaders != null)
{
anvilEx.ResponseHeaders = new Dictionary<string, IEnumerable<string>>(StringComparer.OrdinalIgnoreCase);
foreach (var header in ex.ResponseHeaders)
{
anvilEx.ResponseHeaders[header.Key] = header.Value;
}
}

throw;
var dataCount = 1;
foreach (var msg in messages)
{
anvilEx.Data.Add($"Message{dataCount}", msg);
dataCount++;
}

return anvilEx;
}

/// <summary>
Expand Down Expand Up @@ -234,5 +281,14 @@ string clientUserId

return await SendQuery<Payloads.Response.CreateEtchPacketPayload>(request);
}

public void Dispose()
{
if (!_disposed)
{
_graphQlHttpClient.Dispose();
_disposed = true;
}
}
}
}
Loading