Azure

Create an Azure Function App from Visual Studio

When I started looking at Azure Function Apps in the post, Azure Functions Introduction, I used the Azure Portal to create the sample function App used in the post. On the follow-up post, Open an Azure Portal Created Function in Visual Studio, I showed how to get a portal created function to open in Visual Studio. The code download from the Azure Portal was in the csx format instead of the cs format that Visual Studio normally deals with so a lot of Visual Studio doesn’t work.

This post is going to walk through creating a new Azure Function App from within Visual Studio. My hope is that starting from Visual Studio will result in code that is more Visual Studio friendly. This post will be using Visual Studio 2019.

App Creation

Open Visual Studio and click  Create a new project on the start dialog.

On the next screen search from Azure Functions. Click on the Azure Functions item and click the Next button.

Enter a Project name, and change any other settings if needed, then click Create.

The next dialog will ask for the type of trigger to use. To match the function we created a few weeks ago on the Azure Portal we are going to use an Http trigger and click Create.

Clicking the last Create button will kick off the project creation process. When done you will have a project with a single function that will match the following inside of the file Function1.cs.

public static class Function1
{
    [FunctionName("Function1")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "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");
    }
}

The following is the Portal created function from a few weeks ago.

public static async Task<IActionResult> Run(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");
}

You will notice that the body of the two is the same. The Visual Studio version is using attributes to let Azure know the name, the trigger type, and other information that will be needed once the function is published to Azure.

Local Testing

One really neat thing about using Visual Studio for your function development is you can debug them locally. If you hit the play button (or F5) Visual Studio will launch your function locally. You will see something like the following.

Highlighted is the section listing all the Http Functions in the applications along with URLs that can be used to test them. For this example, the following URL could be used to get the response “Hello, Eric”.

http://localhost:7071/api/Function1?name=Eric

As far as I have seen so far all the normal debugging features of Visual Studio seem to work when running a function locally.

App Publication

Now that we have created and tested our Function App locally it is time to publish it to Azure. Right-click on the project file in Solution Explorer and click Publish.

On the Publish dialog, we are going to Create New and Run from package file since it is recommended (see the docs for why it is recommended). Finally, click the Publish button.

The next dialog is the configuration for the App Service that will be created in Azure. You can take the defaults and hit Create, but I always take the extra time to create a new resource group so that my samples are easy to remove when I am done with them.

Clicking the create button will start the deployment to Azure which will take a few minutes. After the deployment, you can use the Azure Portal to test your Function App. More information on running a function from the Azure Portal can be found in the Azure Functions Introduction post.

Wrapping Up

While creating a function via the Azure Portal is the fastest way to get started, I would recommend you start locally. The slightly longer getting started time it worth it for the better tooling and flexibility it provides.

Create an Azure Function App from Visual Studio Read More »

Open an Azure Portal Created Function in Visual Studio

In last week’s post, Azure Functions Introduction, we created a new Azure Function App with a single function triggered via HTTP. The Portal is great for the initial creation of a function, but what happens when your needs change? For instance, you might want to store your functions in a repo with the rest of the code for your application. In this post, we are going to walk through taking our portal created function and getting it downloaded where it can be edited in Visual Studio.

Download App Content

From the Azure Portal select App Services.

Next, select the Function App you want to get the code for.

The detail of the Function App will load and at the top of the screen click on the Download app content option.

On the popup that shows select Content and Visual Studio Project and then click the Download button.

Once clicking download you will get a zip file containing everything in your Function App. Extract the files and double click the project file to open it in Visual Studio.

Changing a Function

The project will have a folder per function that exist in your applications. In our example, you would see a HttpTrigger1 directory and inside that directory, the code for the actual function is in the run.csx file.  Looking at the code you will see that it is the same that you would have seen in the portal. Here is the code.

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(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");
}

At this point, you could change anything you wanted about the application. I’m going to change the return value.

Before:
(ActionResult)new OkObjectResult($"Hello, {name}")

After:
(ActionResult)new OkObjectResult($"Yo, {name}")

