How to check EU VAT using VIES SOAP service in C# - c#

I have an ASP.NET website that needs to check a user-supplied VAT. The VIES Service can be used for that which exposes a SOAP API.
I need a dead-simple example on how to validate a VAT using this service. In PHP, it's these 4 lines: https://stackoverflow.com/a/14340495. For C#, I have found some articles from 2010 that do not work or are tens or even hundreds lines of "wrappers", "helper services" etc.
I don't need any of that, can someone provide PHP-like four-liner that would check VAT in C#? Thank you.

The simplest way I found is just to send an XML and parse it when it comes back:
var wc = new WebClient();
var request = #"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:urn=""urn:ec.europa.eu:taxud:vies:services:checkVat:types"">
<soapenv:Header/>
<soapenv:Body>
<urn:checkVat>
<urn:countryCode>COUNTRY</urn:countryCode>
<urn:vatNumber>VATNUMBER</urn:vatNumber>
</urn:checkVat>
</soapenv:Body>
</soapenv:Envelope>";
request = request.Replace("COUNTRY", countryCode);
request = request.Replace("VATNUMBER", theRest);
String response;
try
{
response = wc.UploadString("http://ec.europa.eu/taxation_customs/vies/services/checkVatService", request);
}
catch
{
// service throws WebException e.g. when non-EU VAT is supplied
}
var isValid = response.Contains("<valid>true</valid>");

Here is a self-sufficient (no WCF, no WSDL, ...) utility class that will check the VAT number and get information on the company (name and address). It will return null if the VAT number is invalid or if any error occurred.
Update 2022/10/17 : I have added namespace handling to parse the response as it seems the EU web service was modified. If you need the old version, just look at the history
// sample calling code
Console.WriteLine(EuropeanVatInformation.Get("FR89831948815"));
...
public class EuropeanVatInformation
{
private EuropeanVatInformation() { }
public string CountryCode { get; private set; }
public string VatNumber { get; private set; }
public string Address { get; private set; }
public string Name { get; private set; }
public override string ToString() => CountryCode + " " + VatNumber + ": " + Name + ", " + Address.Replace("\n", ", ");
public static EuropeanVatInformation Get(string countryCodeAndVatNumber)
{
if (countryCodeAndVatNumber == null)
throw new ArgumentNullException(nameof(countryCodeAndVatNumber));
if (countryCodeAndVatNumber.Length < 3)
return null;
return Get(countryCodeAndVatNumber.Substring(0, 2), countryCodeAndVatNumber.Substring(2));
}
public static EuropeanVatInformation Get(string countryCode, string vatNumber)
{
if (countryCode == null)
throw new ArgumentNullException(nameof(countryCode));
if (vatNumber == null)
throw new ArgumentNullException(nameof(vatNumber));
countryCode = countryCode.Trim();
vatNumber = vatNumber.Trim().Replace(" ", string.Empty);
const string ns = "urn:ec.europa.eu:taxud:vies:services:checkVat:types";
const string url = "http://ec.europa.eu/taxation_customs/vies/services/checkVatService";
const string xml = #"<s:Envelope xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'><s:Body><checkVat xmlns='" + ns + "'><countryCode>{0}</countryCode><vatNumber>{1}</vatNumber></checkVat></s:Body></s:Envelope>";
try
{
using (var client = new WebClient())
{
var doc = new XmlDocument();
doc.LoadXml(client.UploadString(url, string.Format(xml, countryCode, vatNumber)));
var response = doc.SelectSingleNode("//*[local-name()='checkVatResponse']") as XmlElement;
if (response == null || response["valid", ns]?.InnerText != "true")
return null;
var info = new EuropeanVatInformation
{
CountryCode = response["countryCode", ns].InnerText,
VatNumber = response["vatNumber", ns].InnerText,
Name = response["name", ns]?.InnerText,
Address = response["address", ns]?.InnerText
};
return info;
}
}
catch
{
return null;
}
}
}

On .NET platform it is common to consume a Web service so that we generate a proxy class. This can usually be done using Visual Studio "Add Web Reference" where you just fill in a path to the WSDL. An alternative is to generate source classes using wsdl.exe or svcutil.exe.
Then just consume this class and verifying VAT becomes a one-liner:
DateTime date = new checkVatPortTypeClient().checkVat(ref countryCode, ref vatNumber, out isValid, out name, out address);
Generating proxy provides strongly typed API to consume whole service and we don't need to manually create soap envelope and parse output text. It is much more easier, safer and generic solution than yours.

Updated: I've published this as a NuGet library.
https://github.com/TriggerMe/CSharpVatChecker
var vatQuery = new VATQuery();
var vatResult = await vatQuery.CheckVATNumberAsync("IE", "3041081MH"); // The Squarespace VAT Number
Console.WriteLine(vatResult.Valid); // Is the VAT Number valid?
Console.WriteLine(vatResult.Name); // Name of the organisation

