Using the following code snippet in WinForms, I am successfully able to upload documents through a REST API. But as soon as I move to ASP.NET, it throws a NullReferenceException.
public async Task<string> TestUpload()
{
const string cServerBaseAddress = "https://test-testrestservice.abcd.com/";
const string cFilename = @"D:\temp\Test.txt";
const string cUrl = "{0}abc/dms/api/v1/crmdocuments/?BusinessUnit={1}&AccountID={2}&DocumentType={3}&Description={4}&Filename={5}";
string businessUnit = "XYZ";
string accountID = "ABCCompany";
string docType = "Affidavit";
string description = @"\%&description&%/";
string responseContent = string.Empty;
try
{
string url = string.Format(cUrl, cServerBaseAddress,
WebUtility.UrlEncode(businessUnit), WebUtility.UrlEncode(accountID),
WebUtility.UrlEncode(docType), WebUtility.UrlEncode(description),
WebUtility.UrlEncode(Path.GetFileName(cFilename)));
using (HttpClient client = GetClient(cServerBaseAddress))
{
using (HttpResponseMessage response = await client.PostAsync(url, new ByteArrayContent(File.ReadAllBytes(cFilename))))
{
responseContent = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
string newContentId = Newtonsoft.Json.Linq.JToken.Parse(response.Content.ReadAsStringAsync().Result).ToString();
return newContentId;
}
}
}
I've debugged the client, url, and ByteArrayContent, and none of them is null. But I am still getting an unhandled exception.
Here are the details of the exception:
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.Web.LegacyAspNetSynchronizationContext.Post(SendOrPostCallback callback, Object state)
at System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.PostAction(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.<>c.<ThrowAsyncIfNecessary>b__18_0(Object s)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
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()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
urland or a config setting.EnsureSuccessStatusCode()before you try to read the content; b) you don't declareresponseContentin this code, so where is it declared?; c) it could be this is just an adjusted code snippet, but in general do not create and disposeHttpClientlike that for each request - create one instance and use it for your whole app, as intended; d) changeresponse.Content.ReadAsStringAsync().Resultto justresponseContent.EnsureSuccessStatusCode()first? Could be you're getting a non 2xx response.