Azure Hybrid Integration Day coming to Calgary

Every year some of the brightest minds in Microsoft Integration descend upon Redmond, Washington for the Microsoft MVP Summit. This year 3 MVPs (Saravana Kumar, Steef-Jan Wiggers and Michael Stephenson) from Europe will be stopping by Calgary on their way to the Summit and will be giving some presentations.   Myself and a local Microsoft employee, Darren King, will also be presenting.

I have shared the stage with these MVPs before and can vouch that attendees are in for a unique experience as they discuss their experiences with Microsoft Azure and BizTalk Server.

During this full day of sessions you will learn about how BizTalk and Microsoft Azure can address integration challenges. Session topics include SaaS connectivity, IoT, Hybrid SQL Server, BizTalk administration & operations and Two Speed IT using Microsoft Azure. Also bring your burning questions for our interactive Ask the Experts Q & A.

The free event takes place on October 30th, 2015  at the Calgary Microsoft office.  You can find more details here.

Azure Mobile Services–Update Entity results in 400 Bad Request

While performing some local testing on an Azure Mobile Services (C# backend) app, I kept getting a 400 Bad Request whenever I tried to perform an update to an Entity:

await MobileService.GetTable<MyEntity>().UpdateAsync(myEntity);

I ensured that my entity object was populated correctly and that I was providing an Id as part of the request but was still getting the following error:

“Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException: The request could not be completed.  (Bad Request)\r\n   at Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient.<ThrowInvalidResponse>d__18.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n   at Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient.<SendRequestAsync>d__1d.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n   at Micr
osoft.WindowsAzure.MobileServices.MobileServiceHttpClient.<RequestAsync>d__4.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n   at Microsoft.WindowsAzure.MobileServices.MobileServiceTable.<>c__DisplayClass21.<<UpdateAsync>b__20>d__23.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n   at Microsoft.WindowsAzure.MobileServices.MobileServiceTable.<TransformHttpException>d__51.MoveNext()\r\n— End of stack trace from previous

Not the most descriptive error hence my decision to create the post.  The end result is that within my C# backend project I declared an entity within my DataObjects class.

public class MyEntity:EntityData
   {
       public string Id { get; set; }

As soon as I removed the Id from this class my updates were successful.

In the end it was a silly error on my part as within my Mobile App Model classes you need to declare this Id as part of your class. This is not the same case with your backend classes.  I have several other Entities in this project and knew that you should not declare this Id but it slipped through the cracks.

It is also worth noting that during this time I could successfully insert records even though this Id was declared. 

Using the Azure API Management–Management API

I recall the first time I saw this demoed at the MVP Summit last fall and wondered how/if I would use this.  My thought process, at the time, was that Microsoft has put together a nice, functional Administration and Developer portals so why would I want to call these APIs myself?

Fast-forward about 8 months where I have a ‘Middleware’ support team and also other internal stakeholders who are interested in some of this data.  While I could provide access to all of these users to the portals I just mentioned but it feels like it would be just another website that someone has to remember credentials for.  It also would be very disconnected from some of the other tooling that the Middleware team uses to support interfaces (BAM, Exception Portal, BizTalk360 etc).  In addition to BizTalk, we also have other Azure Services that participate in some API interactions including  Web APIs, SQL Azure and Service Bus topics.  With all of these disparate sites and services, it was time to build an “Integration Portal” where we could consume these external data sources (API Management, SQL Azure, Service Bus) and then link to the other BizTalk tools).

Perhaps I will get deeper into this Integration Portal solution in the future, but for now let’s focus on the Azure API Management – Management API and how we can consume some of the Analytics that we would ordinarily see in our Admin/Developer portal.

Security and Authorization

By default, the Management API is disabled within your API Management tenant. Within the API Management Portal, click on the Security label and then the API Management REST API tab to enable it.  Within this tab:

  • Click on the Enable API REST API checkbox
  • Set an appropriate Expiry date for your token
  • Click Generate Token button
  • Copy your Authorization header token

image

Building the application

For the purposes of this Blog Post I am going to build a simple ASP.NET MVC Project where I will display my API Management Analytic data.  I am not going to go through setting up the MVC project in much detail, but here is a link to a good tutorial.

Within this MVC project I am going to create a new Controller called APIAnalytics and will use the a view called Index to display my data.

image

Below is the code that I have included within my Index() method.  You will notice this is marked as an async method as we are making our API Call using a GetAsync method. I have added comments within the code to provide some additional context.

// GET: APIAnalytics
public async Task<ActionResult> Index()
{

ViewBag.Message = String.Format(“API Management calls for today: {0}”, DateTime.Now.ToShortDateString());

//Note that all Azure timestamps are in UTC.  Going to use this value as a predicate so that we are only returning data for the current day
string currentDate = DateTime.Today.ToUniversalTime().ToString(“s”);

//Notice the Odata filter where we will restrict based upon timestamp

string url = String.Format(“https://<your_tenant_name>.management.azure-api.net/reports/byProduct?api-version=2014-02-14&$filter=timestamp ge datetime'{0}'”, currentDate);

using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Add(“Authorization”, “<your_auth_token_from_api_management_portal”);

client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(“application/json”));

System.Net.Http.HttpResponseMessage response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsStringAsync();

//We want some typed data so that we can bind to our grid view control. Look for “APIStats” model class below
var table = Newtonsoft.Json.JsonConvert.DeserializeObject<APIStats>(data);

 

//Within our view we will use a Gridview control

System.Web.UI.WebControls.GridView gView = new System.Web.UI.WebControls.GridView();

//We are going to create a data binding event so we can manipulate column headers, etc
gView.RowDataBound += gView_RowDataBound;
gView.DataSource = table.value;
gView.DataBind();
gView.AllowSorting = true;
gView.AutoGenerateColumns = false;

gView.AlternatingRowStyle.BackColor = System.Drawing.Color.Azure;
gView.Width = System.Web.UI.WebControls.Unit.Percentage(90);

using (System.IO.StringWriter sw = new System.IO.StringWriter())
{
using (System.Web.UI.HtmlTextWriter htw = new System.Web.UI.HtmlTextWriter(sw))
{
gView.RenderControl(htw);
ViewBag.ReturnedData = sw.ToString();
}
}
}
}
return View();

}

 

