问题
When making PostAsync call using HttpClient to a 3rd party API. I am seeing this error exactly when I do client.PostAsync. Any idea what could have been causing this?
Code:
public class JobController : AsyncController
{
public ActionResult ViewPage()
{
return View("~/Views/Pages/Submit.cshtml");
}
private const string ServiceUrl = "https://api.3points.io/v1/applications/";
[HttpPost]
public async Task<ActionResult> Submit()
{
var client = new HttpClient();
var formData = new MultipartFormDataContent();
var encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes("abc123"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encoded);
foreach (var key in Request.Form.AllKeys)
formData.Add(new StringContent(Request.Form[key]), String.Format("\"{0}\"", key));
foreach (string key in Request.Files.AllKeys)
{
var file = Request.Files[key];
if (file == null || file.ContentLength <= 0) continue;
HttpContent fileStream = new StreamContent(file.InputStream);
formData.Add(fileStream, key, file.FileName);
}
var response = await client.PostAsync(ServiceUrl, formData);
var success = "True";
if (!response.IsSuccessStatusCode) success = "False";
return new JsonResult { Data = success };
}
}
Error:
System.NullReferenceException was unhandled
HResult=-2147467261
Message=Object reference not set to an instance of an object.
Source=System.Web
StackTrace:
at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext)
at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
at System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state)
at System.Web.LegacyAspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state)
at System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task& currentTask)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.Tasks.AwaitTaskContinuation.<ThrowAsyncIfNecessary>b__1(Object s)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
回答1:
I would change
var response = client.PostAsync(ServiceUrl, formData).Result
to
var response = await client.PostAsync(ServiceUrl, formData);
And then monitor for errors after that.
回答2:
Add these two lines to your web.config file:
// First tag might exist already
<httpRuntime targetFramework="4.5" />
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
Im quoting this link:
Enables the new await-friendly asynchronous pipeline that was introduced in 4.5. Many of our synchronization primitives in earlier versions of ASP.NET had bad behaviors, such as taking locks on public objects or violating API contracts. In fact, ASP.NET 4's implementation of SynchronizationContext.Post is a blocking synchronous call! The new asynchronous pipeline strives to be more efficient while also following the expected contracts for its APIs. The new pipeline also performs a small amount of error checking on behalf of the developer, such as detecting unanticipated calls to async void methods.
Certain features like WebSockets require that this switch be set. Importantly, the behavior of async / await is undefined in ASP.NET unless this switch has been set. (Remember: setting is also sufficient.)
来源:https://stackoverflow.com/questions/22993131/httpclient-error-with-postasync-method