Pushing Changes back to Azure

Now that we have a change to our function how do we get that change back to Azure? Head back to the overview page for your Azure Function App and click the Get publish profile link.

In Visual Studio right-click on the project and select Publish.

In the publish dialog click the Import Profile button and select the profile you download from Azure.

Once the profile is imported you can then click the Publish button to push any changes to your Azure Function App.

At this point, if you execute your function you should see the changes you made in Visual Studio.

Wrapping Up

While the above works it isn’t actually very friendly in Visual Studio since the function is a csx file instead of a cs file that normal C# uses. For next week look for an example of starting a function app from Visual Studio to see if it results in a project that will be easier to maintain.

Open an Azure Portal Created Function in Visual Studio Read More »

Deploy ASP.NET Core 3 Previews to Azure App Using Extensions

A few weeks ago when the post Deploy ASP.NET Core 3 Previews to Azure App Service I got an email from Jerrie Pelser who pointed out that there are extensions available for App Service that allow usage of the public previews of ASP.NET Core 3 without having to do a self-contained deployment.

In addition to Jerrie’s suggestion pajaybasu pointed out in this Reddit post that using Docker is another option. Pajaybasu also pointed out a line in the original post where I that self-contained deployments were the only option which of course was incorrect.

The first half of this post is going to be the same as the original post which covers the creation and the initial publication to Azure App Service. The last half will cover using an extension to enable the preview version of ASP.NET Core.

Sample Application

I used the following .NET CLI command to create a new ASP.NET Core application using React for its front end.

dotnet new react

After the creation process is complete open the project in Visual Studio. I highly recommend using the Visual Studio 2019 preview release when working with any .NET Core 3 applications.

Publish to App Service

In Visual Studio’s Solution Explorer right click on the project file and select Publish.

Select App Service for the publish target. Here we are creating a new app service. Next, click Publish.

The next dialog if the information about the new App Service that will be created. I took the defaults for the most part. I did create a new resource group for this application to make the resources easier to clean up in the future. I also changed the hosting plan to the free tier. Click Create to continue.

The Error and the Warning

As part of the publishing process, a browser will be opened to the address of the application. When this happens you will see an error about ANCM In-Process Handler Load Failure (if you are using IIS In-Process Hosting).

If you look back at Visual Studio you will see the following warning that your application requires the .NET Core runtime 3.0 and App Service only supports up to 2.2. Since we are going to fix this in App Service I recommend selecting Don’t perform check in the future (only this profile).

Another Fix

For this version of the fix, go to your App Service in the Azure Portal. In the menu under the Development Tools select the Extensions option.

On the next page click the Add button at the top. Click on the Choose Extension and select the ASP.NET Core 3.0 (x86) Runtime option.

Next, click Legal Terms, read the terms and if you are OK with the terms then click the OK button. You will then have to click OK on the add extension blade which will start the extension installation.

If you were to load your site at this point you would still get the 500 error. Under Settings click the Configuration and click on General settings turn Web sockets On and click Save.

At this point, your site should be working. You can also go back and turn web sockets back off and the site will continue working. I have no idea what toggling web sockets does to make everything start working, but thanks to this comment on a GitHub issue for the key to getting this working.

Wrapping Up

Hopefully, between this post and the previous one using a self-contained deployment, you won’t have any issues trying out the .NET Core 3 with App Service.

Deploy ASP.NET Core 3 Previews to Azure App Using Extensions Read More »

Azure Functions Introduction

Serverless seems to be all the rage these days. Each of the major cloud providers has a serverless offering with Azure Functions, AWS Lambda, and Google Cloud Functions. One of the big selling points of serverless function is the automated scaling based on your workload and the low cost.

For example with Azure using consumption billing, you get 1 million executions for free with each additional million executions costing only $0.20. It does get more complex as there is a charge based on execution time mixed with resource consumption, but you can check out the pricing page for the details.

This post is going to cover creating and calling a very simple function. Note that you will need an Azure account, if needed you can sign up for a free account.

Function App Creation

