Programatically fill TFS New Bug workitem from VBA - ms-access

I am wondering if it is possible to have VBA (Access) open a TFS Bug report webpage and fill in the description ?
While I am able to open the page I have not yet found a way to populate the description and potently other fields.
Perhaps one of the experts knows?

I wouldn't try to do what you are working on.
One, trusting a buggy application to correctly report its own bugs isn't a great idea. But beyond that you will be trying to attach Access to TFS.
That being said you can do this entirely automated. Put in some error trapping and then what you are looking to do is how to call TFS APIs. But you may or may not have to install some third part tools etc.
Starting point TFS API

The way I finally did it is to use a dll to interface between access and tfs...
For anyone trying to do the same here is the code...
Imports Microsoft.TeamFoundation.Client
Imports Microsoft.TeamFoundation.WorkItemTracking.Client
Imports Microsoft.TeamFoundation.WorkItemTracking.Common
Imports System.Runtime.InteropServices
<ComClass(TFSInterOp.ClassId, TFSInterOp.InterfaceId, TFSInterOp.EventsId)> Public Class TFSInterOp
Public Const ClassId As String = "14306fc5-1492-42d6-a032-bc4348508dd3"
Public Const InterfaceId As String = "288339cb-0c2e-45fd-8005-e5fed401f0cc"
Public Const EventsId As String = "723327dc-7777-44e4-b291-9299027665eb"
Public Sub New()
End Sub
Public Function InsertBugWorkItem(Title As String, Desc As String) As String
Dim tfsServer As String = My.Settings("TfsFullPath").ToString ' {YOUR TFS SERVER PATH}
Dim strAssUser As String = My.Settings("AssignTo").ToString
Dim teamFoundationServer1 As Microsoft.TeamFoundation.Client.TfsTeamProjectCollection = Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory.GetTeamProjectCollection(New Uri(tfsServer))
Dim workItemStore1 As New WorkItemStore(teamFoundationServer1)
teamFoundationServer1.Authenticate()
Dim WorkItemStore As WorkItemStore = New WorkItemStore(tfsServer)
Dim tfsProject As Project = WorkItemStore.Projects(0)
Dim wIType As WorkItemType = tfsProject.WorkItemTypes("Bug")
Dim workItem As WorkItem = New WorkItem(wIType)
Dim wiStore = teamFoundationServer1.GetService(Of WorkItemStore)()
Dim Project = wiStore.Projects
Dim Area = Project.Item(0).AreaRootNodes("BITS").Id ' The project to add the work item to
' Prefill items
workItem.Title = Title
workItem.Description = Desc
workItem.AreaId = Project.Item(0).AreaRootNodes("BITS").Id
workItem.Fields("Assigned To").Value = strAssUser
workItem.Fields("System Info").Value = "Access V 1.1.25"
workItem.Fields("Repro Steps").Value = Desc
Dim result As ArrayList = workItem.Validate()
If result.Count > 0 Then
Return (result(0).ToString + "There was an error adding this work item to the work item repository")
Else
workItem.Save()
End If
' Open the new item in explorer
Dim myService = teamFoundationServer1.GetService(Of TswaClientHyperlinkService)()
Dim myUrl = myService.GetWorkItemEditorUrl(workItem.Id)
Dim oProcess As New System.Diagnostics.Process()
oProcess.StartInfo.FileName = myUrl.ToString
oProcess.Start()
Return "OK"
End Function
End Class

Related

Deserialize and serialize Json data in Winform