//Here is our data binding event

protected void gView_RowDataBound(object sender, GridViewRowEventArgs e)
{

if (e.Row.RowType == DataControlRowType.Header)
{
e.Row.BackColor = System.Drawing.Color.LightGray;
e.Row.Cells[0].Text = “API Product”;
e.Row.Cells[0].Width = 300;
e.Row.Cells[1].Text = “Success Count”;
e.Row.Cells[2].Text = “Block Count”;
e.Row.Cells[3].Text = “Failed Count”;
e.Row.Cells[4].Text = “Other Count”;
e.Row.Cells[5].Text = “Total”;
e.Row.Cells[6].Text = “Bandwidth”;
e.Row.Cells[7].Text = “API Avg Time”;
e.Row.Cells[8].Text = “API Min Time”;
e.Row.Cells[9].Text = “API Max Time”;
e.Row.Cells[10].Text = “Svc Avg Time”;
e.Row.Cells[11].Text = “Svc Min Time”;
e.Row.Cells[12].Text = “Svc Max Time”;

}
else
{
try
{

//Going to round some values so that we are not displaying so many decimal points

e.Row.Cells[7].Text = Math.Round(System.Convert.ToDouble(e.Row.Cells[7].Text), 1).ToString();
e.Row.Cells[8].Text = Math.Round(System.Convert.ToDouble(e.Row.Cells[8].Text), 1).ToString();
e.Row.Cells[9].Text = Math.Round(System.Convert.ToDouble(e.Row.Cells[9].Text), 1).ToString();
e.Row.Cells[10].Text = Math.Round(System.Convert.ToDouble(e.Row.Cells[10].Text), 1).ToString();
e.Row.Cells[11].Text = Math.Round(System.Convert.ToDouble(e.Row.Cells[11].Text), 1).ToString();
e.Row.Cells[12].Text = Math.Round(System.Convert.ToDouble(e.Row.Cells[12].Text), 1).ToString();

}
catch (Exception ex;)
{
throw ex;
}

}

}

 

//Here is our APIStats Model Class

public class APIDetail
{

public string name { get; set; }

public int callCountSuccess { get; set; }
public int callCountBlocked { get; set; }
public int callCountFailed { get; set; }
public int callCountOther { get; set; }
public int callCountTotal { get; set; }
public int bandwidth { get; set; }
public double apiTimeAvg { get; set; }
public double apiTimeMin { get; set; }
public double apiTimeMax { get; set; }
public double serviceTimeAvg { get; set; }
public double serviceTimeMin { get; set; }
public double serviceTimeMax { get; set; }
}

