SendGrid throws "Error while copying content to a stream" - c#

I'm creating a Core 2.1 solution in Visual Studio 2017 where I send emails via Sendgrid. When trying to send an email via SendGrid, I get the following error:
An unhandled exception occurred while processing the request.
IOException: The server returned an invalid or unrecognized response.
System.Net.Http.HttpConnection.FillAsync() HttpRequestException: Error
while copying content to a stream.
System.Net.Http.HttpContent.LoadIntoBufferAsyncCore(Task
serializeToStreamTask, MemoryStream tempBuffer)
Here is what my code looks like. I'm entering the following in parameters:
recipients: list containing "****#gmail.com"
Subject: "Hello"
Body: Html generated via Heml. It compiles in an online editor without problem.
private async Task<bool> SendAsync(List<string> recipients, string subject, string body)
{
var client = new SendGridClient(this.configuration["Sendgrid:ApiKey"]);
var from = new EmailAddress(
this.configuration["Administration:MainEmailAddress"],
this.configuration["Administration:MainEmailName"]);
var tos = await GetRecipientsForEnvironment(recipients);
var message = MailHelper.CreateSingleEmailToMultipleRecipients(
from,
tos,
subject,
"",
body,
false);
var response = await client.SendEmailAsync(message);
return response.StatusCode == HttpStatusCode.Accepted;
}
What is the cause of this error?

It turns out that there is a known bug in Sendgrid. If the html content entered is very big, the correct error message will not be sent. Instead, this error will show up. In my case, my apiKey was not found and I should therefore have gotten an Unauthorized error message. When I changed my html into one much smaller, this gave me the correct error.
Read more about the issue here.

I'm having the same problem, but in my case it's because the email quota has expired (I'm using the free version for testing):
Lib version 9.21.0
On the mentioned thread https://github.com/sendgrid/sendgrid-csharp/issues/648 some people were passing the wrong apiKey, and others exceeding the HTML size.
As said in the thread above, apparently it's a bug in the sendgrid library when interpreting the error.
Therefore, in addition to the problems mentioned (passing the wrong apiKey, exceeding the HTML size) the return “Error while copying content to a stream” is hiding other problems as well (like in my case: quota expired).

Related

C# API call from MarketStack and print values - Error 403

I would like to make a successful API call, then print the values in order to see if it works. My main goal is to analyze the data, after I can make a successful API call, and build a systematic strategy for trading.
System.Net.Http.HttpRequestException: "Response status code does not indicate success: 403 (Forbidden)
namespace marketstacktest
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("Hello World!");
var options = Options.Create(new MarketstackOptions() { ApiToken = "secretTokenHere" });
var marketstackService = new MarketstackService(options, NullLogger<MarketstackService>.Instance);
var appleSymbol = "AAPL";
var fromDate = DateTime.Now.AddDays(-200);
var toDate = DateTime.Now;
//error at the await System.Net.Http.HttpRequestException: "Response status code does not indicate success: 403 (Forbidden)."
List<Marketstack.Entities.Stocks.StockBar> stock = await marketstackService.GetStockEodBars(appleSymbol, fromDate, toDate);
foreach (var stock_i in stock)
{
Console.WriteLine($"close: {stock_i.Close}");
}
}
}
}
In the API manual, which is directly linked from the github, it gives information about all of the error codes. The relevant ones here are these two:
Code
Type
Description
403
https_access_restricted
HTTPS access is not supported on the current subscription plan.
403
function_access_restricted
The given API endpoint is not supported on the current subscription plan.
Their class library on github is just wrapping a json REST api. Every call to the API is just an http request, returning data as json objects. The 403 error indicates that your request was accepted as a valid request, but intentionally rejected by the server for some reason. And according to the docs, the error was because your account is not allowed access to either https or to the type of request.
Their free-tier subscription only includes end-of-day data, which is what you requested, so it wouldn't make sense for that not to be allowed. So, your app is almost certainly making an https call.
I went to the examples at the very beginning of their quick start guide, and chose the end-of-day example to match your app, and clicked on the link. It worked, and gave a bunch of json records. But, the request they made was using 'http' not 'https'.
Changing the requst to 'https' elicited a 403 response with this content (formatted for readability):
{
"error":
{
"code": "https_access_restricted",
"message": "Access Restricted - Your current Subscription Plan does not support HTTPS Encryption."
}
}
At this point we have enough to be almost certain that this is your issue. The final thing is to go look up how to turn https requests off in their class library. To avoid having to go through the code, I checked the help at the bottom of the page one more time, and found this (formatted for readability):
var options = Options.Create(new MarketstackOptions(){
ApiToken = apiKey,
MaxRequestsPerSecond = 3,
Https = true
});
Welp. This should probably be in their first example, since that's what people are most likely to try first, but it's not. So, to stop trying to make http requests, you just need to set the Https option to false in your code. You just need to add that to the options in your code, like so:
var options = Options.Create(new MarketstackOptions(){
ApiToken = "secretTokenHere",
Https = false
});
I will leave the testing to you, but from the browser test, we know that the request should work, unless there's a bug in their library. Given the information that was available, this is almost certainly the issue.