I have a winform with a combobox and some textboxes. I get the Json data via REST API and deserialize it via Json.NET and a class file.
The JsonHelper
Imports Newtonsoft.Json
Public Module JsonHelper
Public Function FromClass(Of T)(data As T, Optional isEmptyToNull As Boolean = False, Optional jsonSettings As JsonSerializerSettings = Nothing) As String
Dim response As String = String.Empty
If Not EqualityComparer(Of T).Default.Equals(data, Nothing) Then
response = JsonConvert.SerializeObject(data, jsonSettings)
End If
Return If(isEmptyToNull, (If(response = "{}", "null", response)), response)
End Function
Public Function ToClass(Of T)(data As String, Optional jsonSettings As JsonSerializerSettings = Nothing) As T
Dim response = Nothing
If Not String.IsNullOrEmpty(data) Then
response = If(jsonSettings Is Nothing,
JsonConvert.DeserializeObject(Of T)(data),
JsonConvert.DeserializeObject(Of T)(data, jsonSettings))
End If
Return response
End Function
End Module
Imports Newtonsoft.Json
Namespace Models
Public Class Header
<JsonProperty("Name")>
Public Property Name As String
<JsonProperty("DisplayAt")>
Public Property DisplayAt As String
End Class
The Class file
Public Class DataSource
<JsonProperty("Id")>
Public Property Id As String
<JsonProperty("Name")>
Public Property Name As String
<JsonProperty("Headers")>
Public Property Headers As Header()
<JsonProperty("Rows")>
Public Property Rows As String()()
<JsonProperty("TotalRows")>
Public Property TotalRows As Integer
<JsonProperty("LastUpdated")>
Public Property LastUpdated As DateTime
<JsonProperty("CompanyId")>
Public Property CompanyId As Integer
End Class
Public Class Category
<JsonProperty("DataSource")>
Public Property DataSource As DataSource
End Class
End Namespace
The combobox is populated with data from the Json file and via bindingsource the textboxes are connected to the combobox. So if you select another row, the values of the textboxes change.
The bindingsource
Dim bindingSource As BindingSource = New BindingSource()
bindingSource.DataSource = dt
bindingSource.Sort = "Weergave DESC"
ListBox1.DataSource = bindingSource
ListBox1.DisplayMember = "Weergave"
ListBox1.ValueMember = "Id"
'ListBox1.Sorted = True
txtWeergave.DataBindings.Clear()
txtWeergave.DataBindings.Add(New Binding("Text", ListBox1.DataSource, "Weergave", True, DataSourceUpdateMode.OnPropertyChanged))
txtProjectnaam.DataBindings.Clear()
txtProjectnaam.DataBindings.Add(New Binding("Text", ListBox1.DataSource, "Projectnaam", True, DataSourceUpdateMode.OnPropertyChanged))
txtProjectnummer.DataBindings.Clear()
txtProjectnummer.DataBindings.Add(New Binding("Text", ListBox1.DataSource, "Projectnummer", True, DataSourceUpdateMode.OnPropertyChanged))
txtServicemonteur.DataBindings.Clear()
txtServicemonteur.DataBindings.Add(New Binding("Text", ListBox1.DataSource, "Servicemonteur", True, DataSourceUpdateMode.OnPropertyChanged))
I wan't to make some changes to the data and update the database via a PUT request.
Therefore I made the following routine:
Private Sub PutData()
Dim request As WebRequest = WebRequest.Create("my url")
request.ContentType = "application/json"
request.Method = "PUT"
' Get the response.
Dim response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)
' Get the stream containing content returned by the server.
Dim dataStream As Stream = response.GetResponseStream()
' Open the stream using a StreamReader for easy access.
Dim reader As New StreamReader(dataStream)
' Read the content.
Dim responseFromServer As String = reader.ReadToEnd()
'Dim JObject As Object
Dim rawJson As String = responseFromServer
Dim dataSource As String = JsonHelper.FromClass(Of Category)(rawJson).DataSource
End Sub
The following things are not clear for me.
If I make changes in the textbox, the changes are also made in the combobox because they have been connected with eachother via a bindingsource. But does the values also change in the Class file?
How can I make changes to the values of the textboxes and update the datasource via a PUT request?
It's not completely clear becacuse some things are missing from your question, such as your binding configuration, but..
Generally I wouldn't expect things to be that "when I change the textbox the combo will change". Let's take some artificial example of a Person class with Name and Ethnicity. Name is a string and would be bound to a textbox. Ethnicity is a fixed list of values, and I would expect a combo to be bound up such that the combo's datasource, displaymember and valuememeber related to the columns/properties of a list of ethnicities, and then the combo's selectedvalue be bound to the person's ethnicity setting. This way changing the selected item in the combo edits their ethnicity to one of the other values in the fixed list of ethnicities. Changing the value displayed in the name box doesn't change anything about the ethnicity. If you have a list of multiple Person that the bindingsource is managing, then you can navigate the bindingsource to show different people and edit them. It's probably easiest to see if you also add a datagridview, albeit temporarily, bound to the same bindingsource that persons are bound through; changing the current row of the grid navigates the bindingsource and the textbox/combobox will change to show the details for the new person
The PUT request is easier to answer; you formulate a block of json for the server to work on by re-serializing your edited class to JSON, and then send it as the body of the put request
request.Method = "PUT"
'formulate a body
Dim postData = JsonHelper.FromClass(editedPerson)
Dim encoding As New ASCIIEncoding() 'or whatever
Dim byte1 As Byte() = encoding.GetBytes(postData)
request.ContentType = "application/json"
request.ContentLength = byte1.Length
Dim reqStream = request.GetRequestStream()
reqStream.Write(byte1, 0, byte1.Length)
reqStream.Close()
' Get the response.
Dim response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)
By the way, in C# at least, you can right click your project name and choose Add REST Client, give it the URL of the swagger/openapi descriptor of your web service and it will make all the client classes for you which can simplify interaction a lot. Though it's a C# only thing (it's based on autorest which I don't think supports VB), C# and VB are the same thing internally, so you can add a C# project alongside your VB one purely for purposes of creating a rest client, and then import a reference to the c# project into your VB one

