How to call AZURE DEVOPS rest API in the water fall dialog built using C# BOT Framework SDK V4?

1

I have web channel chat bot created through C# using BOT Framework SDK V4. It has multiple waterfall dialogs that do set of actions based upon option selected in the main dialog.

In one of the dialog my requirement is user inputs some data and then using that I should create a Work Item of Type task in my AZURE DEvOps project for tracing purposes. I am successfully able to acquire the data from user but while creating WORK ITEM in devops I am facing problem. I have tried couple of things from my side but they are working if executed by creating individual C# console applications but if i try to use the same code by installing the related NuGET packages or adding the reference assemblies i get errors or warnings.

Try 1: Using TFS related nuget packages in BOTCode:

If i try to use the code by installing the Nuget packages related to the TFS Extended client then during installation it says the compatibility warnings and my reference assemblies sections have a warning symbol. Through i haven't tried executing this piece of code in my dialog class because though it may have work but i am not sure after publishing to AZURE it may cause issues.

Now when coming to try 2 Try 2: Using AZURE DEVOPS REST API in BOT Code:

I have written code for calling REST API for with i have used the following code in my Dialog class:

string token = "toekn";
        string type = "Task";
        string organization = org
        string project = "Project";
        int workitemid = 0;
        string url = $"https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/${type}?api-version=5.0";

        JavaScriptSerializer serializer = new JavaScriptSerializer();
        string json = serializer.Serialize(new object[]{new
        {
            op = "add",
            path = "/fields/System.Title",
            value = "Testing Workitem creation through API" 
        },
        new {
            op = "add",
            path = "/fields/System.Description",
            value = "Model Request ID#" + requestid + " from: "+ name + " requested from ChatBot" 
        },

        new {
            op = "add",
            path = "/fields/Priority",
            value = 1
        }

        });

        using (HttpClient client = new HttpClient())
        {
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", token))));

            var method = new HttpMethod("POST");

            var request = new HttpRequestMessage(method, url)
            {
                Content = new StringContent(json, Encoding.UTF8,
                    "application/json-patch+json")
            };


            var sendresult = client.SendAsync(request).Result;
            var result = sendresult.Content.ReadAsStringAsync().Result;
            Console.WriteLine("Completed!");
            dynamic workitemdata = JsonConvert.DeserializeObject(result);
            workitemid = workitemdata.id;                
        };

Now if you observe in the above code there is a method -

JavaScriptSerializer serializer = new JavaScriptSerializer();

This needs a assembly reference called: system.web.extensions.dll to be used i have added this reference by browsing this DLL i.e. using System.Web.Script.Serialization;

Now when i execute this i get exception as below: Exception caught : Could not load file or assembly 'System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context. (Exception from HRESULT: 0x80131058)

When i searched for a fix for this error in this blog there they said to remove targetframework related tags from csproj file and that should work but this gave build errors stating targetframework not found.

This is where i got stuck. I am also attaching my unmodified csproj file for reference.

Please note that i have created a basic echo bot in Azure then downloaded this basic bot and build my own water dialogs from scratch on top of this basic botas per my requirement.

Please help me to unblock the issue as i tried couple of things which did not work. If this cannot be achieved then please let me know so that i can communicate the same to my team. Here thanks in Advance for the help.

I also tried to use the following code taken from this blog this also did not work. As i am blocked i am posting this query for help:

 static void Main(string[] args)
{
    CreateWorkItem();
}


public static void CreateWorkItem()
{
    string _tokenAccess = "************"; //Click in security and get Token and give full access https://azure.microsoft.com/en-us/services/devops/
    string type = "Bug";
    string organization = "type your organization";
    string proyect = "type your proyect";
    string _UrlServiceCreate = $"https://dev.azure.com/{organization}/{proyect}/_apis/wit/workitems/${type}?api-version=5.0";
    dynamic WorkItem = new List<dynamic>() {
            new
            {
                op = "add",
                path = "/fields/System.Title",
                value = "Sample Bug test"
            }
        };

    var WorkItemValue = new StringContent(JsonConvert.SerializeObject(WorkItem), Encoding.UTF8, "application/json-patch+json");
    var JsonResultWorkItemCreated = HttpPost(_UrlServiceCreate, _tokenAccess, WorkItemValue);
}


public static string HttpPost(string urlService, string token, StringContent postValue)
{
    try
    {
        string request = string.Empty;
        using (HttpClient httpClient = new HttpClient())
        {
            httpClient.DefaultRequestHeaders.Accept.Clear();
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", token))));
            using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage(new HttpMethod("POST"), urlService) { Content = postValue })
            {
                var httpResponseMessage = httpClient.SendAsync(httpRequestMessage).Result;
                if (httpResponseMessage.IsSuccessStatusCode)
                    request = httpResponseMessage.Content.ReadAsStringAsync().Result;
            }
        }
        return request;
    }
    catch (Exception ex)
    {
        throw new Exception(ex.Message);
    }
}

Below is the data in csproj file for reference:

 <Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.Bot.Builder.AI.QnA" Version="4.6.0" />
    <PackageReference Include="Microsoft.Bot.Builder.Dialogs" Version="4.6.0" />
    <PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.6.0" />
    <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
    <PackageReference Include="System.Data.SqlClient" Version="4.7.0" />
  </ItemGroup>

  <ItemGroup>
    <Reference Include="System.Web.Extensions">
      <HintPath>..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.Web.Extensions.dll</HintPath>
    </Reference>
  </ItemGroup>

  <ItemGroup>
    <Content Update="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

  <Import Project="PostDeployScripts\IncludeSources.targets" Condition="Exists('PostDeployScripts\IncludeSources.targets')" />
  <Import Project="..\PostDeployScripts\IncludeSources.targets" Condition="Exists('..\PostDeployScripts\IncludeSources.targets')" />

</Project>
c#
azure-devops
botframework
chatbot
azure-devops-rest-api
asked on Stack Overflow Oct 31, 2019 by Chaitanya N G

1 Answer

2

I am closing this Query as i got the idea by trying the idea from the post. and it worked.

So as i was explaining in my Try 2 code Converting the data into a JavascriptSerializer object in to a string called as JSON as given code starting from the line :

JavaScriptSerializer serializer = new JavaScriptSerializer();

Instead of doing this what i have done is created a class using the blog given above which has set; and get properties with variables as

OP path Value

 public class WorkItemData
    {
        public string op { get; set; } 
        public  string path { get; set; }
        public  string value { get; set; }
    }

In my actual bot code created a list variable:

List<WorkItemData> wiarray= new List<WorkItemData>;

Added data to class and array as shown in the blog link given above and then finally using the below line of code converted that to Json and storing into a variable:

string wijsondata = JsonConvert.SerializeObject(wiarray);

And using the remaining part of code given try 2 block given in my original question called the post method as it is now instead of Json variable i passed wijsondata

Content = new StringContent(wijsondata , Encoding.UTF8,"application/json-patch+json")

And it worked.

Thanks for all the help and ideas provided in the blog or in this post or outside post and apologies for any inconvenience it may have caused to any one.

answered on Stack Overflow Nov 1, 2019 by Chaitanya N G

User contributions licensed under CC BY-SA 3.0