Autodesk Forge Error trying to access the API online

I have a problem loading a 3D model on an online server, the error shown is related to accessing the Forge API, locally works smoothly however when mounted on the server or a website is made marks the following error "Failed to load resource: the server responded with a status of 404 (Not Found)", then "onDocumentLoadFailure() - errorCode:7".
As I comment, what I find stranger is that, locally, it works. Attached the segment of the code where it displays the error.
function getAccessToken() {
var xmlHttp = null;
xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", '/api/forge/toke', false); //Address not found
xmlHttp.send(null);
return xmlHttp.responseText;
}
Thank you very much in advance.
Are you sure the code you're running locally and the code you've deployed are really the same?
The getAccessToken function doesn't seem to be correct, for several reasons:
First of all, there seems to be a typo in the URL - shouldn't it be /api/forge/token instead of /api/forge/toke?
More importantly, the HTTP request is asynchronous, meaning that it cannot return the response immediately after calling xmlHttp.send(). You can find more details about the usage of XMLHttpRequest in https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest.
And finally, assuming that the function is passed to Autodesk.Viewing.Initializer options, it should return the token using a callback parameter passed to it (as shown in https://forge.autodesk.com/en/docs/viewer/v7/developers_guide/viewer_basics/initialization/#example).
With that, your getAccessToken should probably look more like this (using the more modern fetch and async/await):
async function getAccessToken(callback) {
const resp = await fetch('/api/forge/token');
const json = await resp.json();
callback(json.access_token, json.expires_in);
}
I've already found the issue. When I make the deploy I have to change the url where the request is made for the public or the name of the domain. For example: mywebsite.com/aplication-name/api/forge/token.

System.Text.Json.JsonException: The input does not contain any JSON tokens

I'm just trying to use a Http POST method in a Blazor app through
public async Task CreateUnit(UnitEntity unit)
{
await _http.PostJsonAsync<UnitEntity>("api/units", unit);
}
_http and myObject have been defined elsewhere, but I'm getting this weird error. Can anyone help? This is the closest thing I could find elsewhere: https://github.com/dotnet/runtime/issues/30945.
The full error message is
System.Text.Json.JsonException: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
And it here's the stack
Another reason this error could pop up, as it did for me, is simply because the API endpoint doesn't exist because it was misspelled.
I got a similar error in Program.cs Main method CreateHostBuilder(args).Build();:
System.FormatException: 'Could not parse the JSON file.'
JsonReaderException: The input does not contain any JSON tokens.
Expected the input to start with a valid JSON token, when isFinalBlock
is true. LineNumber: 0 | BytePositionInLine: 0.
For me it turned out to be the local secrets.json file that not contained a valid json object.
https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0&tabs=windows#secret-manager
Because of this I could not see any errors in Git or rollback to a working commit since the file is not checked in.
Solved by adding an empty object to the file via Visual Studio - right click the project in solution explorer and select Manage User Secrets:
{
}
https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0&tabs=windows#manage-user-secrets-with-visual-studio
In my case the code was doing this:
var json = await response.Content.ReadAsStringAsync();
var result = JsonObject.Parse(json); // threw the exception mentioned in the question
Why did that happen? That's because json value was an empty string "". Parse fails with an empty string.
Fixed it doing this simple change:
var json = await response.Content.ReadAsStringAsync();
var result = string.IsNullOrEmpty(json) ? null : JsonObject.Parse(json);
i had similar issue and the problem to check if the json string you are readying is empty, null, or bad formatted. debug to the code line where you are reading data into string before deserialize or serialize call.
I got this error when communicating between two APIs.
request = await req.DeserializeRequestBodyAsync<MyDto>(jsonSerializerOptions);
Turned out the code below did not actually send any values:
httpRequestMessage.Content = JsonContent.Create(myDto);
var httpClient = _clientFactory.CreateClient();
var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage, cancellationToken);
I had to manually specify:
await httpRequestMessage.Content.LoadIntoBufferAsync();
Like this:
httpRequestMessage.Content = JsonContent.Create(myDto);
await httpRequestMessage.Content.LoadIntoBufferAsync();
var httpClient = _clientFactory.CreateClient();
var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage, cancellationToken);
For me, this error occurred when calling FindByNameAsync of UserManager.
Sounds silly, but the database connection string in the appsettings was wrong!
Late answer - but I ran into this using Blazor WebAssembly with Browser Link (trying to get Hot Reload to work). Turns out it's an issue loading the appsettings and Browser Link was expecting the secrets file. I fixed by right clicking the Server project and copy/pasting my appsettings values into the secrets file.
In my case, I was passing the id of my object along with the object itself in the url of the put request to an API and faced the same exception. It turned out that it was not necessary to pass the id (as it was retrieved from the object itself, in fact it was not present in the method signature). Removing the id solved the problem.
This error occurred when communicating between client and web API.
API code:
public async Task<IActionResult> PostAsync(object review)
{
return Ok();
}
Client code:
var res = await _client.PostAsJsonAsync("api/reviews", review);
if (res.IsSuccessStatusCode)
{
var myObject = await res.Content.ReadFromJsonAsync<MyObject>(); //this line threw mentioned error
}
Turned out that the API endpoint was returning something different compared to what I was trying to read from JSON i.e. I was trying to read MyObject but API was returning ActionResult
In my case database column was marked not null and I was passing null in API.

