Repository navigation
Description
Hi, hope you're doing well.
I have the Cloudinary .NET SDK integrated with a Unity project. I've placed the CloudinaryDotNet DLL, as well as all of its DLL dependencies, inside my project. I'm able to access all the Cloudinary namespaces/classes/etc. from my code, which is fantastic.
Unfortunately, when I attempt a simple implementation of Cloudinary.Upload, I get a FormatException. Here's the problem code:
public void UploadImage()
{
ImageUploadParams uploadParams = new ImageUploadParams
{
File = new FileDescription("https://www.fnordware.com/superpng/pnggrad16rgb.png"), // Just a simple gradient image for testing
};
cloudinary.Upload(uploadParams); // FormatException is traced back to this line
}
Before the above method is called in my program, I'm setting my configuration parameters as outlined in the documentation, like this (with my actual info substituted):
Account account = new Account(
"my_cloud_name",
"my_api_key",
"my_api_secret");
Cloudinary cloudinary = new Cloudinary(account);
Here are the package versions I'm using:
- Cloudinary .NET SDK: 1.15.2
- Microsoft.AspNetCore.Html.Abstractions: 2.2.0
- Microsoft.AspNetCore.Http.Abstractions: 2.2.0
- Microsoft.AspNetCore.Http.Features: 2.2.0
- Microsoft.Extensions.DependencyInjection.Abstractions: 5.0.0
- Microsoft.Extensions.Options: 5.0.0
- Microsoft.Extensions.Primitives: 5.0.1
- Microsoft.Extensions.WebEncoders: 5.0.7
- System.Buffers: 4.5.1
- System.IO.Pipelines: 5.0.1
- System.Memory: 4.5.4
- System.Numerics.Vectors: 4.5.0
- System.Runtime.CompilerServices.Unsafe: 5.0.0
- System.Text.Encodings.Web: 5.0.1
- System.Threading.Tasks.Extensions: 4.5.4
Below is the FormatException that I'm getting:
FormatException: One of the identified items was in an invalid format.
System.Net.Http.Headers.HttpHeaders.AddInternal (System.String name, System.Collections.Generic.IEnumerable`1[T] values, System.Net.Http.Headers.HeaderInfo headerInfo, System.Boolean ignoreInvalid) (at <efff4cb93af94c0c950db61b78368b54>:0)
System.Net.Http.Headers.HttpHeaders.Add (System.String name, System.Collections.Generic.IEnumerable`1[T] values) (at <efff4cb93af94c0c950db61b78368b54>:0)
System.Net.Http.Headers.HttpHeaders.Add (System.String name, System.String value) (at <efff4cb93af94c0c950db61b78368b54>:0)
CloudinaryDotNet.ApiShared.PrePrepareRequestBody (System.Net.Http.HttpRequestMessage request, CloudinaryDotNet.HttpMethod method, System.Collections.Generic.Dictionary`2[TKey,TValue] extraHeaders) (at <0c3884533d824ad98e55170b6aba31df>:0)
CloudinaryDotNet.ApiShared+<PrepareRequestBodyAsync>d__75.MoveNext () (at <0c3884533d824ad98e55170b6aba31df>:0)
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[TResult].GetResult () (at <695d1cc93cca45069c528c15c9fdd749>:0)
CloudinaryDotNet.ApiShared+<CallAsync>d__58.MoveNext () (at <0c3884533d824ad98e55170b6aba31df>:0)
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[TResult].GetResult () (at <695d1cc93cca45069c528c15c9fdd749>:0)
CloudinaryDotNet.ApiShared+<CallAndParseAsync>d__56`1[T].MoveNext () (at <0c3884533d824ad98e55170b6aba31df>:0)
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () (at <695d1cc93cca45069c528c15c9fdd749>:0)
CloudinaryDotNet.Cloudinary.Upload[T,TP] (TP parameters) (at <0c3884533d824ad98e55170b6aba31df>:0)
CloudinaryDotNet.Cloudinary.Upload (CloudinaryDotNet.Actions.ImageUploadParams parameters) (at <0c3884533d824ad98e55170b6aba31df>:0)
CloudinaryUploader.UploadImage () (at Assets/Scripts/_general/Cloudinary/CloudinaryUploader.cs:28)
I'm working on a Mac inside Unity 2021.1.3f1, which can use either .NET Standard 2.0 or .NET 4.x. Both APIs produce the above error.
Please let me know if there's any additional information I can provide.
Thank you so much. I would really appreciate any insight anyone might have.
All the best,
Galen
Activity
galenmolk commentedon Jun 20, 2021
In case anyone else working inside Unity comes across this same problem, I'll try to detail what I did to fix this here.
The FormatException error was being thrown from the method
PrePrepareRequestBody, on line 450 ofApiShared.Internal.cs:request.Headers.Add("User-Agent", userPlatform);The issue was the userPlatform parameter. This is created from the static string
ApiInternal.USER_AGENT.USER_AGENTis built on line 809 ofApiShared.csinBuildUserAgent. And this in turn usesSystem.Runtime.InteropServices.RuntimeInformation.FrameworkDescriptionto get the name of your .NET installation.When working inside Unity,
FrameworkDescriptionreturns the following string:Mono 5.11.0 ((HEAD/768f1b247c6)For some incredibly unhelpful reason, there is a closing parentheses missing from the end of that string, which was making HTTP reject the Header parameter.
I fixed this by adding an additional closing parentheses on the end of the string returned inside
ApiInternal.BuildUserAgent. So that method now looks like:Hopefully this sort of direct meddling with the User-Agent string doesn't negatively impact me in some other way. If anyone has any cautionary advice on this, I'd love to hear your thoughts.
Thanks everyone.
const-cloudinary commentedon Jun 20, 2021
@galenmolk , thank you for reporting this issue!
It is a bit weird bug.
We'll fix it by encoding a header value, so it will be safe regardless of the amount of parenthesis or other unsafe characters.