Running Blazor Web App

My web site is running on Linux/Apache server. So, I wanted Blazor Web App to run on that server too.

Developing Blazor app was quite easy and straight forward process but writing the right .htaccess file was not so easy. I searched the internet and found sample on Microsoft web pages (https://docs.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/?view=aspnetcore-6.0&tabs=visual-studio), but provided .htaccess file sample was not enough.

I think that running Blazor on Apache is interesting for others too, so here is .htaccess file I am using in production (just update string ‘sub-directory’ (2x) with correct directory path of your app on Apache file system).

Link to GitHub gist: Apache .htaccess file for running Blazor Web App (github.com)

<IfModule mod_headers.c>
    # Serve brotli compressed files if they exist and the client accepts brotli.
    RewriteCond "%{HTTP:Accept-encoding}" "br"
    RewriteCond "%{REQUEST_FILENAME}\.br" "-s"
    RewriteRule "^(.*)\.(js|json|css|dll|dat|blat|wasm)$" "$1\.$2\.br" [QSA]

    # Serve gzip compressed files if they exist and the client accepts gzip.
    RewriteCond "%{HTTP:Accept-encoding}" "gz"
    RewriteCond "%{REQUEST_FILENAME}\.gz" "-s"
    RewriteRule "^(.*)\.(js|json|css|dll|dat|blat|wasm)$" "$1\.$2\.gz" [QSA]
    
    # Serve correct content types, and prevent double compression.
    RewriteRule "\.css\.br$" "-" [T=text/css,E=no-brotli:1]
    RewriteRule "\.js\.br$"  "-" [T=text/javascript,E=no-brotli:1]
    RewriteRule "\.json\.br$"  "-" [T=application/json,E=no-brotli:1]
    RewriteRule "\.dll\.br$"  "-" [T=T=application/octet-stream,E=no-brotli:1]  
    RewriteRule "\.dat\.br$"  "-" [T=application/octet-stream,E=no-brotli:1]  
    RewriteRule "\.blat\.br$"  "-" [T=application/octet-stream,E=no-brotli:1]  
    RewriteRule "\.wasm\.br$"  "-" [T=application/wasm,E=no-brotli:1]  
    
    # Serve correct content types, and prevent double compression.
    RewriteRule "\.css\.gz$" "-" [T=text/css,E=no-gzip:1]
    RewriteRule "\.js\.gz$"  "-" [T=text/javascript,E=no-gzip:1]
    RewriteRule "\.json\.gz$"  "-" [T=application/json,E=no-gzip:1]
    RewriteRule "\.dll\.gz$"  "-" [T=T=application/octet-stream,E=no-gzip:1]  
    RewriteRule "\.dat\.gz$"  "-" [T=application/octet-stream,E=no-gzip:1]  
    RewriteRule "\.blat\.gz$"  "-" [T=application/octet-stream,E=no-gzip:1]  
    RewriteRule "\.wasm\.gz$"  "-" [T=application/wasm,E=no-gzip:1]  
    
    <FilesMatch "(\.js\.br|\.css\.br|\.json\.br|\.dll\.br|\.dat\.br|\.blat\.br|\.wasm\.br)$">
      # Serve correct encoding type.
      Header set Content-Encoding br
      # Force proxies to cache brotli & non-brotli
      Header append Vary Accept-Encoding
    </FilesMatch>
    
    <FilesMatch "(\.js\.gz|\.css\.gz|\.json\.gz|\.dll\.gz|\.dat\.gz|\.blat\.gz|\.wasm\.gz)$">
      # Serve correct encoding type.
      Header set Content-Encoding gzip
      # Force proxies to cache gzipped & non-gzipped
      Header append Vary Accept-Encoding
    </FilesMatch>
</IfModule>

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /sub-directory/
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /sub-directory/index.html [L]
</IfModule>

XAML DataGrid using one DataTable as lookup

Problem:

I have a DataTable with lookup column into another table. Another table is a small table so all the records can fit in small combobox and the user wants to be able to select lookup record with combobox.

Solution:

XAML has DataGridComboBoxColumn, but it is difficult to bind, because DataGridComboBoxColumn can’’t bind to Windows binding source. It is obviously quite know problem, but I could’n’t find an easy solution.

Test tables:

MAIN_TABLE 
{ 
  ID, 
  SubTableID, 
  ... other fields ...
}

SUB_TABLE 
{ 
  ID, 
  Description 
}

Naive

Naive solution, that doesn’’t work

<DataGrid ItemsSource="{Binding mainTable}">
  <DataGrid.Columns>
    <DataGridTextColumn Header="ID" 
                        Binding="{Binding ID}" />
    <DataGridTextColumn Header="SubID" 
                        Binding="{Binding SubTableID }" />
    <DataGridComboBoxColumn Header="Desc" 
                            ItemsSource="{Binding subTable}}" <!-- can't bind! -->
                            SelectedValueBinding="{Binding SubTableID}"
                            SelectedValuePath="ID" 
                            DisplayMemberPath="Description" />
  </DataGrid.Columns>            
</DataGrid>

The solution doesn’’t work because – for some reason– DataGridComboBoxColumn can’’t bind subTable even if it is defined exactly as mainTable in datasource for the whole xaml window.

Solution

The solution is quite easy. Create a resource that binds to sub table and then use that resurce sa data source 🙂


<DataGrid ItemsSource="{Binding mainTable}">
  <DataGrid.Resources>
    <CollectionViewSource x:Key="cvsSubTable" 
                          Source="{Binding subTable }"/> <!-- can bind! -->
  </DataGrid.Resources>
  <DataGrid.Columns>
    <DataGridTextColumn Header="ID" 
                        Binding="{Binding ID}" />
    <DataGridTextColumn Header="SubID" 
                        Binding="{Binding SubTableID }" />
    <DataGridComboBoxColumn Header="Desc" 
                            ItemsSource="{Binding Source={StaticResource cvsSubTable }}"  <!-- now it is ok! --> 
                            SelectedValueBinding="{Binding SubTableID}"
                            SelectedValuePath="ID" 
                            DisplayMemberPath="Description" />
  </DataGrid.Columns>            
</DataGrid>         

Lost 4 hours on that! Grrrr..