public class APIStats
{
public List<APIDetail> value { get; set; }
public int count { get; set; }
public object nextLink { get; set; }
}
}

//Lastly here is our Index.cshtml view

@{
ViewBag.Title = “Index”;
}

<h2>Index</h2>
@ViewBag.Message

@Html.Raw(ViewBag.ReturnedData)

Running Application

If we go ahead and run our application we will discover the following web page.  The are all of the API Products that exist within my tenant.  As you can see I didn’t have any calls to my Auto Insurance apis and instead was just trying out my BizTalk Boot Camp products.

Within the unlimited tier you will see a very large API Max Time.  The reason for that is that I didn’t actually have the API backend up during that initial call. On my limited product you will see I have a Block Count of 3. The reason for this is that I have rate limiting enabled on that product and as a result I had some blocked calls.

image

Conclusion

The Azure API Management – Management API is quite rich and allows organizations to create custom dashboards or integrate this data with related data from other sources.

Within this blog post,  I have only demonstrated one type of call that is available within this API. For more details and to discover the different APIs, please refer to the following web page.

Azure API Management–IP Whitelisting

When implementing API Management solutions, it is a common practice to use IP Whitelisting when interacting with certain trading partners.  The idea being that only traffic presented from a specific IP Address (or range) can call your API Proxy.  This usually isn’t used exclusively, but can be combined with other techniques to reduce your attack surface.

Trying to manage IP Whitelisting using Firewalls and Reverse Proxies can sometimes be a complex and messy endeavor but is pretty straightforward in Azure API Management.

In my demo, I added the Restrict caller IPs policy at the product level in the inbound section.

image

Once the policy has been added, you can add a specific IP Address or a range if the trading partner has multiple servers that you want to communicate with.  The IP Addresses below are obviously fictitious.

image

Once enabled, if you try to call the API from an IP Address that has not been whitelisted you will get the following error:

image

 

You can find more information about this and other Azure API Management policies here.

Logic Apps: Integrating Custom SharePoint Lists and Salesforce

I have posted a little tutorial video that describes consuming data from a SharePoint Server Custom List and using that data to create new Contacts in Salesforce. The SharePoint Connector will take advantage of the Hybrid Connection capability that allows messages to flow between the Azure cloud and an On-Premise system without requiring ports to be opened in firewall.  

 

Introduction to Azure API Management: Hands-on Lab

I have recently returned from Charlotte where I had a couple of Azure API Management sessions at the BizTalk Bootcamp.  The first presentation was an Introduction to the API Economy, API Management, Azure API Management and how you can use Azure API Management and BizTalk to introduce some agility in your organization.  This was the same session that I delivered at the BizTalk Summit in London.  BizTalk360, who hosted that event, recorded all sessions and started to publish both the talks and the slide decks.  I don’t want to disrupt what they are doing over there so I would encourage you to check out their conference page where my presentation should be available soon.

The second session that I delivered in Charlotte was a Hands-on Lab.  Attendees were encouraged to create an Azure API Management instance in advance of arriving or during a break (only takes 15 min to provision).  I then published an ASP.NET Web API in Azure and each attendee had the ability to:

  • Create 2 API Products
  • Create an API and 3 Operations
  • Publish their Products
  • Testing the API through the Developer Portal
  • Configure a Rate Limiting scenario

The scenarios are pretty simple but I was pleased to hear that for many people, who had no previous experience with API Management, were able to get an API managed in only 45 minutes.

I will make this API available in the interim but if I run into any issues or abuse with it I may decide to take it down.

Also note that I provisioned my API Management solution many months ago and it looks like there have been some subtle changes to the UI in the Azure API Management Portal.  None of these changes should get in the way of walking through the scenarios but I figured I would bring this up now to avoid further confusion.

Azure App Service Demo Scenario–Part 1

While recording is a lot of work, I find that it is a very useful channel for learning. As I learn more about the new Azure App Service I will be posting some short demonstrations and walkthroughs.

The first post in this series is a quick Logic App demo that includes Twitter and Dropbox integration.  The inspiration for the demo comes from the App Service Documentation which can be found here.