Sending a json document using a supplied certificate

I have been supplied a certificate that is required to send a json claim to an uri that has an api for sending the claim. The line in error is: handler.ClientCertificates.Add(certificate)
The following is my code:
Public Shared Sub Main()
Dim path As String = "E:\DRDRW_Update\Web Based Billing\vendorsupplied.pfx"
Dim password As String = "Password"
Dim strGateway As String = "https://MCE/api/WebServiceClaim"
Dim collection = New X509Certificate2Collection()
collection.Import(path, password, X509KeyStorageFlags.Exportable)
Dim certificate = collection(0)
Dim PathClaim As String = "E:\Sample Claim Submission JSON.txt"
Dim fi As New IO.FileInfo(PathClaim)
Dim jsonclaim As String = IO.File.ReadAllText(fi.FullName)
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Dim handler As New WebRequestHandler()
handler.ClientCertificates.Add(certificate)
' custom certificate validation handler to ignore untrusted remote certificate
ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf ValidateServerCertificate)
Using client = New HttpClient(handler)
Dim serializedProduct = JsonConvert.SerializeObject(jsonclaim)
Dim content = New StringContent(serializedProduct, Encoding.UTF8, "application/json")
content.Headers.Add("header1", "header2") ' require header
content.Headers.Add("token", "xxxxxxx-yyyy-zzzz")
Dim result = client.PostAsync(strGateway, content).Result ' ensures task is synchronous
' deserialize the saveresultmodel from the WS response and check for claim validation errors
Dim success As Boolean = False
If result.IsSuccessStatusCode Then
Dim resultResult As String = result.Content.ReadAsStringAsync().Result
Dim claimResult = JsonConvert.DeserializeObject(resultResult)
If claimResult.Errors.Count = 0 Then
success = True
Else
' output error results to console
For Each [error] In claimResult.Errors
Console.WriteLine(JsonConvert.SerializeObject([error]))
Next [error]
End If
End If
End Using
End Sub
Public Class WebRequestHandler
Inherits HttpClientHandler
End Class
The issue is that you have declared your own class for the WebRequestHandler. This is not the same as the System.Net.Http.WebRequestHandler.
Visual Studio had a "nice" feature offering to do this for you when it discovers a missing reference with something like "Generate Class for WebRequestHandler." This usually happens when you copy/paste code from another source and the reference was not fully defined. I never take this option and find it a weird way to approach writing code.
You do need to change your code to reference the correct handler like so.
Dim handler As New System.Net.Http.WebRequestHandler
The reason you are getting an error with that is that your project now needs a reference to another assembly (dll) with that class in it. To figure this out, I used google to find the documentation page here and noted this text: Assembly:
System.Net.Http.WebRequest (in System.Net.Http.WebRequest.dll).
This tells us to add the System.Net.Http.WebRequest reference to the project in order to access this class.
I had two issues, the first was answered by #GMan80013 by putting a reference to System.Net.Http.WebRequest.dll. The other was caused by the use of self-signing certificates. The ServicePointManager.ServerCertificateValidationCallback function needs to return true to ignore the issue of certificate validation caused by self-signed certificates.

