Exercise - Create and test a simple Azure Function locally with Visual Studio
Visual Studio provides an excellent environment for creating and testing an Azure Function App. You can develop an Azure Function locally, and verify that it operates correctly, before deploying it to the cloud.
In the luxury watch online website scenario, there's a requirement for a function that returns detailed information about a watch when given the model number of the watch. The data you need returned includes: the manufacturer, the type of case back (solid, transparent, or engraved), the bezel, the style of the dial, the finishing of the case, the number of jewels, and so on.
In this exercise, you implement and test a version of this function locally using Visual Studio.
Note
Before starting this exercise, make sure you have VS 2022 installed, along with the Web & Cloud workload extensions ASP.NET and web development and Azure development.
Create an Azure Function App
Create an Azure Function App using an Azure Functions template.
Launch Visual Studio Installer and on the Visual Studio 2022 start page, select Modify.
Ensure ASP.NET and web development and Azure development are selected and available (if not select Install while downloading) and then select Close.
On the Visual Studio 2022 start page, select Launch.
On the Get started menu, select Create a new project. The Create a new project page appears.
Search for or scroll to Azure Functions template, and then select Next.
The Configure your new project page appears. Enter the following values.
Field Value Project name WatchPortalFunction Location Select a location to store your project by browsing to a folder or creating a folder on your local computer. Solution name Accept WatchPortalFunction (default). Place solution and project in the same directory Unchecked (NOT selected). This setting ensures the correct folder structure for this module. Select Next.
The Additional information page appears.
Select the following values.
Field Value Dotnet version *.NET 6.0 (Long Term Support) Function trigger Http trigger Use Azurite for runtime storage account (AzureWebJobsStorage) Checked Enable Docker Unchecked Authorization level Anonymous If a Visual Studio notification shows that updates are ready, select Refresh.
Select Create.
Visual Studio creates the
WatchPortalFunction
project and displays the Functions App source code fileFunction1.cs
in the code editor window. The file contains the code for a class namedFunction1
.As shown in the following example code, the
Function1
class contains boilerplate code from the HTTP trigger template. TheRun
method is annotated with the[FunctionName ("Function1")]
attribute. In the previous unit, we learned that the boilerplate parameters for theRun
method are anHttpRequest
object containing the details of the request that triggered the function, and a trace log entry for recording trace information.namespace WatchPortalFunction { public static class Function1 { [FunctionName("Function1")] public static async Task<IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation("C# HTTP trigger function processed a request."); string name = req.Query["name"]; string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); dynamic data = JsonConvert.DeserializeObject(requestBody); name = name ?? data?.name; return name != null ? (ActionResult)new OkObjectResult($"Hello, {name}") : new BadRequestObjectResult("Please pass a name on the query string or in the request body"); } } }
Create the WatchInfo Azure Function
In the View menu, select Solution Explorer. In the Solution Explorer window, right-click the WatchPortalFunction Azure Functions project, and in the context menu select Add > New Azure Function.
In the Add New Item - WatchPortalFunction window, select Azure Function. In the Name field, enter WatchInfo.cs, and then select Add.
In the New Azure Function - WatchInfo window, select Http trigger. In the Authorization level dropdown list, select Anonymous, and then select Add.
Visual Studio creates a new function and the
Run
method is annotated with the[FunctionName("WatchInfo")]
attribute.In the body of the
Run
function, delete the code after thelog.LogInformation
line. The result should look like this.namespace WatchPortalFunction { public static class WatchInfo { [FunctionName("WatchInfo")] public static async Task<IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation("C# HTTP trigger function processed a request."); } } }
Insert the following code in the body of the
Run
method afterlog.LogInformation
line.// Retrieve the model id from the query string string model = req.Query["model"]; // If the user specified a model id, find the details of the model of watch if (model != null) { // Use dummy data for this example dynamic watchinfo = new { Manufacturer = "abc", CaseType = "Solid", Bezel = "Titanium", Dial = "Roman", CaseFinish = "Silver", Jewels = 15 }; return (ActionResult)new OkObjectResult($"Watch Details: {watchinfo.Manufacturer}, {watchinfo.CaseType}, {watchinfo.Bezel}, {watchinfo.Dial}, {watchinfo.CaseFinish}, {watchinfo.Jewels}"); } return new BadRequestObjectResult("Please provide a watch model in the query string");
This code reads the
model
parameter from the query string in the HTTP request and returns the details for that watch model. In this example code, we created dummywatchinfo
data that is returned regardless of the value ofmodel
. The function returns a response that contains these details. Or, if the HTTP request doesn't include a query string, the function returns an error message. In a real-world example, you would use themodel
value to do a lookup of the correctwatchinfo
to return.
Test the Azure Function locally
On the command bar, select Debug > Start Debugging.
Visual Studio builds the Azure Function App and starts the Azure Functions runtime. An Output window opens to display messages as the runtime starts up. When the runtime is ready, a list of the HTTP functions and the URL that you can use to trigger each function is displayed.
Open a web browser, and enter the URL displayed in the runtime window. The default URL is
http://localhost:7071/api/WatchInfo?model=abc
, so that is the one we're using in this exercise. The request triggers theWatchInfo
function and passes the modelabc
as the query string parameter. The web browser should display the dummy details generated by the function.Enter the URL
http://localhost:7071/api/WatchInfo
. This request doesn't include a query string. The trigger returns the error response and the web browser displays the messagePlease provide a watch model in the query string
.Close the web browser, but leave the Azure Function App running.
In Visual Studio, set a breakpoint on the line of code that retrieves the model from the query string.
Restart the web browser, and enter the URL without the query string
http://localhost:7071/api/WatchInfo
.Visual Studio highlights the code at the breakpoint where execution is paused.
In Visual Studio, to step over the statement at the breakpoint, press F10.
In the Autos tab of the Debugger window, verify that the
model
variable isnull
. The variable shows this value because the query string doesn't contain a model parameter.Press F10 again, and verify that control jumps to the statement that returns a
BadRequestObjectResult
object.To continue running the method and return to the web browser, press F5. The same error message should display.
In the web browser, enter the URL with a query string and a model parameter. Step through the function in the debugger, and verify that the model is retrieved correctly. The
model
variable should be populated with the value of the parameter, and the details of the model returned as anOkObjectResult
object.On the menu bar, select Debug > Stop Debugging.
In this exercise, you saw how the Azure Functions Tools extension in Visual Studio simplifies the experience of creating an Azure Function App, by letting you use familiar tools to build and debug your code.