There are a lot of options to create a new function using everything from Visual Studio to the Azure CLI. For this post, we will be using the Azure Portal to create our function. Head to the portal and using the search box at the top search for function and in the results select Function App.

The above will take you to a list of your functions apps. Click either the Add button at the top of the page or the Create Function App button to create a new Function App.

The next step has a lot of options, but for this first, go we are going enter an App name and take the defaults for the rest of the options and click Create.

Clicking create will queue the deployment of a new function app and return you to the list of function apps on your account. After a few minutes, your new app should show in the list, this took almost 3 minutes for me. Once your app shows in the list select it.

Add a Function

Now that we have a Functions App it is time to add a Function. On the menu click the next to Functions.

The next screen will ask you to select a development environment. I will be using the In-portal option. After making the selection click Continue.

The next page will ask about how the function should be triggered. We will be using the Webhook + API option. There are a lot of options for triggers I recommend selecting the More templates option and exploring at some point. When finished click the Create button.

After the creation is finished you will see the code for your new function, which is defaulted to take a request with a name and respond with hello using the name supplied.

From the above page, you can make changes to your function and save them. To try the function out hit the Run button. Hitting the run button will show you the Test area where you can change and run the request to your function as you want and use the Run button to send the request.

Wrapping Up

While we have only scraped the smallest part of the surface of Azure Function Apps I can see why people are excited about the value they can provide. It was surprisingly simple to get started.

Stay tuned if you are interested in functions as I  play to do more exploration on this topic.

Azure Functions Introduction Read More »

Azure Application Insights: Analytics

I found one more feature of Azure Application Insights I wanted to point out before changing subjects. If you are just joining it might be worth checking out the previous entries in this series.

Add Application Insights to an Existing ASP.NET Core Application
Azure Application Insights Overview

Analytics

On the overview of your Application Insights resource click on the Analytics button.

This will take you to a page that will let you query your Application Insight data. The following is the page you will see with one of the example queries and the results it provides.

The official docs for Analytics provide a lot of good resources and I recommend checking them out. We are going to do some exploration in this post, but this post won’t be enough to fully explorer all you can accomplish with Analytics.

If you want to explore Analytics and you don’t have a site up yet or your site doesn’t have much data, like my sample application, check out the Analytics Playground provided by Microsoft.

Schema

Analytics provides a very powerful way to query for information about your application. The first thing I recommend you doing is exploring the schema of the data available. The left side of the page provides the details of the schema that is available. As you can see in the screenshot below you can query details from traces, page views, request, performance counts just to call out a few. Each type has its own set of fields available.

Query Entry

The query entry area is in the top center of the page. You can read up on the details of the query language here. Thankfully the query editor provides IntelliSense as you can see in the screenshot below.

While the syntax isn’t anything like SQL the data is organized in a way that having SQL experience helped me think about how to explored and relate the data.

Results

Clicking the Run button will execute your query and you will the results in the bottom of the page. As you can see the results default to a time chart based on the render statement in the query above.

The chart type can be changed in the results area. There is also an option to view results in a table view (this is the default view if you don’t have a render statement in your query).

Wrapping Up

It is amazing how many features Application Insights provides. I glad I happened to notice Analytics. If you are using Application Insights take the time and really explore all the features that it provides. You never know when you will find a feature that could up being a critical insight into your application.

Azure Application Insights: Analytics Read More »

Azure Application Insights Overview

In the Add Application Insights to an Existing ASP.NET Core Application post from last week, we got Application Insights up and running. This week my plan was to show off some of the features of Application Insights. It turns out this is hard to do in a meaningful way when your application isn’t getting any usage. While I have next to no data for most of the screenshots I still want to point out some of the areas of Application Insights that seem like they would be very useful.

Sample Application

For the most part, the post linked above is a good starting point with the exception of instead of using a React application I switched out for a Razor Pages application. The following is the command to create a Razor Page application with auth using the .NET CLI.

dotnet new webapp --auth Individual

The reason for this change was to get more items in App Insights since Razor Pages makes a request to the server per page.

