Hosting Azure Functions backed Blazor application on Azure Storage static website

My previous blog post was an introduction to static website hosting on Azure Storage. This post focuses on how to deploy Blazor application as a Azure static website on Azure Storage and how to use Azure Functions as a server back-end for Blazor application hosted as a static site.

Source code available! Source code for this blog post is available in my GitHub repository gpeipman/BlazorDemo. Feel free to browse the code or run it in your own machine.

Getting started

Blazor applications are WebAssembly applications that run in all major browsers. These applications doesn’t need any back-end services to work but there is support for making AJAX requests to server. It can be service hosted on our own server but it can be also some external service running elsewhere.

I updated my Blazor demo application by adding support for Azure Functions and therefore also for static website on Azure Storage.

NB! This blog post is baed on Blazor demo application. I expect you to go through the code (not much code) to understand it better. Also I expect you to have at least some knowledge about Azure Functions. Good point to start is my blog post Getting started with Azure Functions

Database is needed! Blazor demo application needs also SQL Server database. By default it uses SQL Server LocalDB. It works when using Azure Functions with emulator on dev box. If you plan to put up things on Azure then you need also Azure SQL database. Demo application solution has Books.bacpac file you can use to restore database with sample data.

Service client for Azure Functions

In my demo application I have books client class that communicates with local back-end API implemented as MVC controller. For Azure Functions we need a little bit different client. Blazor client for Azure Functions uses different URL structure. All URL-s have host specified and additionally security code as query parameter (BooksAzureFunctionsClient.cs in BlazorDemo.Client project).

public class BooksAzureFunctionsClient : IBooksClient
{
    private readonly HttpClient _httpClient;

    private const string FunctionsHost = "https://****.azurewebsites.net/api";
    private const string FunctionsKey = "<Your functions key>";

    public BooksAzureFunctionsClient(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task DeleteBook(Book book)
    {
        await DeleteBook(book.Id);
    }

    public async Task DeleteBook(int id)
    {
        var url = FunctionsHost + "/Books/Delete/" + id + "?code=" + FunctionsKey;

        await _httpClient.PostAsync(url, null);
    }

    public async Task<PagedResult<Book>> ListBooks(int page)
    {
        var url = FunctionsHost + "/Books/Index/page/" + page + "?code=" + FunctionsKey;

        return await _httpClient.GetJsonAsync<PagedResult<Book>>(url);
    }

    public async Task<Book> GetBook(int id)
    {
        var url = FunctionsHost + "/Books/Get/" + id + "?code=" + FunctionsKey;

        return await _httpClient.GetJsonAsync<Book>(url);
    }

    public async Task SaveBook(Book book)
    {
        var url = FunctionsHost + "/Books/Save" + "?code=" + FunctionsKey;

        await _httpClient.PostJsonAsync<Book>(url, book);
    }
}

This client is actually more generic as it allows to use also other back-ends where same URL structure works.Supported are even those end-points where security code parameter is not mandatory and we can leave it empty.

Azure functions for data manipulation

When moving to Azure Functions we have to migrate all data manipuation code we have in web application controller. For every action in controller we define a function that Blazor application can call. As we are working on minimalistic demo application the move is simple. Here are functions for data manipulation (Functions.cs file in BlazorDemo.AzureFunctionsBackend project).

public static class Functions
{
    [FunctionName("Index")]
    public static IActionResult Index([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "Books/Index/page/{page}")]HttpRequest req,
TraceWriter log, [FromRoute] int page)
    {
        if (page <= 0) page = 1;

        using (var context = (new BooksDbContextFactory()).CreateDbContext())
        {
            var books = context.Books
                                .OrderBy(b => b.Title)
                                .GetPaged(page, 10);

            return new JsonResult(books);
        }
    }

    [FunctionName("Get")]
    public static IActionResult Get([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "Books/Get/{id}")]HttpRequest req,
TraceWriter log, [FromRoute]int id)
    {
        using (var context = (new BooksDbContextFactory()).CreateDbContext())
        {
            var book = context.Books.FirstOrDefault(b => b.Id == id);

            return new JsonResult(book);
        }
    }

    [FunctionName("Save")]
    public static IActionResult Save([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "Books/Save")]HttpRequest req, TraceWriter log)
    {
        using (var reader = new StreamReader(req.Body, Encoding.UTF8))
        using (var context = (new BooksDbContextFactory()).CreateDbContext())
        {
            var body = reader.ReadToEnd();
            var book = JsonConvert.DeserializeObject<Book>(body);

            context.Update(book);
            context.SaveChanges();
        }

        return null;
    }

    [FunctionName("Delete")]
    public static async Task Delete([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "Books/Delete/{id}")]HttpRequest req,
