Differences between Azure Functions v1 and v2 in C#
- 📅
- 📝 618 words
- 🕙 3 minutes
- 📦 .NET
- 🏷️ Azure, C#
- 💬 2 responses
I’ve been messing around in the .NET ecosystem again, jumping back in with Azure Functions (similar to AWS Lambda) to get my blog onto 99% static hosting. I immediately ran into the API changes between v1 and v2 (currently in beta).
These changes are because v1 was based around .NET 4.6 using WebAPI 2 while v2 is based on ASP.NET Core which uses MVC 6. There are some guides around conversion, but none in the context of Azure Functions.
I’ll illustrate with a PageViewCount sample that uses Table Storage to retrieve and update a simple page count.
v1 (.NET 4.61 / WebAPI 2)
[FunctionName("PageView")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")]HttpRequestMessage req, TraceWriter log) {
var page = req.MessageUri.ParseQueryString()["page"];
if (String.IsNullOrEmpty(page))
return req.CreateErrorResponse(HttpStatusCode.BadRequest, "'page' parameter missing.");
var table = Helpers.GetTableReference("PageViewCounts");
var pageView = await table.RetrieveAsync<PageViewCount>("damieng.com", page)
?? new PageViewCount(page) { ViewCount = 0 };
var operation = pageView.ViewCount == 0
? TableOperation.Insert(pageView)
: TableOperation.Replace(pageView);
pageView.ViewCount++;
await table.ExecuteAsync(operation);
return req.CreateResponse(HttpStatusCode.OK, new { viewCount = pageView.ViewCount });
}
v2 (ASP.NET Core / MVC 6)
[FunctionName("PageView")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")]HttpRequest req, TraceWriter log) {
var page = req.Query["page"];
if (String.IsNullOrEmpty(page))
return new BadRequestObjectResult("'page' parameter missing.");
var table = Helpers.GetTableReference("PageViewCounts");
var pageView = await table.RetrieveAsync<PageViewCount>("damieng.com", page)
?? new PageViewCount(page) { ViewCount = 0 };
var operation = pageView.ViewCount == 0
? TableOperation.Insert(pageView)
: TableOperation.Replace(pageView);
pageView.ViewCount++;
await table.ExecuteAsync(operation);
return new OkObjectResult(new { viewCount = pageView.ViewCount });
}
Differences
The main differences are that:
- Return types are
IActionResult
/ObjectResult
objects rather than extension methods againstHttpRequestMessage
(easier to mock/create custom ones) - Input is the
HttpRequest
object rather thanHttpResponseMessage
(easier to get query parameters)
The error Can not create abstract class
when executing your function means you are trying to use the wrong tech for that environment.
Helpers
Both classes above utilise a small helper class to take care of Table Storage which doesn’t have the nicest to use API. A data-context like wrapper that ensures the right types go to the right table might be an even better option.
static class Helpers {
public static CloudStorageAccount GetCloudStorageAccount() {
var connection = ConfigurationManager.AppSettings["DamienGTableStorage"];
return connection == null ? CloudStorageAccount.DevelopmentStorageAccount : CloudStorageAccount.Parse(connection);
}
public static CloudTable GetTableReference(string name) {
return GetCloudStorageAccount().CreateCloudTableClient().GetTableReference(name);
}
public static async Task<T> RetrieveAsync<T>(this CloudTable cloudTable, string partitionKey, string rowKey)
where T:TableEntity {
var tableResult = await cloudTable.ExecuteAsync(TableOperation.Retrieve<T>(partitionKey, rowKey));
return (T)tableResult.Result;
}
}
To compile
If you want to compile this, or Google led you here looking for code to do a simple page counter, here’s the missing TableEntity
class;
public class PageViewCount : TableEntity
{
public PageViewCount(string pageName)
{
PartitionKey = "damieng.com";
RowKey = pageName;
}
public PageViewCount() { }
public int ViewCount { get; set; }
}
[)amien
2 responses to Differences between Azure Functions v1 and v2 in C#
The explanation was helpful! Thanks.
Thank you for explaining with example. Superb!!!