Dynamic Code Blocks

Microsoft Dynamics GP & .NET technical Blog by Tim Wappat

WCF Service on Server 2012

The page you are requesting cannot be served because of the extension 
configuration. If the page is a script, add a handler. If the file should be 
downloaded, add a MIME map.

My first experiences with Server 2012 had me puzzled for a few mins when trying to get some WCF service end points transferred from another older 2003 server.

It was solved by going into server manager, drilling down in the add roles and features to the server concerned, selecting Features. under the .NET Framework 4.5 features there was WCF Services, after checking the box and under that also selecting HTTP Activation to on, everything sprang to life.

There are also 3.5 versions of these too if the application is running on the older framework.

image

More...

VEIS Webservice matchcode error

Something changed this week with the VEIS web service that provides validation of European tax registration numbers.

http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl

All of a sudden we get an error! The SOAP error on deserialization is:

'Invalid enum value '3' cannot be deserialized into type 'canford.checkVATWebservice.matchCode'

I regenerated the SOAP reference in Visual Studio, -still not working.

It seems the soap response is containing an invalid (according to the WSDL) value of 3 for the type match code that is returned.

I’ve emailed the address provided for support, no response yet, so to get us running again I’ve added in this as a valid enum, however I have no idea of what the value of 3 actually means!

To fix, edit the Reference.vb file generated after refreshing the reference, found under your service reference directory,  (this example in VB.NET)

<System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0"),  _
System.Runtime.Serialization.DataContractAttribute(Name:="matchCode", [Namespace]:="urn:ec.europa.eu:taxud:vies:services:checkVat:types")> _
Public Enum matchCode As Integer

<System.Runtime.Serialization.EnumMemberAttribute(Value:="1")> _
_1 = 0

<System.Runtime.Serialization.EnumMemberAttribute(Value:="2")> _
_2 = 1

End Enum

 

Adding

<System.Runtime.Serialization.EnumMemberAttribute(Value:="3")> _        _3 = 2
to give this:
<System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0"),  _
System.Runtime.Serialization.DataContractAttribute(Name:="matchCode", [Namespace]:="urn:ec.europa.eu:taxud:vies:services:checkVat:types")> _
Public Enum matchCode As Integer

<System.Runtime.Serialization.EnumMemberAttribute(Value:="1")> _
_1 = 0

<System.Runtime.Serialization.EnumMemberAttribute(Value:="2")> _
_2 = 1

<System.Runtime.Serialization.EnumMemberAttribute(Value:="3")> _
_3 = 2
End Enum

Now it will work again. I expect this will be fixed sometime after this post, but for those of you struggling with this issue at least you know what to do now!

Dynamics GP real time EU tax registration number validation using VIES

Member states of the European Union expose thier VAT (Tax Registration Number) validation to the masses via VIES. Below is an example using Amazon’s VAT registration details against the service on the EU website.
image

image

 

Here the member state to which the organisation belongs has been selected, then the VAT number has been entered allowing for validity check. In the next screen we see the response to clicking the verifty button.

image

– open data goodness! - now for the cool bit…

Webservice

If you hunt under the FAQ, buried in there, it turns out there is a SOAP webservice available that does the same thing!

http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl

This WSDL URL is our key to some great functionality for Dynamics GP.

In Visual Studio For Dynamics GP Add-in project create a WCF reference to the VIES SOAP webservice.
In your proxy class you will find checkVatPortTypeClient.CheckVat as a method. This is the one we are after, supply the parameters and by reference the results will be returned

. image

We then create a visual studio add in event handler to fire on the user leaving the Tax Registration field of relevant forms in GP. Hence we can validate the VAT number the user has entered! So in our Add in project in the event handler for the options window Tax Registration Field we handle the event.

Public Shared Sub TaxRegNumberValidateBeforeOriginal(Sender As Object, e As System.ComponentModel.CancelEventArgs)
Try
Dim CustomerMaintOptionsForm As MicrosoftDynamicsGpModifiedDictionary.RmCustomerMaintenanceForm.RmCustomerOptionsWindow = _
MicrosoftDynamicsGpModified.Forms.RmCustomerMaintenance.RmCustomerOptions
If Not CustomerMaintOptionsForm.TaxRegistrationNumber.IsEmpty Then
If Windows.Forms.MessageBox.Show("Remember to update address intrastats field too." & vbCrLf & "Do you want to validate this number?", "Validate?", _
Windows.Forms.MessageBoxButtons.YesNo, Windows.Forms.MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then
Using oVATNumberValidationForm As New VATNumberValidation
oVATNumberValidationForm.VatNumber = CustomerMaintOptionsForm.TaxRegistrationNumber.Value
If oVATNumberValidationForm.ShowDialog() = vbOK Then
e.Cancel = True
Else
e.Cancel = True
End If
CustomerMaintOptionsForm.TaxRegistrationNumber.Value = oVATNumberValidationForm.VatNumber
End Using
End If
End If
Catch ex As Exception
Windows.Forms.MessageBox.Show("TaxRegNumberValidateBeforeOriginal" & vbCrLf & ex.ToString)
End Try
End Sub

Using the address of the company being looked up, we select the state code from the combo box (could automate this), we then supply to the webservice on hitting the validate button. A windows form shows the results of the validation to the user. If the supplied details fail validation we show the windows form to the user so they can correct the issue and try again. On closing the form we update the Tax Registration Field.

image

Private Sub btnValidate_Click(sender As System.Object, e As System.EventArgs) Handles btnValidate.Click
If txtVATNumber.Text.Length > 0 And cbxMemberState.SelectedIndex <> -1 Then
Dim oStringBuilder As New Text.StringBuilder
Dim o As New VATChecker.checkVatPortTypeClient
Dim ovalid As Boolean
Dim oName As String = String.Empty
Dim oAddress As String = String.Empty
Dim oResult As String = String.Empty
Dim oSelectedCountryCode As String = CStr(cbxMemberState.SelectedItem).Split(CChar(("-")))(0)

oResult = o.checkVat(oSelectedCountryCode, txtVATNumber.Text, ovalid, oName, oAddress)
If ovalid Then
oStringBuilder.AppendLine(oName)
oStringBuilder.AppendLine(oAddress)
oStringBuilder.AppendLine(oResult)
txtResults.Text = oStringBuilder.ToString
Else
txtResults.Text = "INVALID"
End If

Else
Windows.Forms.MessageBox.Show("Enter VAT number and select member state")
End If


End Sub

Conclusion

This is a rough example, the webservice call can be asynchronous, the country code derived from addresses, more error checking and neater presentation of the results, window could be derived from Dex windows for familiar Dex styles, however this post is more about what is possible in twenty mins with Dynamics GP plugins and data opened to the world via webservices.

Optionally, if the details of the your company are passed to the service (state & VAT number), then a consultation number is returned which is proof that you have looked up and validated the VAT number should you be challenged on that fact, but this is optional.

Note:

Different countries have maintenance windows where this service will not work check the VIES website for details

eConnect: The creator of this fault did not specify a Reason

eConnect WCF exception handling

For this example a WCF service reference to the server endpoint running the GP2010 eConnect integration service as a reference named “GPeConnect” is used.

If an exception were to occur from eConnect on say the CreateEnity mehods, and the exception examined as type system.exception, then the following message is found from ex.message,

System.ServiceModel.FaultException: The creator of this fault did not specify a Reason

To retrieve the error message from econnect that we are interested in, use the System.ServiceModel.FaultException class as shown below. By accessing the Detail.Message property, it is possible to get message of interest.

More...