Application Dashboard

The first item I recommend you check out is the Application Dashboard. On the Azure Portal select your App Insights resource and at the top click Application Dashboard.

This link will drop you on a page that will let you see how your application is doing at a glance. This includes everything from Unique sessions and Failed requests to Average I/O rate and Average available memory.

Live Metrics Stream

From your application dashboard or the App Insights menu you if you select Live Metrics Stream you will see real-time information about Incoming Requests, Outgoing Request, Overall Health, and a list of servers your application is running on and some stats about your usage on those servers.

Investigate

As a developer, a lot of the items in the Investigate menu jump out to me as being really helpful.

For example, Failures will give you a graph of failures over your selected timeframe with a list of the failed operations and a summary of the top 3 failed response codes, exception types, and dependency failures. The following screenshot is what it looks like, but my sample application doesn’t have any failures so it may not be super helpful.

The other option I want to point out is Performance which will give you a great summary of how your application is performing with break down by operation. This operation level view is a great place to spot areas in your application that may need some perf work.

Wrapping Up

This post covered a small fraction of the value provided by Application Insights. I encourage you to give the service a try especially if you are running a .NET application and most of the value can be provided without having to make any code changes.

Azure Application Insights Overview Read More »

Deploy ASP.NET Core 3 Previews to Azure App Service

I have found some time to play around with some of the features coming with ASP.NET Core 3 and I needed a place to host some of the applications I’m playing around with. Azure App Services has always been a great place for this type of thing, but as you will see in the details below it doesn’t support ASP.NET Core 3 by default currently.

This post is going to walk through creating a new ASP.NET Core 3 React application and publishing it to a new App Service with the default setting and then show you what to change to get the application to run.

Sample Application

I used the following .NET CLI command to create a new ASP.NET Core application using React for its front end.

dotnet new react

After the creation process is complete open the project in Visual Studio. I highly recommend using the Visual Studio 2019 preview release when working with any .NET Core 3 applications.

Publish to App Service

In Visual Studio’s Solution Explorer right click on the project file and select Publish.

Select App Service for the publish target. Here we are creating a new app service. Next, click Publish.

The next dialog if the information about the new App Service that will be created. I took the defaults for the most part. I did create a new resource group for this application to make the resources easier to clean up in the future. I also changed the hosting plan to the free tier. Click Create to continue.

The Error and the Warning

As part of the publishing process, a browser will be opened to the address of the application. When this happens you will see an error about ANCM In-Process Handler Load Failure (if you are using IIS In-Process Hosting).

If you look back at Visual Studio you will see the following warning that your application requires the .NET Core runtime 3.0 and App Service only supports up to 2.2.

The Fix

After dismissing the dialog above you will see a summary of the publish profile we created above. Click the Pincel next to the Framework-Dependent value for Deployment Mode.

In the dialog that pops up set the Deployment Mode to Self-Contained and select an appropriate Target Runtime for your App Service. In the case of this sample which is deployed to a Windows App Service, we are using win-x86.

Back on the publish profile summary screen click the Publish button to redeploy the application to App Service with the new settings. When the process finishes this time you should see a browser load with your application running properly.

Wrapping Up

This is a great example of the power of being able to do self-contained deployments. If this option didn’t exist then we would have no option for running .NET Core 3 applications on App Service.

Deploy ASP.NET Core 3 Previews to Azure App Service Read More »

Azure B2C: User Profiles

In this post, we will be adding access to user profiles using Azure B2C. We will be building on the setup used in the ASP.NET Core with Azure B2C Auth post so make sure and check it out if something in this post isn’t clear. The following is the full list of post from what has turned in to a series on Azure B2C.

ASP.NET Core with Azure B2C Auth
Azure B2C: Customize Layouts
Azure B2C: Social Logins

User Profile Flow

The first step to enabling profile access is to add the Profile editing user flow. From the menu for your Azure B2C resource select User flows.

At the top of the list of user flows click the New user flow button. This will display a list of recommended flows to add. From the list click Profile editing.