Based on Pavel Hodek's:
Make sure you have the Microsoft WCF Web Service Reference
Provide extension installed for visual studio (I'm using VS 2017
Community).
In the solution explorer right click on Connected Services > Add Connected Service
Select the WCF extension.
Type in the URL provided by VIES
http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl to generate the Service class from the wsdl.
Press Go and select the service, give a proper name for the namespace e.g. Services.VATCheck
Press Finish, which will create a new folder and a file called reference.cs in the Connected Services rename the file to VATCheck which will also rename the Class.
In a controller use the following code to invoke the call, make sure it's async (it can take awhile to eventually load all the data)
public async Task<IActionResult> CheckVAT()
{
var countryCode = "BE";
var vatNumber = "123456789";
try
{
checkVatPortType test = new checkVatPortTypeClient(checkVatPortTypeClient.EndpointConfiguration.checkVatPort, "http://ec.europa.eu/taxation_customs/vies/services/checkVatService");
checkVatResponse response = await test.checkVatAsync(new checkVatRequest { countryCode = countryCode, vatNumber = vatNumber });
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
return Ok();
}
Please note that you can clean-up this call, but that's totally up to you.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BTWCheck.eu.europa.ec;
namespace BTWCheck
{
class Program
{
static void Main(string[] args)
{
// VS 2017
// add service reference -> button "Advanced" -> button "Add Web Reference" ->
// URL = http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl
string Landcode = "NL";
string BTWNummer = "820471616B01"; // VAT nr BOL.COM
checkVatService test = new checkVatService();
test.checkVat(ref Landcode, ref BTWNummer, out bool GeldigBTWNr, out string Naam, out string Adres);
Console.WriteLine(Landcode + BTWNummer + " " + GeldigBTWNr);
Console.WriteLine(Naam+Adres);
Console.ReadKey();
}
}
}

Related

Does ActiveMQ Artemis support getting messages from the ActiveMQ.Advisory.Queue?

I have a .NETcore application/client which has several defined endpoints to get data from the broker. One end point is to get a list of all of the addresses but when I run it it gives back an empty response. We are using amq7. Would the C# code need to be refactored to leverage Artemis? How would I be able to get Broker/Queue metrics in Artemis with .NET?
Below is an example of the code the code we are using from the ActiveMQ NMS website
using System;
using Apache.NMS;
using Apache.NMS.Util;
using Apache.NMS.ActiveMQ;
using Apache.NMS.ActiveMQ.Commands;
namespace AdvisoryExample
{
class AdvisoryExample
{
private IConnection connection;
private ISession session;
public const String QUEUE\_ADVISORY\_DESTINATION = "ActiveMQ.Advisory.Queue";
public const String TOPIC\_ADVISORY\_DESTINATION = "ActiveMQ.Advisory.Topic";
public const String TEMPQUEUE\_ADVISORY\_DESTINATION = "ActiveMQ.Advisory.TempQueue";
public const String TEMPTOPIC\_ADVISORY\_DESTINATION = "ActiveMQ.Advisory.TempTopic";
public const String ALLDEST\_ADVISORY\_DESTINATION = QUEUE\_ADVISORY\_DESTINATION + "," +
TOPIC\_ADVISORY\_DESTINATION + "," +
TEMPQUEUE\_ADVISORY\_DESTINATION + "," +
TEMPTOPIC\_ADVISORY\_DESTINATION;
AdvisoryExample()
{
IConnectionFactory factory = new ConnectionFactory();
connection = factory.CreateConnection();
connection.Start();
session = connection.CreateSession();
}
void EnumerateQueues()
{
Console.WriteLine("Listing all Queues on Broker:");
IDestination dest = session.GetTopic(QUEUE\_ADVISORY\_DESTINATION);
using(IMessageConsumer consumer = session.CreateConsumer(dest))
{
IMessage advisory;
while((advisory = consumer.Receive(TimeSpan.FromMilliseconds(2000))) != null)
{
ActiveMQMessage amqMsg = advisory as ActiveMQMessage;
if(amqMsg.DataStructure != null)
{
DestinationInfo info = amqMsg.DataStructure as DestinationInfo;
if(info != null)
{
Console.WriteLine(" Queue: " + info.Destination.ToString() );
}
}
}
}
Console.WriteLine("Listing Complete.");
}
The default broker.xml disables advisory support, e.g.:
<acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;amqpMinLargeMessageSize=102400;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpDuplicateDetection=true;supportAdvisory=false;suppressInternalManagementObjects=false</acceptor>
The key parameter is supportAdvisory=false which you can read more about in the documentation. You can set supportAdvisory=true or omit it entirely at which point you should be able to use advisories from your client.
Regarding other ways to get broker/queue metrics, ActiveMQ Artemis supports a number of different ways to access this data (e.g. JMX, HTTP via Jolokia, management messages, web console, CLI tools). You can read more about this in the documentation. The broker also supports exporting metrics via plugins so you can integrate with solutions like Prometheus.

Using MWS API to get FBA Inventory Reconciliation report data

I'm looking how to query undocumented MWS API for Inventory Reconciliation report (List of api names for seller central fulfillment reports ) using C# Client Library or any other client libraries, or using Amazon MWS Scratchpad - for the latter the rules to set the values of the fields MarketplaceIdList.Id.1, StartDate, EndDate and ReportOptions are unclear for me: I'm setting the first three fields as I usually do for the other report types and I leave the ReportOptions field empty - and the MWS API call via C# library for _GET_FBA_RECONCILIATION_REPORT_DATA_ report is accepted but it finally gets 'No Data Available' status.
UPDATE
Sample workaround code to download manually requested via sellercentral.amazon.com web site most recent _GET_FBA_RECONCILIATION_REPORT_DATA_ report using MWS API C# Client library:
//private string ACCESS_KEY_ID => ...
//private string SECRET_ACCESS_KEY => ...
//private string MERCHANT_ID => ...
//private string MAKETPLACE_ID => ...
//private string APPLICATION_NAME => ...
//private string APPLICATION_VERSION => ...
public void DownloadMostRecentFBAInventoryReconciliationReport(string downloadedReportFullPath)
{
string reportId = "";
string reportType = "_GET_FBA_RECONCILIATION_REPORT_DATA_";
var config = new MarketplaceWebService.MarketplaceWebServiceConfig();
config.ServiceURL = "https://mws.amazonservices.com";
config.SetUserAgentHeader(APPLICATION_NAME, APPLICATION_VERSION, "C#");
var service = new MarketplaceWebService.MarketplaceWebServiceClient(ACCESS_KEY_ID, SECRET_ACCESS_KEY, config);
// find most recent report id for '_GET_FBA_RECONCILIATION_REPORT_DATA_' report type
{
var request = new MarketplaceWebService.Model.GetReportRequestListRequest();
request.Merchant = MERCHANT_ID;
request.ReportTypeList = new MarketplaceWebService.Model.TypeList();
request.ReportTypeList.Type.Add(reportType);
var response = service.GetReportRequestList(request);
foreach (MarketplaceWebService.Model.ReportRequestInfo info in response.GetReportRequestListResult.ReportRequestInfo)
{
if (!info.ReportProcessingStatus.Equals("_DONE_")) continue;
reportId = info.GeneratedReportId;
break;
}
}
// if most recent reportId found - download report's (.csv) data file into {{ downloadedReportFullPath }}
if (!string.IsNullOrEmpty(reportId))
{
var request = new MarketplaceWebService.Model.GetReportRequest();
request.Merchant = MERCHANT_ID;
request.ReportId = reportId;
request.Report = File.Open(downloadedReportFullPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
var response = service.GetReport(request);
}
}

Azure Text Analytics using C# giving errors

I am trying to use code that I got from github: https://github.com/liamca/azure-search-machine-learning-text-analytics and the creating of an index works perfect, but the Keyphrase portion is giving me a 403 - Forbidden: Access is denied error. This happens in the TextExtractionHelper class on the following line of code:
if (!response.IsSuccessStatusCode)
{
throw new Exception("Call to get key phrases failed with HTTP status code: " +
response.StatusCode + " and contents: " + content);
}
Based on the information in the comments, I created an account at this link: https://datamarket.azure.com/account/keys and used the key that it provided, but I am getting the above error.
Here is the code in case you do not want to download from github:
class Program
{
static string searchServiceName = "<removed>"; // Learn more here: https://azure.microsoft.com/en-us/documentation/articles/search-what-is-azure-search/
static string searchServiceAPIKey = "<removed>";
static string azureMLTextAnalyticsKey = "<removed>"; // Learn more here: https://azure.microsoft.com/en-us/documentation/articles/machine-learning-apps-text-analytics/
static string indexName = "textanalytics";
static SearchServiceClient serviceClient = new SearchServiceClient(searchServiceName, new SearchCredentials(searchServiceAPIKey));
static SearchIndexClient indexClient = serviceClient.Indexes.GetClient(indexName);
static void Main(string[] args)
{
string filetext = "Build great search experiences for your web and mobile apps. " +
"Many applications use search as the primary interaction pattern for their users. When it comes to search, user expectations are high. They expect great relevance, suggestions, near-instantaneous responses, multiple languages, faceting, and more. Azure Search makes it easy to add powerful and sophisticated search capabilities to your website or application. The integrated Microsoft natural language stack, also used in Bing and Office, has been improved over 16 years of development. Quickly and easily tune search results, and construct rich, fine-tuned ranking models to tie search results to business goals. Reliable throughput and storage provide fast search indexing and querying to support time-sensitive search scenarios. " +
"Reduce complexity with a fully managed service. " +
"Azure Search removes the complexity of setting up and managing your own search index. This fully managed service helps you avoid the hassle of dealing with index corruption, service availability, scaling, and service updates. Create multiple indexes with no incremental cost per index. Easily scale up or down as the traffic and data volume of your application changes.";
// Note, this will create a new Azure Search Index for the text and the key phrases
Console.WriteLine("Creating Azure Search index...");
AzureSearch.CreateIndex(serviceClient, indexName);
// Apply the Machine Learning Text Extraction to retrieve only the key phrases
Console.WriteLine("Extracting key phrases from processed text... \r\n");
KeyPhraseResult keyPhraseResult = TextExtraction.ProcessText(azureMLTextAnalyticsKey, filetext);
Console.WriteLine("Found the following phrases... \r\n");
foreach (var phrase in keyPhraseResult.KeyPhrases)
Console.WriteLine(phrase);
// Take the resulting key phrases to a new Azure Search Index
// It is highly recommended that you upload documents in batches rather
// individually like is done here
Console.WriteLine("Uploading extracted text to Azure Search...\r\n");
AzureSearch.UploadDocuments(indexClient, "1", keyPhraseResult);
Console.WriteLine("Wait 5 seconds for content to become searchable...\r\n");
Thread.Sleep(5000);
// Execute a test search
Console.WriteLine("Execute Search...");
AzureSearch.SearchDocuments(indexClient, "Azure Search");
Console.WriteLine("All done. Press any key to continue.");
Console.ReadLine();
}
}
The below is in the TextExtractionHelper class:
/// <summary>
/// This is a sample program that shows how to use the Azure ML Text Analytics app (https://datamarket.azure.com/dataset/amla/text-analytics)
/// </summary>
public class TextExtraction
{
private const string ServiceBaseUri = "https://api.datamarket.azure.com/";
public static KeyPhraseResult ProcessText(string accountKey, string inputText)
{
KeyPhraseResult keyPhraseResult = new KeyPhraseResult();
using (var httpClient = new HttpClient())
{
string inputTextEncoded = HttpUtility.UrlEncode(inputText);
httpClient.BaseAddress = new Uri(ServiceBaseUri);
string creds = "AccountKey:" + accountKey;
string authorizationHeader = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(creds));
httpClient.DefaultRequestHeaders.Add("Authorization", authorizationHeader);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// get key phrases
string keyPhrasesRequest = "data.ashx/amla/text-analytics/v1/GetKeyPhrases?Text=" + inputTextEncoded;
Task<HttpResponseMessage> responseTask = httpClient.GetAsync(keyPhrasesRequest);
responseTask.Wait();
HttpResponseMessage response = responseTask.Result;
Task<string> contentTask = response.Content.ReadAsStringAsync();
contentTask.Wait();
string content = contentTask.Result;
if (!response.IsSuccessStatusCode)
{
throw new Exception("Call to get key phrases failed with HTTP status code: " +
response.StatusCode + " and contents: " + content);
}
keyPhraseResult = JsonConvert.DeserializeObject<KeyPhraseResult>(content);
}
return keyPhraseResult;
}
}
/// <summary>
/// Class to hold result of Key Phrases call
/// </summary>
public class KeyPhraseResult
{
public List<string> KeyPhrases { get; set; }
}
/// <summary>
/// Class to hold result of Sentiment call
/// </summary>
public class SentimentResult
{
public double Score { get; set; }
}
/// <summary>
/// Class to hold result of Language detection call
/// </summary>
public class LanguageResult
{
public bool UnknownLanguage { get; set; }
public IList<DetectedLanguage> DetectedLanguages { get; set; }
}
/// <summary>
/// Class to hold information about a single detected language
/// </summary>
public class DetectedLanguage
{
public string Name { get; set; }
/// <summary>
/// This is the short ISO 639-1 standard form of representing
/// all languages. The short form is a 2 letter representation of the language.
/// en = English, fr = French for example
/// </summary>
public string Iso6391Name { get; set; }
public double Score { get; set; }
}
UPDATE
After many hours of taking different sample code and trying to put them together, I finally got something "kind of" working. Here is all my code:
class Program
{
static string searchServiceName = "<removed>"; // Learn more here: https://azure.microsoft.com/en-us/documentation/articles/search-what-is-azure-search/
static string searchServiceAPIKey = "<removed>";
//static string azureMLTextAnalyticsKey = "<removed>"; // Learn more here: https://azure.microsoft.com/en-us/documentation/articles/machine-learning-apps-text-analytics/
static string indexName = "textanalytics";
static SearchServiceClient serviceClient = new SearchServiceClient(searchServiceName, new SearchCredentials(searchServiceAPIKey));
static SearchIndexClient indexClient = serviceClient.Indexes.GetClient(indexName);
static void Main()
{
MakeRequests();
Console.WriteLine("Hit ENTER to exit...");
Console.ReadLine();
}
static async void MakeRequests()
{
// Note, this will create a new Azure Search Index for the text and the key phrases
Console.WriteLine("Creating Azure Search index...");
AzureSearch.CreateIndex(serviceClient, indexName);
// Apply the Machine Learning Text Extraction to retrieve only the key phrases
Console.WriteLine("Extracting key phrases from processed text... \r\n");
KeyPhraseResult keyPhraseResult = await TextExtraction.ProcessText();
Console.WriteLine("Found the following phrases... \r\n");
foreach (var phrase in keyPhraseResult.KeyPhrases)
Console.WriteLine(phrase);
// Take the resulting key phrases to a new Azure Search Index
// It is highly recommended that you upload documents in batches rather
// individually like is done here
Console.WriteLine("Uploading extracted text to Azure Search...\r\n");
AzureSearch.UploadDocuments(indexClient, "1", keyPhraseResult);
Console.WriteLine("Wait 5 seconds for content to become searchable...\r\n");
Thread.Sleep(5000);
// Execute a test search
Console.WriteLine("Execute Search...");
AzureSearch.SearchDocuments(indexClient, "Azure Search");
Console.WriteLine("All done. Press any key to continue.");
Console.ReadLine();
}
}
Here is my TextExtractionHelper class:
public class TextExtraction
{
static string azureMLTextAnalyticsKey = "<Removed>"; // Learn more here: https://azure.microsoft.com/en-us/documentation/articles/machine-learning-apps-text-analytics/
private const string ServiceBaseUri = "https://westus.api.cognitive.microsoft.com/";
public static async Task<KeyPhraseResult> ProcessText()
{
string filetext = "Build great search experiences for your web and mobile apps. " +
"Many applications use search as the primary interaction pattern for their users. When it comes to search, user expectations are high. They expect great relevance, suggestions, near-instantaneous responses, multiple languages, faceting, and more. Azure Search makes it easy to add powerful and sophisticated search capabilities to your website or application. The integrated Microsoft natural language stack, also used in Bing and Office, has been improved over 16 years of development. Quickly and easily tune search results, and construct rich, fine-tuned ranking models to tie search results to business goals. Reliable throughput and storage provide fast search indexing and querying to support time-sensitive search scenarios. " +
"Reduce complexity with a fully managed service. " +
"Azure Search removes the complexity of setting up and managing your own search index. This fully managed service helps you avoid the hassle of dealing with index corruption, service availability, scaling, and service updates. Create multiple indexes with no incremental cost per index. Easily scale up or down as the traffic and data volume of your application changes.";
KeyPhraseResult keyPhraseResult = new KeyPhraseResult();
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(ServiceBaseUri);
// Request headers.
httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", azureMLTextAnalyticsKey);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
byte[] byteData = Encoding.UTF8.GetBytes("{\"documents\":[" +
"{\"id\":\"1\",\"text\":\"" + filetext + "\"},]}");
//byte[] byteData = Encoding.UTF8.GetBytes("{\"documents\":[" +
// "{\"id\":\"1\",\"text\":\"Build great search experiences for your web and mobile apps." +
// "Many applications use search as the primary interaction pattern for their users. When it comes to search, user expectations are high. They expect great relevance, suggestions, near-instantaneous responses, multiple languages, faceting, and more. Azure Search makes it easy to add powerful and sophisticated search capabilities to your website or application. The integrated Microsoft natural language stack, also used in Bing and Office, has been improved over 16 years of development. Quickly and easily tune search results, and construct rich, fine-tuned ranking models to tie search results to business goals. Reliable throughput and storage provide fast search indexing and querying to support time-sensitive search scenarios." +
// "Reduce complexity with a fully managed service. " +
// "Azure Search removes the complexity of setting up and managing your own search index. This fully managed service helps you avoid the hassle of dealing with index corruption, service availability, scaling, and service updates. Create multiple indexes with no incremental cost per index. Easily scale up or down as the traffic and data volume of your application changes.\"}," +
// "]}");
// Detect key phrases:
var keyPhrasesRequest = "text/analytics/v2.0/keyPhrases";
//var response = await CallEndpoint(httpClient, uri, byteData);
// get key phrases
using (var getcontent = new ByteArrayContent(byteData))
{
getcontent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await httpClient.PostAsync(keyPhrasesRequest, getcontent);
Task<string> contentTask = response.Content.ReadAsStringAsync();
string content = contentTask.Result;
if (!response.IsSuccessStatusCode)
{
throw new Exception("Call to get key phrases failed with HTTP status code: " +
response.StatusCode + " and contents: " + content);
}
keyPhraseResult = JsonConvert.DeserializeObject<KeyPhraseResult>(content);
//return await response.Content.ReadAsStringAsync();
}
}
return keyPhraseResult;
}
}
/// <summary>
/// Class to hold result of Key Phrases call
/// </summary>
public class KeyPhraseResult
{
public List<string> KeyPhrases { get; set; }
}
/// <summary>
/// Class to hold result of Sentiment call
/// </summary>
public class SentimentResult
{
public double Score { get; set; }
}
/// <summary>
/// Class to hold result of Language detection call
/// </summary>
public class LanguageResult
{
public bool UnknownLanguage { get; set; }
public IList<DetectedLanguage> DetectedLanguages { get; set; }
}
/// <summary>
/// Class to hold information about a single detected language
/// </summary>
public class DetectedLanguage
{
public string Name { get; set; }
/// <summary>
/// This is the short ISO 639-1 standard form of representing
/// all languages. The short form is a 2 letter representation of the language.
/// en = English, fr = French for example
/// </summary>
public string Iso6391Name { get; set; }
public double Score { get; set; }
}
So I am now able to pull the KeyPhrases from the text! But, now I am sitting with a problem where it doesnt seem like the JSON string is being deserialized and my keyPhraseResult is now getting a null value.
What am I missing ?
If anyone is able to help, I would greatly appreciate it.
Thanks!
So I got it working! With the help from this link: Deserializing JSON using C# to return items, which i posted to simplify where my issue was occurring now.
So what this code is doing is the following:
Creating an Index in Azure called textanalytics.
Creating a JSON string of the text provided.
Retrieving the KeyPhrases and adding these to the Index created in point 1 above.
Below is my entire code, in case it helps someone else:
(Please ensure that you add the relevant references from Nuget packages: Microsoft.Azure.Search and Newtonsoft.Json)
Program.cs(This is a console application):
using Microsoft.Azure.Search;
using System;
using System.Configuration;
using System.IO;
using System.Threading;
namespace AzureSearchTextAnalytics
{
class Program
{
static string searchServiceName = "<removed>"; // This is the Azure Search service name that you create in Azure
static string searchServiceAPIKey = "<removed>"; // This is the Primary key that is provided after creating a Azure Search Service
static string indexName = "textanalytics";
static SearchServiceClient serviceClient = new SearchServiceClient(searchServiceName, new SearchCredentials(searchServiceAPIKey));
static SearchIndexClient indexClient = serviceClient.Indexes.GetClient(indexName);
static void Main()
{
MakeRequests();
Console.WriteLine("Hit ENTER to exit...");
Console.ReadLine();
}
static async void MakeRequests()
{
// Note, this will create a new Azure Search Index for the text and the key phrases
Console.WriteLine("Creating Azure Search index...");
AzureSearch.CreateIndex(serviceClient, indexName);
// Apply the Machine Learning Text Extraction to retrieve only the key phrases
Console.WriteLine("Extracting key phrases from processed text... \r\n");
KeyPhraseResult keyPhraseResult = await TextExtraction.ProcessText();
Console.WriteLine("Found the following phrases... \r\n");
foreach (var phrase in keyPhraseResult.KeyPhrases)
Console.WriteLine(phrase);
// Take the resulting key phrases to a new Azure Search Index
// It is highly recommended that you upload documents in batches rather
// individually like is done here
Console.WriteLine("Uploading extracted text to Azure Search...\r\n");
AzureSearch.UploadDocuments(indexClient, "1", keyPhraseResult);
Console.WriteLine("Wait 5 seconds for content to become searchable...\r\n");
Thread.Sleep(5000);
// Execute a test search
Console.WriteLine("Execute Search...");
AzureSearch.SearchDocuments(indexClient, "Azure Search");
Console.WriteLine("All done. Press any key to continue.");
Console.ReadLine();
}
}
}
My TextExtractionHelper.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Newtonsoft.Json;
using System.Configuration; // get it from http://www.newtonsoft.com/json
using Newtonsoft.Json.Linq;
namespace AzureSearchTextAnalytics
{
/// </summary>
public class TextExtraction
{
static string azureMLTextAnalyticsKey = "<removed>"; // This key you will get when you have added TextAnalytics in Azure.
private const string ServiceBaseUri = "https://westus.api.cognitive.microsoft.com/"; //This you will get when you have added TextAnalytics in Azure
public static async Task<KeyPhraseResult> ProcessText()
{
string filetext = "Build great search experiences for your web and mobile apps. " +
"Many applications use search as the primary interaction pattern for their users. When it comes to search, user expectations are high. They expect great relevance, suggestions, near-instantaneous responses, multiple languages, faceting, and more. Azure Search makes it easy to add powerful and sophisticated search capabilities to your website or application. The integrated Microsoft natural language stack, also used in Bing and Office, has been improved over 16 years of development. Quickly and easily tune search results, and construct rich, fine-tuned ranking models to tie search results to business goals. Reliable throughput and storage provide fast search indexing and querying to support time-sensitive search scenarios. " +
"Reduce complexity with a fully managed service. " +
"Azure Search removes the complexity of setting up and managing your own search index. This fully managed service helps you avoid the hassle of dealing with index corruption, service availability, scaling, and service updates. Create multiple indexes with no incremental cost per index. Easily scale up or down as the traffic and data volume of your application changes.";
KeyPhraseResult keyPhraseResult = new KeyPhraseResult();
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(ServiceBaseUri);
// Request headers.
httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", azureMLTextAnalyticsKey);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
byte[] byteData = Encoding.UTF8.GetBytes("{\"documents\":[" +
"{\"id\":\"1\",\"text\":\"" + filetext + "\"},]}");
// Detect key phrases:
var keyPhrasesRequest = "text/analytics/v2.0/keyPhrases";
// get key phrases
using (var getcontent = new ByteArrayContent(byteData))
{
getcontent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await httpClient.PostAsync(keyPhrasesRequest, getcontent);
Task<string> contentTask = response.Content.ReadAsStringAsync();
string content = contentTask.Result;
if (!response.IsSuccessStatusCode)
{
throw new Exception("Call to get key phrases failed with HTTP status code: " +
response.StatusCode + " and contents: " + content);
}
var result = JsonConvert.DeserializeObject<RootObject>(content);
keyPhraseResult.KeyPhrases = result.documents[0].keyPhrases;
}
}
return keyPhraseResult;
}
}
public class Documents
{
public List<string> keyPhrases { get; set; }
public string id { get; set; }
}
public class RootObject
{
public List<Documents> documents { get; set; }
public List<object> errors { get; set; }
}
/// <summary>
/// Class to hold result of Key Phrases call
/// </summary>
public class KeyPhraseResult
{
public List<string> KeyPhrases { get; set; }
}
}
AzureSearch.cs:
using Microsoft.Azure.Search;
using Microsoft.Azure.Search.Models;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AzureSearchTextAnalytics
{
public class AzureSearch
{
public static void CreateIndex(SearchServiceClient serviceClient, string indexName)
{
if (serviceClient.Indexes.Exists(indexName))
{
serviceClient.Indexes.Delete(indexName);
}
var definition = new Index()
{
Name = indexName,
Fields = new[]
{
new Field("fileId", DataType.String) { IsKey = true },
new Field("fileText", DataType.String) { IsSearchable = true, IsFilterable = false, IsSortable = false, IsFacetable = false },
new Field("keyPhrases", DataType.Collection(DataType.String)) { IsSearchable = true, IsFilterable = true, IsFacetable = true }
}
};
serviceClient.Indexes.Create(definition);
}
public static void UploadDocuments(SearchIndexClient indexClient, string fileId, KeyPhraseResult keyPhraseResult)
{
List<IndexAction> indexOperations = new List<IndexAction>();
var doc = new Document();
doc.Add("fileId", fileId);
doc.Add("keyPhrases", keyPhraseResult.KeyPhrases.ToList());
indexOperations.Add(IndexAction.Upload(doc));
try
{
indexClient.Documents.Index(new IndexBatch(indexOperations));
}
catch (IndexBatchException e)
{
// Sometimes when your Search service is under load, indexing will fail for some of the documents in
// the batch. Depending on your application, you can take compensating actions like delaying and
// retrying. For this simple demo, we just log the failed document keys and continue.
Console.WriteLine(
"Failed to index some of the documents: {0}",
String.Join(", ", e.IndexingResults.Where(r => !r.Succeeded).Select(r => r.Key)));
}
}
public static void SearchDocuments(SearchIndexClient indexClient, string searchText)
{
// Search using the supplied searchText and output documents that match
try
{
var sp = new SearchParameters();
DocumentSearchResult<OCRTextIndex> response = indexClient.Documents.Search<OCRTextIndex>(searchText, sp);
foreach (SearchResult<OCRTextIndex> result in response.Results)
{
Console.WriteLine("File ID: {0}", result.Document.fileId);
Console.WriteLine("Key Phrases: {0}", string.Join(",", result.Document.keyPhrases));
}
}
catch (Exception e)
{
Console.WriteLine("Failed search: {0}", e.Message.ToString());
}
}
}
}
DataModel.cs
using Microsoft.Azure.Search.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AzureSearchTextAnalytics
{
[SerializePropertyNamesAsCamelCase]
public class OCRTextIndex
{
public string fileId { get; set; }
public string[] keyPhrases { get; set; }
}
}

Cannot find com.apiconnector.API in the dotMailer API for C#

I am trying to make sense of the dotMailer API for C#.
I have a class library where I intend to store the functionality that will consume the dotMailer API which references version 1.5 of the API. I also have a Service Reference set up from this WSDL
I was looking through the C# examples, but already I'm stumped! The following was pulled directly from here
Example of use in C#
/// <summary>
/// Adds a contact to an address book
/// </summary>
public void AddContactToAddressBook()
{
const string username = "apiuser-XXXXXXXXXXXX#apiconnector.com";
const string password = "password";
const int addressBookId = 1; // ID of the target address book
Console.WriteLine("AddContactToAddressBook");
Console.WriteLine("-----------------------");
// Get an instance to the web reference
com.apiconnector.API api = new com.apiconnector.API();
try
{
// we need a new contact
com.apiconnector.APIContact contact = new com.apiconnector.APIContact();
// populate the contact
contact.AudienceType = com.apiconnector.ContactAudienceTypes.B2B;
// populate the data fields
contact.DataFields = new com.apiconnector.ContactDataFields();
contact.DataFields.Keys = new string[3];
contact.DataFields.Values = new object[3];
contact.DataFields.Keys[0] = "FIRSTNAME";
contact.DataFields.Values[0] = "John";
contact.DataFields.Keys[1] = "LASTNAME";
contact.DataFields.Values[1] = "Smith";
contact.DataFields.Keys[2] = "POSTCODE";
contact.DataFields.Values[2] = "IP4 1XU";
// email address
contact.Email = "joe.smith#example.com";
contact.EmailType = com.apiconnector.ContactEmailTypes.PlainText;
contact.Notes = "This is a test only email";
contact.OptInType = com.apiconnector.ContactOptInTypes.Single;
// This method will create the contact required if it doesn't already exist within the dotMailer system,
// so we don't have to call CreateContact as a prerequisite.
//
// This method will also overwrite an existing contact, with the information provided here.
//
// This method will fail if you try to add a contact to the "Test" or "All Contacts" address books.
//
com.apiconnector.APIContact newContact = api.AddContactToAddressBook(username, password, contact, addressBookId);
// Did we get something back from the API ?
if (newContact != null)
{
Console.WriteLine("Contact added to address book {0} -> {1}", newContact.ID, addressBookId);
}
}
catch (SoapException ex) // catch any soap issues/errors from the web service
{
Console.WriteLine("Error -> {0}", ex.Message);
}
Console.WriteLine();
}
My problem is that the following line does not resolve.
com.apiconnector.API api = new com.apiconnector.API();
I have looked in namespace dotMailer.Sdk.com.apiconnector for API but it does not exist, so where is it?
Am I missing something?
Add the wsdl as a service reference. In the example below I've called it "ServiceReference1" (because that's the default and I was lazy). You then use the reference to the APISoapClient (I've called it Client) instead of "api" that you're having trouble declaring.
All compiles fine, I'm not going to execute it because I've no idea what shenanigans my random code snippet is going to cause for the server! Should point you in the right direction?
using WindowsFormsApplication1.ServiceReference1;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
const string username = "apiuser-XXXXXXXXXXXX#apiconnector.com";
const string password = "password";
const int addressBookId = 1; // ID of the target address book
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
AddContactToAddressBook();
}
private void AddContactToAddressBook()
{
using (ServiceReference1.APISoapClient Client = new ServiceReference1.APISoapClient())
{
APIContact Contact = new APIContact();
Contact.AudienceType = ContactAudienceTypes.B2B;
APIContact NewContact = Client.AddContactToAddressBook(username, password, Contact, addressBookId); // etc. etc.
}
}
}
}

