Page 49 - MSDN Magazine, August 2017
P. 49

ValidationSucceeded. If the validation succeeded, the value will be true; otherwise, it’ll be false.
The result also includes two other properties that will be use- ful to third parties. The first one is Sender. This is the value of the sender claim in the token. This is the e-mail address of the account that sent the actionable message. The second one is the Action- Performer, which is the value of the sub claim. This is the e-mail address of the person who performed the action. In this example, only those with @contoso.com e-mail addresses can approve or reject an expense report. You can replace the code with a more complicated verification of your own.
Refresh Card
So far the only way to provide feedback to a user is through the CARD-ACTION-STATUS header. The value of the header will be displayed to the user in a reserved area of the card. Another option is to return a refresh card to the user. The idea is to replace the current action card with a different card. There are a few reasons why you want to do that. For example, after an expense report is approved, you don’t want users to be able to approve or reject the expense report again. Instead, you’d like to tell the user that the expense report is already approved. Figure 10 shows the markup that you’ll return.
You need to set the value of the header CARD-UPDATE-IN-BODY to true so Microsoft servers know that the response has a refresh card. Figure 11 shows the Approve method returns a refresh card.
Wrapping Up
Actionable Messages let users complete tasks within Outlook in a secure way. It’s available in desktop Outlook and Outlook Web Access today and the feature is coming to Outlook for Mac and Outlook Mobile soon. It’s straightforward to implement Action- able Messages. First, you need to add the required markup to the e-mails you’re sending out. Second, you need to verify the bearer token sent by Microsoft in your Web service. Actionable Messages will make your users happier and more productive. There is so much more about Actionable Messages than this article can cover. Visit bit.ly/2rAD6AZ for the complete references and links to the code samples.
Figure 10 Markup Returned to Expense Report with Refresh Card
Figure 11 The Approve Method Returns a Refresh Card
private HttpResponseMessage CreateRefreshCard(
HttpRequestMessage request, string actionStatus,
string expenseID, string amount, string submitter, string description)
{
string refreshCardFormatString = "{\\\\"@context\\\\": \\\\"http://schema.
org/extensions\\\\",\\\\"@type\\\\": \\\\"MessageCard\\\\",\\\\"hideOriginalBody\\\\": \\\\"true\\\\",\\\\"title\\\\": \\\\"Expense report #{0} was approved\\\\",\\\\"sections\\\\": [{\\\\"facts\\\\": [{\\\\"name\\\\": \\\\"ID\\\\",\\\\"value\\\\": \\\\"{0}\\\\"},{\\\\"name\\\\": \\\\"Amount\\\\",\\\\"value\\\\": \\\\"{1}\\\\"},{\\\\"name\\\\": \\\\"Submitter\\\\",\\\\"value\\\\": \\\\"{2}\\\\"},{\\\\"name\\\\": \\\\"Description\\\\",\\\\"value\\\\": \\\\"{3}\\\\"}]}]}";
string refreshCardMarkup = string.Format( refreshCardFormatString,
expenseID,
amount,
submitter, description);
HttpResponseMessage response = request.CreateResponse(HttpStatusCode.OK); Response.Headers.Add("CARD-ACTION-STATUS", actionStatus);
response.Headers.Add("CARD-UPDATE-IN-BODY", "true"); response.Content = new StringContent(refreshCardMarkup);
return response; }
[HttpPost]
[Route("approve")]
public async Task<HttpResponseMessage> Approve([FromBody]JObject jBody) {
HttpRequestMessage request = this.ActionContext.Request; HttpStatusCode result = await VerifyBearerToken(
request, "https://api.contoso.com", "expenseapproval@contoso.com");
switch (result) {
case HttpStatusCode.Unauthorized: return request.CreateErrorResponse(
HttpStatusCode.Unauthorized, new HttpError());
case HttpStatusCode.Forbidden: HttpResponseMessage errorResponse = this.Request.CreateErrorResponse(
HttpStatusCode.Forbidden, new HttpError()); errorResponse.Headers.Add("CARD-ACTION-STATUS",
"Invalid sender or the action performer is not allowed."); return errorResponse;
default: break;
}
string expenseId = jBody["id"].ToString(); // Process and approve the expense report.
return CreateRefreshCard( request,
"The expense was approved.", "98432019",
"83.27 USD", "Jonathan Kiev", "Dinner with client");
}
{
"@context": "http://schema.org/extensions", "@type": "MessageCard",
"hideOriginalBody": "true",
"title": "Expense report #98432019 was approved", "sections": [{
"facts": [{
"name": "ID", "value": "98432019"
}, {
"name": "Amount", "value": "83.27 USD"
}, {
"name": "Submitter", "value": "Kathrine Joseph"
}, {
"name": "Description", "value": "Dinner with client"
}] }]
}
I’d like to acknowledge Sohail Zafar, Edaena Salinas Jasso, Vas- ant Kumar Tiwari, Mark Encarnacion and Miaosen Wang, who helped review this article for grammar, spelling, and flow. n
Woon Kiat Wong is a software engineer from the Knowledge Technologies Group in Microsoft Research. He works closely with the Outlook team to deliver Action- able Messages. Contact him at wowong@microsoft.com.
thanKs to the following Microsoft technical experts for reviewing this article: Pretish Abraham, David Claux, Mark Encarnacion and Patrick Pantel
msdnmagazine.com
August 2017 43








































   47   48   49   50   51