Azure, Cognitive services, Connected Field Service

Invalid subscription key error when connecting Azure cognitive services Face API

Recently during an integration scenario with D365 Field services in order to identify if the person making a change to the Customer asset is an employee or not we spinned up an Azure Face API service and on trying to connect it from an Azure function we were getting Invalid key exception.

We were using the Face API client library which defaults to west US endpoint of the service but our service was in EastUS.

Default endpoint: https://westus.api.cognitive.microsoft.com/face/v1.0/

The solution is to override the endpoint to https://eastus.api.cognitive.microsoft.com/face/v1.0/ which can be done by using another constructor of the FaceServiceClient class

FaceServiceAPIClient = new FaceServiceClient("Face API subscription key", "https://eastus.api.cognitive.microsoft.com/face/v1.0");

 

 

Advertisements
Standard
C#, Web Application

Adding User-Agent HTTP header to a web request from C# code

Recently I faced a small issue while passing User-Agent as part of Http headers.

I was assuming any header can be passed to a Web Request using request.Headers.Add(“Header Name”, “Value”) but I was wrong.

 

User-Agent is actually a property on WebRequest and has to be set like the following:

request.UserAgent=”Value”;

 

Simple issue but good to remember ūüôā

Standard
C#, CRM, Microsoft CRM Dynamics, Microsoft Dynamics CRM

TCP/IP based Integrations in CRM Dynamics On Prem

We recently had a requirement to Integrate with a System using MML(Man Machine Language) Commands with CRM Dynamics.

Sending MML commands to systems is done using TCP/IP protocol. Let’s first see the Sequence Diagram for the Integration:

sequencediagram

 

Here is the Source code for a Sample Console App we used for a POC, same code can be used from a Windows service or a Desktop application if required with few tweeks:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace EMATestingConsoleApp
{
    class Program
    {
        // Receiving byte array  
        static byte[] bytes = new byte[1024];
        static Socket senderSock;

        static void Main(string[] args)
        {
            Console.WriteLine("Connect to server? Press any key to continue connecting..");
            Console.ReadKey();

            try
            {
                // Create one SocketPermission for socket access restrictions 
                SocketPermission permission = new SocketPermission(
                    NetworkAccess.Connect,    // Connection permission 
                    TransportType.Tcp,        // Defines transport types 
                    "",                       // Gets the IP addresses 
                    SocketPermission.AllPorts // All ports 
                    );

                // Ensures the code to have permission to access a Socket 
                permission.Demand();

                var ipAddr = IPAddress.Parse(System.Configuration.ConfigurationManager.AppSettings["ipaddress"]);
                var port = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["port"]);
                // Creates a network endpoint 
                IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, port);

                // Create one Socket object to setup Tcp connection 
                senderSock = new Socket(
                    ipAddr.AddressFamily,// Specifies the addressing scheme 
                    SocketType.Stream,   // The type of socket  
                    ProtocolType.Tcp     // Specifies the protocols  
                    );

                senderSock.NoDelay = false;   // Using the Nagle algorithm 

                // Establishes a connection to a remote host 
                senderSock.Connect(ipEndPoint);
                Console.WriteLine("Socket connected to " + senderSock.RemoteEndPoint.ToString());

                Console.WriteLine("Enter command to be sent to EMA");
                

                try
                {
                    // Sending message 
                    //<Client Quit> is the sign for end of data 
                    string theMessageToSend = Console.ReadLine();
                    byte[] msg = Encoding.Unicode.GetBytes(theMessageToSend + "<Client Quit>");

                    // Sends data to a connected Socket. 
                    int bytesSend = senderSock.Send(msg);

                    ReceiveDataFromServer();

                
                }
                catch (Exception exc) { Console.WriteLine(exc.ToString()); }

                Console.ReadLine();
            }
            catch (Exception exc) { Console.WriteLine(exc.ToString()); }

        }

        private static void ReceiveDataFromServer()
        {
            try
            {
                // Receives data from a bound Socket. 
                int bytesRec = senderSock.Receive(bytes);

                // Converts byte array to string 
                String theMessageToReceive = Encoding.Unicode.GetString(bytes, 0, bytesRec);

                // Continues to read the data till data isn't available 
                while (senderSock.Available > 0)
                {
                    bytesRec = senderSock.Receive(bytes);
                    theMessageToReceive += Encoding.Unicode.GetString(bytes, 0, bytesRec);
                }

                Console.WriteLine("The server reply: " + theMessageToReceive);
                Console.WriteLine("Press any key to disconnect");
                Console.ReadKey();

                // Disables sends and receives on a Socket. 
                senderSock.Shutdown(SocketShutdown.Both);

                //Closes the Socket connection and releases all resources 
                senderSock.Close();
            }
            catch (Exception exc) { Console.WriteLine(exc.ToString()); }
        }

      

    }
}

 

 

 