docker/linux aspnet core 2.03 truncating post data. How is this possible?

I am at a loss and would welcome any and all advice. This code is deceptively simple, but Async might be complicating things and causing issues.
POST method works when data bytes is less than 3802. Data is truncated at 3800 or 3801 when the POST data is greater than 3802. This took a while to catch for us because most of the time data is < 3800. I finally added the debug logging and saw the disconnect.
I have been doing extra reading on async and don't currently believe this code has an issue. I know async void will cause fire and forget, but we have a try/catch, so I expect errors to show up in the logs without taking the whole program out due to an exception. I would welcome suggestions for improvement however.
[HttpPost("{instance}/{objectType}")]
public async void Post( [FromRoute] string instance, [FromRoute] string objectType )
{
Log.Debug("Incoming post(instance/objectype)");
string content = "";
try
{
using (var reader = new StreamReader(Request.Body, Encoding.UTF8))
{
// have a scenario where conlen below is always cut off at 3800 or 3801 bytes
// wild guess is that it is a async/threadpool issue?
content = await reader.ReadToEndAsync();
}
var conlen = (content != null) ? content.Length : 0;
var contentbegin = (content != null) ? content.Substring(0, Math.Min(conlen, 80)) : "";
Log.Debug("POST {objecttype} {contentlen} {contentbegin}", objectType, conlen, contentbegin);
await ProcessPost(objectType, content, instance);
}
catch (Exception ex)
{
Log.Error("Exception in Post {msg} {trace}", ex.Message, ex.StackTrace);
Log.Error("Exception in Post offending message {msg} ", content);
}
}
Here is an example of the logs. You can see the size of the data is > 3800, but alas, we are getting cut off when we go to read it.
[19:27:57 INF] Request starting HTTP/1.0 POST http://backend.example.com/orderinput application/json 5459
[19:27:57 INF] Executing action method Controllers.ValuesController.Post (Test) with arguments (["Production", "orderinput"]) - ModelState is Valid
[19:27:57 DBG] Incoming post(instance/objectype)
[19:27:57 INF] Executed action Controllers.ValuesController.Post (Test) in 0.4701ms
[19:27:57 INF] Request finished in 0.789ms 200
[19:27:57 DBG] POST orderinput 3801 {"SAMPLE":"1234567890.........
[19:27:57 DBG] Enter ProcessPost
[19:27:57 DBG] Persisting post
[19:27:57 ERR] Exception in ProcessPost DB Persist Unexpected end of content while loading JObject. Path 'customer_id', line 1, position 3801.
EDITS:
WHY DO I THINK THIS CODE IS AN ISSUE?
At the end of line 1 in the logs, ASP.NET has helpfully put the content length, 5459. Line 6 has my calculation and it shows 3801. These two numbers are always the same unless the length exceeds 3802.
HOW IS THE DATA SUBMITTED? HAVE I TRIED DOING SO?
Data is coming from another web service not under my control through an NGINX proxy. Thanks for the suggestion I will exercise this both with and without the proxy, above and below 3802 and report the results back here. Given the disconnect between the ASP.NET logs and my calculation, it seems like a long shot, but all roads are worth going down.
I threw away the codebase that was written by another developer and started over from scratch to fix this issue. I think the fact that sync/async was being mixed indiscriminately was the issue, and this weird symptom was the result. I used nito asyncex in my final solution to isolate the rabbit library from Async calls, and for the Asp.Net web API, I had all incoming data post to a queue, and the queue ran in a separate thread that exclusively talked to rabbit. No issues at all since the rewrite.

Error Calling DescribeIndexFieldsAsync on AmazonCloudSearchClient

I've confirmed that I have permissions to perform the request.
According to amazon's Cloud Search Dev Troubleshooting Guide the error I'm experiencing is likely due to the .net sdk using the wrong api version. I don't see a way to specify the api version explicitely.
I want to avoid having to manually create the http request.
I want to make the request through the SDK.
I've tried all the available versions of the SDK and all of them give me this error.
I've also tried specifying the request properties in various combinations. Nothing works.
Can anybody give me direction as to how I can resolve this issue?
Expected behavior: return info for all index fields
Actual behavior:
error -
"Result Message:
Amazon.Runtime.AmazonUnmarshallingException : Error unmarshalling response back from AWS. Response Body: {
"message": "Request forbidden by administrative rules",
"__type": "CloudSearchException"
}"
----> System.Xml.XmlException : Data at the root level is invalid. Line 1, position 1.
Code sample:
var _configClient = new AmazonCloudSearchClient(
WebConfigurationManager.AppSettings["CloudSearchAccessKey"],
WebConfigurationManager.AppSettings["CloudSearchSecretKey"],
new AmazonCloudSearchConfig
{
RegionEndpoint = RegionEndpoint.USWest2,
ServiceURL = WebConfigurationManager.AppSettings["CloudSearchUrl"]
});
await _configClient.DescribeIndexFieldsAsync(new DescribeIndexFieldsRequest())
CloudSearch is returning json, which you can see in your response body, and the SDK is trying to unmarshal that into xml. When you make a query directly, you can add &format=xml to get xml results. There should be an analogous option in the SDK.

Categories