On the Create page enter a Name for your flow, select which Identity providers can use the flow, select which User attributes to collect/display, and then create the Create button. The user attributes you select will control which fields show when the user is editing their profile. Also, notice the Show more link which will give you a full list of the user attributes available on your account.

Sample Application

Back in the sample application in the appsettings.json file enter the name of the profile editing user flow from above for the EditProfilePolicyId.

"EditProfilePolicyId": "B2C_1_Profile"

Run the application and after login, the user’s name will be a link which will take them to a page where they can edit their profile information.

The following is a sample of what the profile page looks like.

Tweaking the Layout

From the screenshot, you will notice that the order of the fields wouldn’t make a lot of sense to a user. Thankfully B2C provides a way to customize the order of files, labels, control types, etc. without doing a full custom page which is also an option if you need to match an existing application’s look and feel.

From the B2C menu, select User flows and click on your profile flow. Once in your profile flow select Page layouts and then in the details select Profile edit page.

You will see something similar to the following screenshot. As you can see it allows reordering of fields, label changes, etc.

User Attributes

If the built-in user attributes don’t cover all your needs B2C does allow you to add your own attributes. From the main menu of B2C click on User attributes and you will see a list of your current attributes as well as an Add button if you need a custom attribute.

Wrapping Up

Enabling profile access was a pretty easy process and the flexibility provided with the built-in customizations is nice. I’m betting that most people will end up using a custom layout to give users a consistent experience. If you need help getting started with a custom layout check out my Azure B2C: Customize Layouts post.

Azure B2C: User Profiles Read More »

Azure B2C: Social Logins

This post is going to cover enabling a social login for a site using Azure B2C for authentication. If you are new to this set of posts you can find the initial setup of the sample application in the  ASP.NET Core with Azure B2C Auth post. I would also recommend checking out the Azure B2C: Customize Layouts to learn how to change the provided UI to provide your users with a consistent look and feel that matches the rest of your application.

Social Login Provider Setup

Azure B2C supports most of the login provides you would expect such as Google, Facebook, Twitter, Microsoft, etc. as well as any provider that supports OpendID Connect. No matter which option you pick you will have to register/signup your application with the provider. Unfortunately, Azure B2C doesn’t provide links to the registration pages of the services it supports so it is up to you to find those yourself.

For this example, I’m going to be walking through the process using Google. You can get all the details of Google’s OpenID Connect offering in their docs. To get started we need to set up our application in the developer console. The link will take you to the dashboard where you will see a message about selecting or creating a new project. Click the Create link. In the next page enter the Project name and click Create.

After the creation process finishes click Credentials from the navigation menu on the left.

On the top of the screen select OAuth consent screen. On this page, you will need to at least enter an Application name and an Authorized domain of b2clogin.com (not shown in the screenshot, but still required) and click the Save button at the bottom of the page.

Next, select the Credentials tab and click the Create credentials button and select the OAuth client ID option.

On the next page, select Web application as the application type. Enter a Name. For the next two fields, you will need your tenant ID from Azure B2C. In the screenshot, you can see my where I did this with my tenant ID of testingorg3. Also, make sure and enter the URLs in all lower case, I had redirect issues using mixed casing. For Authorized JavaScript origins use the URL https://yourtenantid.b2clogin.com and for Authorized redirect URIs use https://yourtenantid.b2clogin.com/testingorg3.onmicrosoft.com/oauth2/authresp

After clicking create you will see a dialog with your client ID and client secret make note of these as they will be needed when we add the login provider in Azure B2C.

Azure B2C Changes

Now that we have the Google side setup head over to Azure and find your Azure B2C resource. Select Identity provides from the navigation menu and click the Add button.

Enter a Name, I’m just using the name of the provider. Then, click on Identity provider type which will trigger the Select social identity provider selection to show. Click Google and then click OK.

Next, click Setup this identity provider which will show a fly out where you will need to enter your Client ID and Client secret provided by Google. After entering your values click OK.

