Hi
I am able to test NAV2013R2 web service in Asp.net by following the link below:-
https://docs.microsoft.com/en-us/dynamics-nav/walkthrough--creating-and-using-a-codeunit-web-service--soap-
When I tried the same thing in Asp.net Core 2.1, by using "Connected Services" > "Microsoft WCF Web Service Reference Provider", I cannot get the same result.
Could someone show me the proper steps how to consume NAV2013R2 web service in Asp.net Core 2.1 project?
Thanks in advance
VH8000
Answers
Independent Consultant/Developer
blog: https://dynamicsuser.net/nav/b/ara3n
How about ASP.net Core 2.1 to use OData in NAV2013R2?
https://devblogs.microsoft.com/odata/asp-net-core-odata-now-available/
Independent Consultant/Developer
blog: https://dynamicsuser.net/nav/b/ara3n
I've managed to get the OData services working and can query the data easily enough, but when it comes to published CodeUnits, they're not exposed using OData and are only available as SOAP web services.
Using the same process as VH8000 (add a connected service in Visual Studio in my .Net Core 3.0 application) I can get the proxies for the SOAP web Services created in my application. I can even build request and response objects and get as far as firing the request to NAV, but the response is always the same, and that's that I'm using the wrong authentication scheme...
"The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'NTLM'."
For testing I ccreated a simple calculator codeunit with add, subtract functions etc, and use the code below, with different Impersonation Levels with no success...
public void OnPostAdd(CalcModel model)
{
FncAdd_Result fncAddResult = new FncAdd_Result();
svcCalculator_PortClient client = new svcCalculator_PortClient();
try
{
FncAdd fncAdd = new FncAdd(model.ValueA, model.ValueB);
client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Delegation;
client.ClientCredentials.Windows.ClientCredential = new NetworkCredential
{
Domain = Globals.WSDomain,
UserName = Globals.WSUsername,
Password = Globals.WSPassword
};
var binding = (BasicHttpBinding)client.Endpoint.Binding;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Ntlm;
fncAddResult = client.FncAdd(fncAdd);
}
catch (Exception ex)
{
ViewData["OutputMessage"] = ex.Message;
}
model.Result = fncAddResult.return_value;
}
has anyone got past this and if so, how?
Following the post here...
https://medium.com/grensesnittet/integrating-with-soap-web-services-in-net-core-adebfad173fb
... I have been able to successfully call a SOAP web service published in Business Central using an ASP.Net Core 3.0 web application.
The steps feel a bit clumsy, and its not clear to me why I have to change the reference.cs file that gets generated as part of the "Add Connected Service" process, but changing the code generated (as specified in section 3 of the post linked above) allowed me to connect successfully.
We enabled SSL on our SOAP service so that a HTTPS connection with Basic authentication worked. We also set "Enable NTLM Authentication" in the Business Central Administration tool.
Another thing I don't fully understand is that these changes only allow us to enter a username and password to the PortClient constructor (not the domain), which in turn are not passed to the ChannelFactory's Windows credentials, but just the standard credentials.
At some point we'll need to host our .Net Core site in the DMZ, and then we'll need to pass a full set of domain credentials to the SOAP services through the firewall on the LAN. I've not tested this yet and suspect there'll be another hurdle to clear when I do as our services are secured by a service account on the domain that's been configured as a user in the database (Business Central).
With the standard connected service code created when you "Add Connected Service", create your client using a small method as describe below to allow NTLM connectvity using .Net Core
private svcCalculator_PortClient GetCalculatorClient()
{
svcCalculator_PortClient client = new svcCalculator_PortClient();
client.ClientCredentials.Windows.ClientCredential = new NetworkCredential(Globals.WSUsername, Globals.WSPassword, Globals.WSDomain);
((BasicHttpBinding)client.Endpoint.Binding).Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
((BasicHttpBinding)client.Endpoint.Binding).Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Ntlm;
return client;
}