However, you don’t want everyone to invoke a management API endpoint you’ve exposed to ‘do stuff’ in your cloud environment. Normally, you’d want to authenticate if the user pressing the button (read: invoking the endpoint).
Lucky for us, this is very doable when invoking the endpoint via a Teams MessageCard/Actionable Message.
The token
Because Microsoft Teams is part of the Office 365 suite, you will be logged in as a user on the tenant. Therefore, the software has a user context and is able to pass this along to your API via a JWT Bearer token.
If you log in to the web client of Microsoft Teams (https://teams.microsoft.com) with your favorite browser you’ll be able to find the token which belongs to you.
In order to test this, I’ve created a new MessageCard in my Teams channel with 1 potentialAction which will invoke an Azure Function.
If you open up the network tab of your browser’s Developer Tools and press the AuthorizationTest button you’ll see the request is made to a Teams endpoint called executeAction with a bearer token in the Authorization header.
Warming up your web applications and websites is something which we have been doing for quite some time now and will probably be doing for the next couple of years also. This warmup is necessary to ‘spin up’ your services, like the just-in-time compiler, your database context, caches, etc.
I’ve worked in several teams where we had solved the warming up of a web application in different ways. Running smoke-tests, pinging some endpoint on a regular basis, making sure the IIS application recycle timeout is set to infinite and some more creative solutions.
Luckily you don’t need to resort to these kind of solutions anymore. There is built-in functionality inside IIS and the ASP.NET framework. Just add an applicationInitialization-element inside the system.WebServer-element in your web.config file and you are good to go! This configuration will look very similar to the following block.
What this will do is invoke a call to the /Warmup-endpoint whenever the application is being deployed/spun up. Quite awesome, right? This way you don’t have to resort to those arcane solutions anymore and just use the functionality which is delivered out of the box.
The above works quite well most of the time.
However, we were noticing some strange behavior while using this for our Azure App Services. The App Services weren’t ‘hot’ when a new version was deployed and swapped. This probably isn’t much of a problem if you’re only deploying your application once per day, but it does become a problem when your application is being deployed multiple times per hour.
For a project on the side I’m creating a Web API which has to parse XML requests in a POST. The first method I’ve written looks like this:
[HttpPost]public HttpResponseMessage IndexPost(RequestModel requestMessage)
{
returnnew HttpResponseMessage(HttpStatusCode.Accepted) { Content = new StringContent("This is the POST API response from BusinessPartner!") };
}
To test the new API I’m using the Postman Chrome plugin. With this plugin you are able to send requests to an endpoint and see what the response is. Of course you can also use Fiddler for this, but I like the user experience of Postman a bit more.
There were a few problems I encountered during the development of the Web API.
The first problem was this error:
{
"message": "An error has occurred.",
"exceptionMessage": "No MediaTypeFormatter is available to read an object of type 'RequestModel' from content with media type 'text/plain'.",
"exceptionType": "System.InvalidOperationException",
"stackTrace": " at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger)\r\n at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger)\r\n at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger)\r\n at System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)\r\n at System.Web.Http.Tracing.Tracers.FormatterParameterBindingTracer.<>c__DisplayClass3.<executebindingasync>b__1()\r\n at System.Web.Http.Tracing.ITraceWriterExtensions.TraceBeginEndAsync(ITraceWriter traceWriter, HttpRequestMessage request, String category, TraceLevel level, String operatorName, String operationName, Action`1 beginTrace, Func`1 execute, Action`1 endTrace, Action`1 errorTrace)\r\n at System.Web.Http.Tracing.Tracers.FormatterParameterBindingTracer.ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)\r\n at System.Web.Http.Controllers.HttpActionBinding.<>c__DisplayClass1.<executebindingasync>b__0(HttpParameterBinding parameterBinder)\r\n at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()\r\n at System.Threading.Tasks.TaskHelpers.IterateImpl(IEnumerator`1 enumerator, CancellationToken cancellationToken)"}
This was quite surprising as I thought I was sending a proper request which could be serialized. For reference, I was sending a POST request to https://localhost:11210/api/businesspartnerapi/ in this format:
Some time ago Microsoft has introduced the ASP.NET Web API framework. It’s a framework you can use to create your own RESTful services. It’s much like WCF Data Services or WCF RIA Services, but a lot easier to use (IMO). I’ve never liked the WCF-stack much, probably because configuring it always posed to be a hassle.
Using the Web API framework is much easier and you have to configure a lot less, or at least I haven’t found all of the configurable options yet. Then again, it’s created for entirely different purposes of course.
Because I was put on a new project, I was finally able to do some real work with ASP.NET Web API. We had to develop a solution containing a so called self-hosted Web API service which also supported OData queries. This sounds like a lot of work, but it’s actually rather easy to do so nowadays.
During this new project we had some time to investigate and learn a bit about the platform. Therefore we chose to use the latest version of everything we could find, just to keep us up-to-date. To get OData working we used the beta2 version which works great for the simple stuff we were doing.