ServiceStack.Text reading json results not working

I am just trying to figure out the best way to deserialize a json string returned from a 3rd party api call. I read ServiceStack is fast so want to try it out. No experience and here is what I have done:
Opened Visual Studio 2013
Created new project Windows Forms Application
Installed ServiceStack.Text (based on https://servicestack.net/download)
Added a button (btnView) and textbox (txtOutput)
Add code to btnView_Click event
Private Sub btnView_Click(sender As Object, e As EventArgs) Handles btnView.Click
Me.Cursor = Cursors.WaitCursor
Dim wp As New WebPost 'this allows to pass url and return results
wp.URL = "xxxx"
Dim sJSONRetVal As String = wp.Request(String.Empty, True)
'sJSONRetVal return values looks like the following:
'{"complaints":[{"feedback_type":"abuse","subject":"Sales Agent Position"},{"feedback_type":"abuse","subject":"Sales Agent Position"}],"message":"OK","code":0}
'ServiceStack.Text example
Dim t As SMTP_Complaints = ServiceStack.Text.JsonSerializer.DeserializeFromString(Of SMTP_Complaints)(sJSONRetVal)
'For Each xi As SMTP_Complaints In t
' txtOutput.Text &= xi.mail_from & vbCrLf
'Next
wp = Nothing
txtOutput.Text = t.ToString
Me.Cursor = Cursors.Default
End Sub
Public Class SMTP_Complaints
Dim _feedback_type As String = ""
Dim _subject As String = ""
Public Property feedback_type As String
Get
Return _feedback_type
End Get
Set(value As String)
_feedback_type = value
End Set
End Property
Public Property subject As String
Get
Return _subject
End Get
Set(value As String)
_subject = value
End Set
End Property
End Class
The above doesn't seem to get any data. how would I loop through the data returned and return the data from both instances? Just not sure how I need to set this up to read the json data and then be able to output.
Based on the returned JSON of:
{"complaints":[{"feedback_type":"abuse","subject":"Sales Agent Position"},{"feedback_type":"abuse","subject":"Sales Agent Position"}],"message":"OK","code":0}
You will need two DTOs to deserialise this result.
I have used auto implemented properties here to simplify the complexity of the code. If you use an older version of VB, you'll need to expand these out to include a backing field with get and set method.
Public Class SMTP_Complaint
Public Property feedback_type As String
Public Property subject As String
End Class
Public Class SMTP_ComplaintsResponse
Public Property complaints As SMTP_Complaint()
Public Property message As String
Public Property code As Integer
End Class
You need the SMTP_ComplaintsResponse class because your complaints are wrapped in your JSON response.
Then to deserialise the response:
Dim response = JsonSerializer.DeserializeFromString(Of SMTP_ComplaintsResponse)(sJSONRetVal)
And your complaints are then accessible:
For Each complaint As var In response.complaints
Console.WriteLine("Type: {0}, Subject {1}", complaint.feedback_type, complaint.subject)
Next

Issue with loading report

I have designed a report using Telerik Report Designer 2013 Q3 and added it in my project folder. Now i need to load it with available parameters for the report
For that i used the code as below
Private Sub DeserialiseXmlAndGenerateReport(strFilePath As String)
Dim settings As New XmlReaderSettings()
settings.IgnoreWhitespace = True
Dim myReportBook As Telerik.Reporting.ReportBook = New Telerik.Reporting.ReportBook
Using xmlReader As System.Xml.XmlReader = System.Xml.XmlReader.Create(Server.MapPath(strFilePath), settings)
Dim xmlSerializer As New Telerik.Reporting.XmlSerialization.ReportXmlSerializer()
Dim reportWMS As Telerik.Reporting.Report = DirectCast(xmlSerializer.Deserialize(xmlReader), Telerik.Reporting.Report)
With reportWMS
.DocumentMapText = ""
.ReportParameters("projectNo").Value = _projectNo
.ReportParameters("dnHeaderNo").Value = _value
.ReportParameters("transferType").Value = _TransferType
ReportViewer1.DocumentMapVisible = False
ReportViewer1.ShowDocumentMapButton = False
End With
myReportBook.Reports.Add(reportWMS)
End Using
Dim reportSource = New Telerik.Reporting.InstanceReportSource
reportSource.ReportDocument = myReportBook
ReportViewer1.ReportSource = reportSource
ReportViewer1.RefreshReport()
End Sub
All the values for report parameters are supplied. But not getting any output. There is no exception fired. But a blank screen with a toolbar only gets loaded. Please help me

Get schema name for dependent objects with SMO

Using a source script component in SSIS, I am attempting to retreive details of all objects which depend on a table. So far, I have the object type and name but can't retreive the schema. Does anyone know how to acheive this in SMO?
My script component code is:
' Microsoft SQL Server Integration Services user script component
' This is your new script component in Microsoft Visual Basic .NET
' ScriptMain is the entrypoint class for script components
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
Imports Microsoft.SqlServer.Management.Smo
Imports Microsoft.SqlServer.Management.Common
Public Class ScriptMain
Inherits UserComponent
Public Overrides Sub CreateNewOutputRows()
'
'
'
Dim TargetSQLServer As Server
Dim TargetDatabase As Database
Dim TargetTable As Table
Dim uc As New UrnCollection()
Dim dw As New DependencyWalker
Dim dt As DependencyTree
Dim dc As DependencyCollection
Dim dcn As DependencyCollectionNode
Dim sp As New Scripter
Dim outputString As String
TargetSQLServer = New Server("localhost")
TargetDatabase = TargetSQLServer.Databases("AdventureWorks")
For Each TargetTable In TargetDatabase.Tables
' Exclude these objects
If TargetTable.IsSystemObject = False Then
uc = New UrnCollection()
uc.Add(TargetTable.Urn)
sp = New Scripter
sp.Server = TargetSQLServer
' Get dependencies
dw = New DependencyWalker
dw.Server = TargetSQLServer
dt = dw.DiscoverDependencies(uc, DependencyType.Children)
sp = New Scripter(TargetSQLServer)
dc = New DependencyCollection
dc = sp.WalkDependencies(dt)
outputString = ""
For Each dcn In dc
Me.Output0Buffer.AddRow()
Me.Output0Buffer.Database = TargetDatabase.Name.ToString
Me.Output0Buffer.Table = TargetTable.Name.ToString
outputString = dcn.Urn.ToString
Me.Output0Buffer.Dependency.AddBlobData(Text.Encoding.GetEncoding(1252).GetBytes(outputString))
Me.Output0Buffer.ObjectType = dcn.Urn.Type.ToString
outputString = dcn.Urn.GetNameForType(dcn.Urn.Type.ToString).ToString
Me.Output0Buffer.ObjectName.AddBlobData(Text.Encoding.GetEncoding(1252).GetBytes(outputString))
outputString = ""
Me.Output0Buffer.Schema.AddBlobData(Text.Encoding.GetEncoding(1252).GetBytes(outputString))
Next
End If
Next
End Sub
End Class
Hey ekoner,
I have working code that walks the dependency tree in databases, and resolved the issue with simple string parsing.
Your urn will be returned is in the form of
///StoredProcedure[#Name='uspUpdateEmployeeHireInfo' and #Schema='HumanResources']
Just parse for #Name and then for #Schema.
Download the source code for DBSourceTools : http://dbsourcetools.codeplex.com
Have a look at DBSourceToolsLib.SysObjects.UrnParser
And also DBSourceToolsLib.SysObjects.SODependencyTree for working examples.