I have a codeunit that worked well in BC on premise (before the need for OAuth) - it took the contents of a file and processed it using the following procedure in a codeunit exposed as a web service:
procedure FromWebService(BigTextVar: BigText) ErrorsReturned: Text[1024];
by using .Net - reading in the data from a file (My.Computer.FileSystem.ReadAllText into a string variable) and calling a Web Service object passing this variable.
What I’m struggling with is how to call this using OAuth.
I have set up the connections ok (I can successfully call a Page web service with some sample code I found).
But I can’t find sample .Net code that gets an OAuth token then calls a codeunit that has parameters (note my file data with contain carriage returns and spaces etc).
Has anything done this type of thing please, and can point me in the right direction for some sample code?
Using OAuth to Authenticate Business Central Web Services (OData and SOAP) - Business Central | Microsoft Docs
does this work? The same code down near the bottom has the C# code to authenticate and make a page call. (which is similar to the codeunit call)
about the bigtext, I wonder if the NAV variable in this code can handle it
Thanks Dustin. I had seen that site before and it didn’t work with the codeunit parameter.
Hi All. I have managed to find a solution to this issue. It involved building the SOAP wrapper. Extracts of the code (vb .Net) are below FYI:
Imports System.Threading
Imports Microsoft.Identity.Client
Imports System.Net.Http
Imports System.Net
Private _accessToken As String = String.Empty
Private client_id As String = My.Settings.ClientID '<-- enter the client_id guid here
Private tenant_id As String = My.Settings.Tenant '<-- enter either your tenant id here
Private client_secret As String = My.Settings.ClientSecret '<-- enter the client_id guid here
Private authority As String = $"https://login.microsoftonline.com/{tenant_id}"
Private scopes As New List(Of String)
GETTING THE TOKEN
scopes.Add($“https://api.businesscentral.dynamics.com/.default”)
Dim publicClientApp As IConfidentialClientApplication
publicClientApp = ConfidentialClientApplicationBuilder.Create(client_id).WithClientSecret(client_secret).WithAuthority(authority).Build()
Dim authResult As AuthenticationResult
Try
authResult = publicClientApp.AcquireTokenForClient(scopes).ExecuteAsync().Result()
Catch ex As MsalUiRequiredException
WriteLog($“Auth Exception: {ex.Message}”)
Exit Sub
End Try
_accessToken = authResult.AccessToken
BUILDING THE SOAP STRING - note that FromWebService is the name of the function within the codeunit, bigTextVar is the parameter in that function, FileContent is a string variable containing the whole file data
Dim BodyText As String
BodyText = "<?xml version = " & Chr(34) & "1.0" & Chr(34) & "?>"
BodyText = BodyText & "<soapenv:Envelope xmlns:soapenv=" & Chr(34) & "http://schemas.xmlsoap.org/soap/envelope/" & Chr(34) & " xmlns:log=" & Chr(34) & "urn:microsoft-dynamics-schemas/codeunit/LogisticsInvoiceImport" & Chr(34) & ">"
BodyText = BodyText & "<soapenv:Header/>"
BodyText = BodyText & "<soapenv:Body>"
BodyText = BodyText & "<log:FromWebService>"
BodyText = BodyText & "<log:bigTextVar>"
BodyText = BodyText & "<![CDATA[" & FileContent & "]]>"
BodyText = BodyText & "</log:bigTextVar>"
BodyText = BodyText & "</log:FromWebService>"
BodyText = BodyText & "</soapenv:Body>"
BodyText = BodyText & "</soapenv:Envelope>" ';
Dim soapEnvelopeXml As New System.Xml.XmlDocument
soapEnvelopeXml.LoadXml(BodyText)
CALLING THE WEB SERVICE, includes unwrapping the response
Dim OutputStr As String = “”
Try
Dim request As HttpWebRequest = HttpWebRequest.Create(UriL)
request.Headers.Add(“SOAPAction”, Chr(34) & “urn:microsoft-dynamics-schemas/codeunit/LogisticsInvoiceImport:FromWebService” & Chr(34))
request.Headers.Add(“Authorization”, "Bearer " & _accessToken)
request.PreAuthenticate = True
request.Accept = “application/json”
request.Method = “POST”
request.ContentType = “text/xml;charset=UTF-8”
Dim PutStream As System.IO.Stream = request.GetRequestStream()
soapEnvelopeXml.Save(PutStream)
Dim response As WebResponse
response = request.GetResponse()
Dim sr As New System.IO.StreamReader(response.GetResponseStream())
OutputStr = sr.ReadToEnd
Catch ex As Exception
OutputStr = ex.Message
End Try
If OutputStr <> "<return_value/>" Then
If InStr(OutputStr, "<return_value>") > 0 And InStr(OutputStr, "</return_value>") > 0 Then
OutputStr = Mid(OutputStr, InStr(OutputStr, "<return_value>") + 14)
OutputStr = Mid(OutputStr, 1, InStr(OutputStr, "</return_value>") - 1)
End If
WriteLog("Message from Process " & OutputStr)
Using outfile As New System.IO.StreamWriter(DirList(DirLoop) & "\Errors\" & RawFileName & ".error")
outfile.Write(OutputStr)
End Using
Else
System.IO.File.Move(DirList(DirLoop) & "\Errors\" & RawFileName, DirList(DirLoop) & "\Archive\" & RawFileName)
End If
Console.WriteLine(OutputStr)
1 Like