TraceWriter log, [FromRoute]int id)
    {
        using (var context = (new BooksDbContextFactory()).CreateDbContext())
        {
            var book = context.Books.FirstOrDefault(b => b.Id == id);
            if (book == null)
            {
                return;
            }

            context.Books.Remove(book);
            await context.SaveChangesAsync();
        }
    }
}

Before configuring functions on Azure Portal we need to implement DbContext factory used in functions.

DbContext factory for Azure Functions

To communicate with database we need to get connection string to database. When running Azure Functions emulator on local machine we can use local.settings.json file. At server we don’t have this file and application settings are coming in as environment variables. To support this I wrote DbContext factory that works for both cases (BooksDbContextFactory.cs file in AzureFunctionsBackend project).

public class BooksDbContextFactory : IDesignTimeDbContextFactory<BooksDbContext>
{
    private static string _connectionString;

    public BooksDbContext CreateDbContext()
    {
        return CreateDbContext(null);
    }

    public BooksDbContext CreateDbContext(string[] args)
    {
        if (string.IsNullOrEmpty(_connectionString))
        {
            LoadConnectionString();
        }

        var builder = new DbContextOptionsBuilder<BooksDbContext>();
        builder.UseSqlServer(_connectionString);

        return new BooksDbContext(builder.Options);
    }

    private static string ConnectionString
    {
        get
        {
            if(string.IsNullOrEmpty(_connectionString))
            {
                LoadConnectionString();
            }

            return _connectionString;
        }
    }

    private static void LoadConnectionString()
    {
        var builder = new ConfigurationBuilder();
        var settingsPath = Path.Combine(Environment.CurrentDirectory, "local.settings.json");

        builder.AddJsonFile(settingsPath, optional: true);
        builder.AddEnvironmentVariables();

        var configuration = builder.Build();

        _connectionString = configuration.GetConnectionString("DefaultConnection");
    }
}

Now let’s deploy functions to Azure. To make Blazor application work we have to copy Azure functions host and security key to Azure Functions client in Blazor.Client project.

  • Azure Functions host. Open Azure Portal and search for functions account you created for Blazor demo application. On Overview tab there is URL parameter. This is the functions host.
    Azure Functions overview tab
  • Security key. To get security click some function open and select Manage under function name. There is host keys section where keys for all functions are listed.
    Azure Functions host keys

Configuring Azure Functions in Azure Portal

There are few things left to configure on Azure portal:

  • Cross-Origin Resourse Sharing (CORS) – add all supported host headers (the hosts where Blazor application may onnect to functions) to CORS host list. For testing we can remove all headers and add just one with asterisk (*) as host to allow all clients to connect. (To find CORS settings move to Platform Features => API => CORS).
  • Ćonnection string – add connection string called DefaultConnection to functions account in Azure portal. (To find function app settings move to Platform Features => General Settings => Application Settings => Connection strings).

Our functions are now configured and it’s time to get Blazor application running on Azure Store.

Configuring Azure Functions for emulator in dev box

