dev

New Version of the GPWebpayNet v1.2.0 Has Been Released

New version of the GPWebpayNet v1.2.0 has been released. It adds new methods into IEncodingService and IClientService to be able to set certificate instance directly instead of path to certificate file and its password.

Install it from NuGet via

Install-Package GPWebpayNet.Sdk -Version 1.2.0

Clone it on GitHub here.

Enjoy!

 

Advertisements
dev

Deploying and Hosting Static Web Sites (ReactJS, Angular) in Azure App Service

Outline

On Azure, you can host a static web multiple ways

  • As separate App Service
  • Via Blob Storage and CDN
  • As a part of App Service (that hosts, e.g., an API)

Hosting As a Part of App Service

You you want to host the site in some existing App Service that already hosts some app, e.g., Web Api, it is a very simple process – just copy the built web into wwwroot folder. There is only one problem – proper routing. Because now there are basically two sources that are provided:

  • Web site
  • Api endpoints

the simplest way how to distinguish between Api and Web App is to use different ports. But it is not possible in our case because App Service supports only port 80/443. So it must be done in a different way.

Rewrite Rules

In out case we will use rewrite rules defined in immortal web.config file. Basically, we have to distinguish between following resources:

  • Api routes (third negation in wwwroot-spa-routing-to-index rule)
  • Web App root file, e.g., index.html (rules wwwroot-static-files and wwwroot-spa-routing-to-index)
  • Static files, e.g., images, fonts, styles, etc. (content of element handlers)
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <system.webServer xdt:Transform="Insert">
        <rewrite>
            <rules>
                <rule name="wwwroot-static-files" stopProcessing="true">
                    <!-- Following extensions should be defined in <handlers /> section -->
                    <match url="([\S]+[.](html|htm|svg|js|css|png|gif|jpg|jpeg|woff|woff2|eot|ttf|map))" />
                    <action type="Rewrite" url="wwwroot/{R:1}" />
                </rule>
                <rule name="wwwroot-index" stopProcessing="true">
                    <match url="^$" />
                    <action type="Rewrite" url="wwwroot/index.html" />
                </rule>
                <!--
                    Note: root path must be set to "/" ,i.e., <base href="/" />
                    otherwise relative paths will not work
                -->
                <rule name="wwwroot-spa-routing-to-index" stopProcessing="true">
                    <match url=".*" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                        <add input="{REQUEST_URI}" pattern="api/" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="wwwroot/index.html" />
                </rule>
            </rules>
        </rewrite>
        <handlers>
            <add name="StaticFileModuleHtml" path="*.htm*" verb="*" modules="StaticFileModule" resourceType="File"                  requireAccess="Read" />
            <add name="StaticFileModuleSvg" path="*.svg" verb="*" modules="StaticFileModule" resourceType="File"                  requireAccess="Read" />
            <add name="StaticFileModuleJs" path="*.js" verb="*" modules="StaticFileModule" resourceType="File"                  requireAccess="Read" />
            <add name="StaticFileModuleCss" path="*.css" verb="*" modules="StaticFileModule" resourceType="File"                  requireAccess="Read" />
            <add name="StaticFileModuleJpeg" path="*.jpeg" verb="*" modules="StaticFileModule" resourceType="File"                  requireAccess="Read" />
            <add name="StaticFileModuleJpg" path="*.jpg" verb="*" modules="StaticFileModule" resourceType="File"                  requireAccess="Read" />
            <add name="StaticFileModulePng" path="*.png" verb="*" modules="StaticFileModule" resourceType="File"                  requireAccess="Read" />
            <add name="StaticFileModuleGif" path="*.gif" verb="*" modules="StaticFileModule" resourceType="File"                  requireAccess="Read" />
            <add name="StaticFileModuleWoff" path="*.woff" verb="*" modules="StaticFileModule" resourceType="File"                  requireAccess="Read" />
            <add name="StaticFileModuleWoff2" path="*.woff2" verb="*" modules="StaticFileModule" resourceType="File"                  requireAccess="Read" />
            <add name="StaticFileModuleEot" path="*.eot" verb="*" modules="StaticFileModule" resourceType="File"                  requireAccess="Read" />
            <add name="StaticFileModuleTtf" path="*.ttf" verb="*" modules="StaticFileModule" resourceType="File"                  requireAccess="Read" />
            <add name="StaticFileModuleMap" path="*.map" verb="*" modules="StaticFileModule" resourceType="File"                  requireAccess="Read" />
            <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
        </handlers>
        <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false"                     stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
    </system.webServer>
</configuration>

 

Thats all. Routes matching api/ pattern will be routed to your Web Api. All other routes except static files will be routed to the index.html, where the SPA’s routing will do its work.

Conclusion

There are many methods how to publish SPA web site in Azure. If you want to host together with your Web Api in the same App Service, all you need is a proper web.config setup.