在云端部署时调用 workItemTrackingHttpClient.CreateWorkItemAsync() 会抛出不同的异常

Calling workItemTrackingHttpClient.CreateWorkItemAsync() throws different exceptions when deployed on cloud

我正在尝试使用客户端库并使用 OAuth 作为身份验证机制在 Azure DevOps 中创建一个工作项。

它在我的本地机器上运行良好(当我在本地调试它时),但只要部署在云上(在我的例子中是 Azure App 服务)就会抛出异常。

public string CreateWorkItemDemo(string accesstoken)
    {
        try
        {
            Uri _uri = new Uri("https://xyz.visualstudio.com");
            JsonPatchDocument patchDocument = new JsonPatchDocument();
            string project = "abcproject";
            patchDocument.Add(
                new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path = "/fields/System.Title",
                    Value = "Test item created through token two"
                });
            patchDocument.Add(
                new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path = "/fields/System.AreaPath",
                    Value = string.Format("{0}", project)
                });
            try
            {
                VssConnection connection = new VssConnection(_uri, new VssOAuthAccessTokenCredential(accesstoken));
                WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient<WorkItemTrackingHttpClient>();
                try
                {
                    var result = workItemTrackingHttpClient.CreateWorkItemAsync(patchDocument, project, "Bug").Result; //This line of code throws exception
                    return result.Id.Value.ToString();
                }
                catch (Exception ex)
                {
                   //The exceptions is logged from here.
                }
            }
            catch (Exception ex)
            {
                 //Exception messages here
            }
        }
        catch (Exception exception)
        {
               //Exception messages here
        }

它抛出的异常是:

One or more errors occurred. ex.stacktrace at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task1.get_Result()

此方法直接从 link 调用,访问令牌也随之传递。早些时候我通过 ajax 调用调用此方法,因为我认为 ajax 调用可能不会等待异步。但它抛出了同样的异常。

然后我将方法更改为async/await并通过link调用它。 这是代码:

public async Task<string> CreateItem(string accesstoken)
    {
        string _uri = "https://xyz.visualstudio.com";
        Uri uri = new Uri(_uri);
        string project = "abcproject";
        JsonPatchDocument patchDocument = new JsonPatchDocument();
        patchDocument.Add(
            new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path = "/fields/System.Title",
                Value = "Test item created through code seven"
            });
        patchDocument.Add(
            new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path = "/fields/System.AreaPath",
                Value = string.Format("{0}", project)
            });
        try
        {
            VssConnection connection = new VssConnection(uri, new VssOAuthAccessTokenCredential(accesstoken));
            WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient<WorkItemTrackingHttpClient>();
            try
            {
                var response = await workItemTrackingHttpClient.CreateWorkItemAsync(patchDocument, project, "Bug");

                return "Successfully created bug with Id" + response.Id.Value.ToString();
            }
            catch (Exception ex)
            {
                //Exceptions are logging here
                return ex.Message + " ," + ex.StackTrace + " One here";
            }
        }
        catch (Exception ex)
        {
            return ex.Message + " ," + ex.StackTrace + " 2 here";
        }
    }

这里我遇到了这种异常,最后一行:

d__52.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.d__50.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.d__471.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.d__281.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

You must pass a valid patch document in the body of the request. , at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.

由于我使用的是 OAuth 机制,因此访问令牌仅在我的云应用程序中生成。 因此,为了在本地 运行 它,我创建了一个单独的 Asp.net Web 应用程序,并通过传递从我的云应用程序生成的访问令牌在本地 运行 将其

我怎么强调都不为过,当我在本地多次 运行 时,这两种方法都 运行 非常好。

我对此深感震惊,由于我是这个编程世界的新手,我们将不胜感激任何提供一点细节的帮助

类似的问题在这里:You must pass a valid patch document in the body of the request. Used WorkItemTrackingHttpClient

This is then a Bug of the stable version, so you have to use a preview version

尝试更新您的客户端库以预览版本。

Edit:

I seriously don't know how, but when I deployed my above code on Azure cloud service, it works. But it still shows the exceptions when I run it on Azure App service. Maybe the Azure App service that I was using came under a free plan (without any Cores), so that might be the case. However please note that HttpClient worked in both the cases. Hope this answer can save someone's time.

这段代码工作正常。这里我没有使用 WorkItemHttpClient,而是使用了 HttpClient。


public async Task<string> CreateWorkItemUsingHttpClient(string accesstoken)
    {
        try
        {
            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json-patch+json"));
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accesstoken);
            WorkItemPostData wiPostData = new WorkItemPostData();
            wiPostData.op = "add";
            wiPostData.path = "/fields/System.Title";
            wiPostData.value = "Workitem created through cloud";
            List<WorkItemPostData> wiPostDataArr = new List<WorkItemPostData> { wiPostData };
            string wiPostDataString = JsonConvert.SerializeObject(wiPostDataArr);
            HttpContent wiPostDataContent = new StringContent(wiPostDataString, Encoding.UTF8, "application/json-patch+json");
            string url = "https://dev.azure.com/xyz/abcproject/_apis/wit/workitems/$Bug?api-version=5.0";
            try
            {
                HttpResponseMessage response = client.PatchAsync(url, wiPostDataContent).Result;
                try
                {
                    if (response.IsSuccessStatusCode)
                    {
                        response.EnsureSuccessStatusCode();
                        string responseContent = await response.Content.ReadAsStringAsync();
                        return responseContent;
                    }
                    else
                    {
                        return "Success code returned false";
                    }
                }
                catch(Exception ex)
                {
                    return "One " +ex.Message + " " + ex.StackTrace;
                }
            }
            catch(Exception ex)
            {
                return "Two " +ex.Message + " " + ex.StackTrace;
            }
        }
        catch(Exception ex)
        {
            return "Three " +ex.Message + " " + ex.StackTrace;
        }
    }

此代码在本地以及部署在云端时都可以正常工作。 我不知道为什么 WorkItemHttpClient 不能在云上工作并给出与线程和修补相关的异常,尽管它在本地工作正常。 我只是外行猜测,也许 WorkItemHttpClient 不如 HttpClient 强大,因此它无法在云上部署时创建工作项,因为它必须更快地完成。但这只是一个非技术性的猜测。

无论如何,我发布这个答案只是为了让其他可能遇到同样问题的人可以参考这个解决方案。

按照文档中的步骤操作,

https://docs.microsoft.com/es-es/azure/devops/integrate/quickstarts/create-bug-quickstart?view=azure-devops&viewFallbackFrom=vsts

只有一个变化,

而不是

WorkItem result = workItemTrackingHttpClient.CreateWorkItemAsync(patchDocument, project, "Bug").Result;

新代码

WorkItem result = workItemTrackingHttpClient.CreateWorkItemAsync(patchDocument, project, "Issue").Result;