Next, click the Create button at the bottom of the Add identity provider screen. When this process is done we will have two identity providers for this B2C resource email and Google. Next, we need to enable our new Google provider for our sign up/sign in user flow. From the menu select User flows and then click the flow you have set up for Sign up and sign in.

Next, select Identity providers, this will show a list of providers available for the selected flow. Check any additional providers the flow should use, Google, in our case. Finally, click Save.

Try it out

With all the above change attempt a login with your application and you will see Google as a sign in option.

Wrapping Up

Hopefully the above will give you a jump start on adding support for social logins to your applications. Adding other providers will really close to what we did for Google from the Azure B2C prospective, of course the sign up process will vary by provider.

Azure B2C: Social Logins Read More »

Azure B2C: Customize Layouts

In the post ASP.NET Core with Azure B2C Auth we did a walkthrough of setting up the basics of Azure B2C and creating a new application that used our new B2C setup for auth. This post is going to be using that same setup to show how to replace the Microsoft provided pages for sign up/sign in with your own custom pages.

Custom Page Hosting

Our custom page needs to be hosted somewhere public with CORS enabled. If the test application was hosted somewhere public we could just us it, but since it is running on localhost that isn’t currently an option. We are going to use Azure Blob storage for hosting in this example.

Create A Storage Account

From the Azure Portal select Storage accounts.

Click the Add button.

Next, on the Create storage account page, I used a new resource group and tried storage accounts names until I found an unused one. For the rest of the fields, I took the defaults and then clicked Review + create.

On the review + create page it takes a few seconds for the account to be validated. After validation click the Create button.

After the storage deployment is complete click the Go to resource button.

Setup Blob storage

The above will land you on the Overview page for the new storage account. Select CORS from the menu.

Since this is just a test I’m allowing everything under the Blob service, for a real deploy I would recommend only allowing the values you expect requests from. After setting your values click the Save button.

Back on the storage menu on the right side of the screen select Blobs.

Click the + Container button to create a new blob storage container.

In the new container, page enter a name and select your public access level. I’m going with the most permissive access level, for a production system you will need to evaluate the appropriate access level for your use case. Click OK when done.

When done you will be returned to your list of containers. Click on the container that was just created to view the details.

Create a custom page

Now that we have our blob storage we need to create the HTML page that we want to to use instead of the default. The following is the code for the page I’m going to use. It is going to be super ugly as I’m not going to use any styling.

<!DOCTYPE html>
<html>
  <head>
    <title>Custom Page!</title>
  </head>
  <body>
    <h1>Custom Page!</h1>
    <div id="api"></div> 
  </body>
</html>

You can make this page look however you want, but it will always need the div with the ID of API as this is where Azure will inject the elements that actually handle the signup/sign in. Save your page.

Upload custom page to blob storage

Back in Azure click the Upload button and then select your file and click the Upload button.

After upload, you will be returned to the list of items in your current container. Click the item you just created. In the details copy the URL as we are going to need it to give B2C the location of our custom page.

B2C use custom page

In your portal head back to your Azure AD B2C page and select User flows.

Select the flow you want to use the custom page for. In our case, we are going to be using the flow for Sign up and sign in.

In the Customize section select Page layouts.

In the bottom of the page select Yes for  Use custom page content and past the link to your blob from above into the Custome page URI field and click Save.

Try it out

With all of the above setup you can now go back to the application using B2C and hit your sign in link and you will see your custom page. Here is what the one in the sample looks like.

Obviously, this example is really ugly and isn’t something you would do to your users, but it gives you the basic idea of how to use a custom page.

Wrapping Up

Hopefully the above will help you get started with customizing you B2C related pages to give your users a more consistent look and feel. The above only uploaded an HTML page to blob storage, but you could also upload a CSS file or any other assets you need. Also, don’t forget if your site is publicly accessible the assets can be stored with the rest of your application in that is appropriate, just remember to configure CORS to allow requests from Azure.

If you want more information on this topic check out the official docs from Microsoft on the subject.

Azure B2C: Customize Layouts Read More »