Standard
C#, CRM, Microsoft CRM Dynamics

String.Equals returning false even for same strings

If you are startled by seeing String.Equals returning false for exactly similar looking strings, this is what you need to do:

  1. Check if both strings have equal lengths, if not return
  2. Check Trimmed versions of both strings, there maybe extra white-spaces that get unnoticed.
  3. Finally if both lengths are equal and trimmed versions look exactly the same, the issue could be the encoding of the spaces in the 2 strings as they maybe be coming from different sources. In this case, use the following code to correct the encoding:

image 

Using regex, I have just replaced the unicode equivalent of space with a space.

Standard
Azure, C#

Azure Webjob not starting – Status Pending Restart

Recently I have been working with WebJobs and one common issue while deploying these is getting a Pending Restart status on the Azure Portal.

Pending Restart basically means there was an error/exception while Azure tried to run your Job.

First of all check your Webjob logs and see the exception being thrown:

Now go back and check for the code you have written in your WebJob and see if something needs to be fixed.

 

Issue for me was related to configuration. There are 3 important configuration settings you need in your webjob config file:

  1. ServiceBus Connectionstring (Connectionstribf to your ASB namespace)
  2. AzureWebJobsDashboard (This would come from Azure storage A/C you want to use to store the logs from the job)
  3. AzureWebJobsStorage (same as above)

 

Final words

Webjobs are a great way to do background processing/ supporting async operations/ reading¬†or writing to Queues and should be leveraged whenever there’s a use case for them.

 

Standard
Azure, C#, Logging

How to log from Azure Web Jobs

The simplest way to enable logging in a Web Job that runs Continuously is by first enabling Application Logs from the Azure Portal and using Console.Write() in the actual WebJob file.

 

Here’s the code for the Function class which holds a method “ProcessQueueMessage”, gets executed whenever there’s a new message in the queue:

Webjob logging code C#

 

To enable logging, go to the portal => Web Job = > Diagnostics  logs=> Turn on application logging (Filesystem (You can also use a Blog/Table storage which is more robust)):

 

We can see the logs from the Log section in the webJob from the portal:

Webjob logs

 

Also there’s a way to see logs as a stream(You aren’t seeing any log messages on the stream as no activity is going on but trust me it works :-))

 

Final Words

The only downside with using FileSystem for logging is that it automatically shuts down logging after few hours. To enable logging permanently, use Blog/Table storage.

Standard
C#, MultiThreading

Producer Consumer Problem using locks in C#.Net

Problem Statement

The Producer Consumer problem is a classical Multithreaded problem which involves synchronization among multiple threads which are producing/consuming items from a resource at different speeds.

There are different ways to solve this problem in C#. I would be using the Monitor class for locking and its Wait/Pulse methods for signalling.

The client of the ProducerConsumer Class could use the old Threading API (Thread class) to spin off threads which try to consume/produce items or use TPL to use threads from the ThreadPool.

Code

using System.Collections.Generic;
using System.Linq;
using System.Threading;
 
namespace MultiThreading
{
    internal class ProducerConsumerProblem
    {
        private readonly object _lock = new object();
        private readonly Queue<int> queue = new Queue<int>();
 
 
        public void Produce(int input)
        {
            lock (_lock)
            {
                queue.Enqueue(input);
                Monitor.Pulse(_lock);
            }
        }
 
        public int Consume()
        {
            lock (_lock)
            {
                while (!queue.Any())
                {
                    Monitor.Wait(_lock);
                }
 
                return queue.Dequeue();
            }
        }
    }
}

Test

 [TestMethod]
       public void PoducerConsumerProblem_Should_Succeed()
       {
           var producerConsumerProblem = new ProducerConsumerProblem();
 
           Thread.CurrentThread.Name = "Main Consumer Thread";
           var t1=new Thread(
             () => producerConsumerProblem.Produce(1)) {Name = "Producer Thread"};
           t1.Start();
 
           producerConsumerProblem.Consume();
         
 
           var t2 =new Thread(
               () =>
               {
                   for (int i = 0; i < 10; i++)
                   {
                       producerConsumerProblem.Produce(i);
                   }
                   
               }
               ) {Name = "Producer Thread 2"};
 
           t2.Start();
       }

Final Words

.NET Framework 4.5 has a Concurrent collection called BlockingCollection which solves the same Producer-Consumer problem. In case you are using a former version of the framework, using Monitor is the simplest way to solve the problem. You can also use Semaphores to restrict Threads to a certain number (maybe depending on the cores of your system).

Standard