Wednesday, March 29, 2017

Build an ASP.NET Core 1.1 tag helper that consumes Azure Web API RESTful service

In a previous post, I demonstrated how to create an ASP.NET Core 1.0 tag helper. Since ASP.NET 1.1 was released, some of the packages in the previous post are not supported anymore. Therefore, I am hereby updating this article to fix this issue. I am also using Visual Studio 2017 instead of Visual Studio 2015.

Tag Helpers in ASP.NET Core allow you to create your own tags that fulfill a server-side purpose. In this tutorial, I will show you how to create a tag helper <toon> that accesses a Web API service and displays contents in any razor view page.

The Web API service we will consume in this exercise is located at http://cartoonapi.azurewebsites.net/api/cartoon. It delivers the names of cartoon characters and their respective images.

1) To start with, create an ASP.NET Core Web application named ToonTagHelper in Visual Studio 2017.

2) We need to create a class that closely matches the nature of the Web API JSON object. Therefore, add the following Toon class to a Models folder in your project:
public class Toon {
  public string Name { get; set; }
  public string PictureUrl { get; set; }
}
3) Next, we need to install the We API Client libraries. To that end, execute the following commands from within the Package Manager Console window in Visual Studio 2017:
Install-Package Newtonsoft.Json
Install-Package System.Net.Http
Install-Package System.Runtime.Serialization.Xml
Alternatively, you can run the following commands from within a terminal window:
dotnet add package Newtonsoft.Json
dotnet add package System.Net.Http
dotnet add package System.Runtime.Serialization.Xml

This should add the following dependencies to your .csproj file:
<PackageReference Include="Newtonsoft.Json" Version="10.0.1" />
<PackageReference Include="System.Net.Http" Version="4.3.1" />
<PackageReference Include="System.Runtime.Serialization.Xml" Version="4.3.0" />
4) Add the following tag to the bottom of Views/Home/About.cshtml:


<toon></toon>

5) Create a folder named TagHelpers and add to it a class file named ToonTag.cs. Have the class inherit from TagHelper and implement the ProcessAsync() method as follows:

public async override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
}


We could have implemented a method Process() instead. However, in our case, it is appropriate to implement ProcessAsync() instead because we are about to make an async call to a remote service.

6) Add the following instance variable to the ToonTagHelper class:
 private string baseUrl = "http://cartoonapi.azurewebsites.net";

7) Annotate the CartoonCharactersTagHelper class with the following:

[HtmlTargetElement("toon")]
[HtmlTargetElement(Attributes = "toon")]


The first annotation defines the tag <toon> and the second defines the “toon” attribute. This means that we have two different ways to produce the same output on a razor .cshtml view.

8) Add the following method to the ToonTagHelper class:

async Task<IEnumerable<Toon>> GetToonsAsync() {
  HttpClient client = new HttpClient();
  client.BaseAddress = new Uri(baseUrl);
  client.DefaultRequestHeaders.Accept.Clear();
  client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
  IEnumerable<Toon> toons = null;
  try {
    // Get all cartoon characters
    HttpResponseMessage response = await client.GetAsync("/api/cartoon");
    if (response.IsSuccessStatusCode)
    {
       string json = await response.Content.ReadAsStringAsync();
      toons = JsonConvert.DeserializeObject<IEnumerable<Toon>>(json);
    }
  } catch (Exception e) {
      System.Diagnostics.Debug.WriteLine(e.ToString());
  }
  return toons;
}



The above code makes a request to the Web API service and returns an IEnumerable<Toon> collection with the results.

9) Add the following code inside the ProcessAsync() method:

IEnumerable<Toon> toons= await GetToonsAsync();
string html = string.Empty;
html += "<table><tr><th>Name</th><th>Picture</th></tr>";
foreach (var item in toons) {
    string photoUrl = baseUrl + "/" + item.PictureUrl;
    html += "<tr>";
    html += "<td>" + item.Name + "</td>";
    html += "<td><img src='" + photoUrl + "' style='width: 50px' /></td>";
    html += "</tr>";
}
html += "</table>";
output.Content.SetHtmlContent(html);


The above code creates a table with the collection of cartoon characters so that it can be displayed wherever the tag helper is used.

11) Register the tag name in the Views/_ViewImports.cshtml file by adding the following to the list of tags that are already there:

@addTagHelper "ToonTagHelper.TagHelpers.ToonTag, ToonTagHelper"

You may need to adjust the above names depending on what you called your app and/or your tag helper class.

11) Compile and run your application, then click on About. You should see the following output:



If you inspect the table in your browser, you will see the following:



The above is using the tag and not the attribute. Edit About.cshtml and comment out “<toon></toon>” and put the following <div> tag with the toon attribute underneath it:
<div toon></div>

Your About.cshtml should now look like this:
@{
    ViewData["Title"] = "About";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<p>Use this area to provide additional information.</p>
@*<toon></toon>*@
<div toon></div>
When you run your application. you should see the same output as before. However, upon inspection of the HTML source, you will notice that a <div> tag is the primary container for our code rather than a <toon> tag:



This proves to us that you can either use tags or attributes with TagHelpers in ASP.NET Core.

No comments:

Post a Comment