If you don’t want to use Azure Functions live version you can also go with Azure Functions emulator that is part of Visual Studio tooling. To make things work locally we have to edit local.settings.json file so it looks like shown here. For some reason this file doesn’t make it to source code repository. Just add it to root folder of AzureFunctionsBackend project.

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "AzureWebJobsDashboard": ""
  },
  "Host": {
    "LocalHttpPort": 7071,
    "CORS": "*"
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=Books;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

Publishing Blazor application to Azure static website

As we have now everything ready on Azure we can publish our Blazor application there. If you need better overview of steps below please go through my blog post Introducing static website hosting for Azure Storage. The blog post covers basics of publishing process in detail.

  • Open Visual Studio Code and install Azure Storage extension
  • Set up GPv2 storage account using Azure Portal
  • Publish Blazor application to some folder in your dev box
  • Open BlazorDemo.Client\dist subfolder of this folder in Visual Studio Code
  • Move to Azure Storage workspace, and open newly created storage account and open blobs
  • Right-click on $web container and select Deploy to static website…
  • Pick publish folder and start deployment

When Azure Storage extension is done with publishing it’s time to try out if Blazor application works with Azure Functions back-end. For this we need Azure static website URL and we can take it from Azure portal.

As I did everything right – otherwise there would have been nothing to blog about – I see the following view in my browser.

blazor-books-list

Wrapping up

Blazor applications are pure browser applications by nature and often they don’t need any background code to work. This blog post demonstrated how to host Blazor application as Azure static website and implement server back-end on Azure Functions that are consumed directly from browser. It is not perhaps so easy to do as building Web API but Azure Functions are the bes fit for small functionalities consumed often.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    4 thoughts on “Hosting Azure Functions backed Blazor application on Azure Storage static website

    • Pingback:Dew Drop - July 5, 2018 (#2759) - Morning Dew

    • June 21, 2019 at 1:22 am
      Permalink

      I cannot find the example project for this post in the repo. It looks like maybe this was just converted into the ADAL demo and the demo for blazor with azure functions / azure blob storage w/o authentication was removed or something?
      What am I missing?

    • April 15, 2025 at 12:13 pm
      Permalink

      But I additionally know simply how many rip-off-based mostly sites claim to be Ukrainian or offer dates with single Ukrainian women, solely to see what number of Ukrainian singles sites are actually scams. However, before planning a marriage with lovely Ukraine ladies, you might want to win the center of a Ukraine lady. You could introduce your lady to a family or pals, however all of your good and bad times need to come up in a dialog with anyone else. Family-oriented. Family holds a central place in Ukrainian culture, and many Ukrainian girls are very family-oriented. Ukrainian women make their household a protected house where everyone is welcome and accepted. Ukrainian women value their dad and mom and kinfolk, so you have to be ready to turn into a part of a big household. They value straightforward gentlemanly deeds like taking their jackets, opening doorways, and bringing blooms on times. The intention of this article is to share those suggestions with you now in case you desire to something up your sleeve subsequent time you meet someone totally different.

      British males are at ease spending their time in pubs. In case you are planning so far a British lad, take time to polish your conversational skills. When relationship a Ukrainian girl, you’re not wasting time with a “girl” who doesn’t know what she needs. She’ll see you want your dearest folks to know her. We wish stable and loving relationships with long-time period commitment. We all know our loved ones want a secure and inviting space to return to after a annoying or fantastic day. The most important thing to find out about Ukrainian women for courting is that they are only looking for a long-time period, critical relationship with the prospect of marriage. They are committed to associations after a couple of dates because they take them significantly. Make her feel special with considerate gestures, like remembering things she’s passionate about or planning meaningful dates. Nevertheless, she would like to care charmdate.com about you, but don’t suppose you may flip her utterly into an obedient housewife. As you possibly can see, many Ukrainian lady characteristics make a Ukrainian spouse a dream associate. Masculinity is what a Ukrainian girl really appears for in a relationship. Indeed, making ready an excessive amount of tells the Ukrainian lady that you simply don’t stay in abundance as you clearly don’t produce other choices in your love life.

      Your Ukrainian girlfriend will glow with natural magnificence and use sensible self-care routines that have been instilled in her since girlhood. Ukrainian ladies are good at cooking, cleansing, and protecting all the pieces under control. Ukrainian ladies are ferociously honest and demand the very best degree of honesty from their companions. They are additionally devoted and demand loyalty in returning. Don’t demand to meet her in actual life if she’s already informed you she needs extra time to get to know you. But not all people know methods to behave at the beginning of a relationship, what you’ll be able to or can’t say, what you are able to do and what can’t. Mutual respect is a base of every relationship, so don’t lose it. For example, sustaining eye contact signifies curiosity and respect. Ukrainian ladies appreciate any attempt of their males to share and respect their leisure activities. After the transaction is mad, the scammers will tell the Russian males that they can’t attend the date, and will recommend they ask for a refund. When you repeatedly inform her about your greatest options, your Ukrainian bride will hardly be pleased however but confused.

      The most effective ways to please her is to display involvement in her life-style. So, are you one of those conventional ladies who choose somebody with a standard method to relationship and relationships? Ukrainian people are strongly devoted to their associates and will never betray them. Because of this, a Ukrainian lady will likely be quite unbiased and sometimes less compromising in partnerships than you might anticipate. Make your lady chuckle and provides her compliments. Show your Ukrainian lady you’re a gentleman: be initiative, ask her to go out, pay for her taxi or dinner. Profiles are completely verified to ensure authenticity, giving you peace of mind as you discover potential connections. The best Ukrainian dating sites eliminate faux profiles and do their greatest to make sure a smooth and secure expertise for their customers. If you, desirous to make the very best impression, begin to behave artificially, then both the lady notices and becomes upset, or the relations are started but initially flip right into a “theater”.

    Leave a Reply

    Your email address will not be published. Required fields are marked *