How can I change this code to handle recurringpayment?

I am trying to implement Direct payment method as I have user's credit card information etc in my database. This is the sample that I am referring:
using System;
using System.Collections.Generic;
using System.Text;
using com.paypal.sdk.services;
using com.paypal.sdk.profiles;
using com.paypal.sdk.util;
using com.paypal.soap.api;
namespace ASPDotNetSamples
{
public class DoDirectPayment
{
public DoDirectPayment()
{
}
public string DoDirectPaymentCode(string paymentAction, string amount, string creditCardType, string creditCardNumber, string expdate_month, string cvv2Number, string firstName, string lastName, string address1, string city, string state, string zip, string countryCode, string currencyCode)
{
com.paypal.soap.api.DoDirectPaymentReq req = new com.paypal.soap.api.DoDirectPaymentReq();
NVPCallerServices caller = new NVPCallerServices();
IAPIProfile profile = ProfileFactory.createSignatureAPIProfile();
/*
WARNING: Do not embed plaintext credentials in your application code.
Doing so is insecure and against best practices.
Your API credentials must be handled securely. Please consider
encrypting them for use in any production environment, and ensure
that only authorized individuals may view or modify them.
*/
// Set up your API credentials, PayPal end point, API operation and version.
profile.APIUsername = "sdk-three_api1.sdk.com";
profile.APIPassword = "QFZCWN5HZM8VBG7Q";
profile.APISignature = "AVGidzoSQiGWu.lGj3z15HLczXaaAcK6imHawrjefqgclVwBe8imgCHZ";
profile.Environment = "sandbox";
caller.APIProfile = profile;
NVPCodec encoder = new NVPCodec();
encoder["VERSION"] = "51.0";
encoder["METHOD"] = "DoDirectPayment";
// Add request-specific fields to the request.
encoder["PAYMENTACTION"] = paymentAction;
encoder["AMT"] = amount;
encoder["CREDITCARDTYPE"] = creditCardType;
encoder["ACCT"] = creditCardNumber;
encoder["EXPDATE"] = expdate_month;
encoder["CVV2"] = cvv2Number;
encoder["FIRSTNAME"] = firstName;
encoder["LASTNAME"] = lastName;
encoder["STREET"] = address1;
encoder["CITY"] = city;
encoder["STATE"] = state;
encoder["ZIP"] = zip;
encoder["COUNTRYCODE"] = countryCode;
encoder["CURRENCYCODE"] = currencyCode;
// Execute the API operation and obtain the response.
string pStrrequestforNvp = encoder.Encode();
string pStresponsenvp = caller.Call(pStrrequestforNvp);
NVPCodec decoder = new NVPCodec();
decoder.Decode(pStresponsenvp);
return decoder["ACK"];
}
}
}
This is the link:
https://cms.paypal.com/cms_content/US/en_US/files/developer/nvp_DoDirectPayment_cs.txt
This works fine but my only question is how do I handle recurringpayment with this? What changes should I make in the sample?
Thanks in advance :)
Check the PayPal API Reference.
There is a method named CreateRecurringPaymentsProfile
Also read Handling Recurring Payments

Categories