Building Xero Files Integration with .NET Blazor WebAssembly

Albert Gromek
Xero Developer
Published in
9 min readMay 6, 2021

--

In 2018, Microsoft created a new experimental .NET web framework that runs on the browser called Blazor. It allows .NET developers to build an interactive web UI with C#. With the release of .NET 5.0 in late 2020 came the official production ready release of Blazor WebAssembly.

Blazor WebAssembly compiles all the required code (.NET libraries and your application) and executes in the user’s browser. This results in better UI performance compared to the traditional Blazor Server apps which used a SingalR connection for UI rendering as each request and UI action no longer has to be sent to the server to be re-rendered.

In this blog post, we’ll go through setting up a Blazor WebAssembly Sample Application from scratch in VSCode. It also demonstrates how to connect to the Xero Files API using the Xero NetStandard SDK to do cool things like getting, uploading, and deleting files. Files are used in a variety of ways including proof of transaction, or copy of a contract with a customer or supplier.

The Xero API doesn’t currently support requests from Single Page Applications (SPAs). We use the ASP.NET Core Hosted model of Blazor WebAssembly in this blog. This allows us to add an API layer for making requests using the Xero NetStandard SDK.

You can peruse, download and play with the complete project shown in this blog on Github.

Prerequisites

Before starting you should install the .NET Core 5.0 SDK and Visual Studio Code including the Microsoft C# extension[C# for Visual Studio Code (powered by OmniSharp)].

Create a Xero app for OAuth 2.0

If you don’t have a Xero user account, you can create one for free. Once you’ve activated your user account and enabled the Demo company:

Setting up a new .NET Blazor WebAssembly application

Once we set up our Xero app, open a VSCode terminal in the directory and we’ll create our Blazor WebAssembly project using the existing dotnet templates:

dotnet new blazorwasm -ho -au Individual -o BlazorFilesApp

The -hosted flag will choose the hosted option which adds a server project to our application. The -au Individual flag adds built in OIDC authentication which we can use to authenticate with Xero.

You should see 3 new folders in VSCode in the directory we just created BlazorFilesApp.

Project structure

The Client project holds our Blazor front-end’s razor components and the Server project is the API layer we use to interact with the Xero API through the NetStandard SDK. The Shared project allows us to add shared models. For example, when building a custom Upload object that contains data needed for Xero API, we can define an Upload object once in the Shared folder and then serialize and deserialize it to transfer the data from the Client to Server.

Navigate to our newly created Server project cd BlazorFilesApp/Server and run it using the dotnet run command.

If everything is set up correctly, you’ll see something like below in your output window. Our project will be running on https://localhost:5001

Output

Navigate in your browser to https://localhost:5001 and we’ll see the vanilla application running:

Screenshot of running application

Once the app is running correctly, let’s add in the required code for Xero authentication.

First you will need to add your client id into the appsettings.json file in the client project. (Client/wwwroot/appsettings.json).

Then, you will need to add the OIDC configuration in the Program.cs file of the Client project (after the AddScoped method).

Next, we will add in an AuthorizeView component on the main page to print out a list of claims for the logged in user. We add this in the Index.razor component. Put the code inside an <Authorized> tag so it will only be displayed when a user is Authorized.

Now run the application again using the dotnet run command and test the new login functionality by clicking on the Login button. It should redirect to the Xero login page where we can enter our Xero login details and choose the organisation to connect to and authorize it. You’ll be redirected back to the main page of the Blazor app, and a list of claims for the logged in user are displayed.

Screenshot showing logged in user

And that’s all there is to setting up your first Blazor WebAssembly project with authentication. If you’d like more information about setting up authentication or using the Xero NetStandard SDK refer to the Microsoft documentation for securing a Blazor WebAssembly application and check out the Getting Started with Xero .NET SDK blog.

The code for this project is available on Github. Keep reading for a walk through of the basic structure of the project and go through some of the functions for getting, uploading, and deleting files.

Blazor Project Walkthrough

We already know that we have to use the ASP.NET Core hosted model of Blazor WebAssembly because the Xero API doesn’t support requests from SPAs. But what does this mean for how we actually build our application?

In the ASP.NET hosted model of Blazor WASM, the Blazor Client app is created together with a backend ASP.NET Core app to serve its files and make external API requests. The Client app communicates to the Server using web API calls.

In our project, we use the inbuilt OIDC authentication to manage login and OAuth 2.0 with the Xero Identity Server using PKCE. This means our Client app manages the auth flow, login state, and keeps the access tokens required to interact with the Xero API (via the NetStandard SDK) in the session.

It will add these access tokens to each request sent to the ASP.NET Core Server, and the server uses these tokens and the NetStandard SDK to authenticate requests sent to the Xero API.

Solution diagram

The app functionality is outlined below:

Files:

  • Upload a File
  • Upload a File to a Folder
  • Get Files
  • Delete Files.

Folders

  • Create Folder
  • Delete folder

Associations

  • Create Association
  • Delete Association
  • Get Association

The app has three razor pages to achieve this functionality. The tabs are only visible when a user has logged in and is Authorized.

.gif animation showing the app functionality

Now let’s use Blazor code to interact with the Files API.

Uploading Files

For uploading files, we first need to make a POST request from our Client app to our Server app with the required data (FileName, FileContent, Size, ContentType, FolderId). Then in the Server app we can use the Xero NetStandard SDK’s UploadFileAsync()to do the file upload.

We start by creating a XeroUpload model and adding it to the Shared project. Both Client and Server projects have references to the model making it a breeze to send to the Server project and deserialize.

With our model ready, we can go about getting the file from the user.

Luckily, there is a new Blazor component for uploading files added in ASP.NET Core 5.0. It does all the logic of handling our file upload. Without it, you might need to write some custom Javascript code to compensate.

The component supports uploading both single and multiple files in Blazor. In this app, I used it for single file uploads — all you need to do is add the InputFile component in the razor component we use for Files Upload/Viewing/Deletion. (Client/Pages/Files.razor)

<InputFile OnChange="@SingleUpload" />

This adds a basic Choose File button to our page, and opens a File Explorer window in our Operating System when clicked to choose the file we want to upload.

We can then use the OnChange method in the code section of our razor component to get an InputFileChangeEventArgs object when a file is submitted. This is just a List of IBrowserFile which you can use to get the Name, LastModified, Size and ContentType, as well as an OpenReadStream method for getting the file Stream.

Because the Xero API and NetStandard SDK (and our XeroUpload model) expect a byte array, we will have to do a little bit of work to convert the stream, then we can build the XeroUpload object and send it off to the server.

The upload action can be bound to a separate Upload button, but for simplicity we make the file upload trigger automatically once a file is selected.

One more thing to keep an eye on is the folderId, this is being read from a dropdown on the razor component where the user can choose a folder to upload the file to (Which is populated using the FilesApi.GetFoldersAsync() method). If they choose a folder we will add it to our XeroUpload object, if not then it will be set to null and we can deal with it on the Server.

Now that we have the required logic sorted in the Client project we can take a look at the controller method in the Server. When we get a request at the /uploadfile endpoint, we simply instantiate a FilesApi, get the required tokens which were attached by the OIDC packages to the Authorization header, and then make a request using either the UploadFileAsync or UploadFileToFolderAsync method of the SDK depending on whether a folderId was supplied or not.

And that’s all there is to uploading a file from a Blazor WebAssembly front-end to the Xero API.

Now let’s take a look at how we can get and display all the files on a page.

Get Files

In the same razor page (Client/Pages/Files.razor) we used for uploading files, we have a List of FileObject we use for storing the files we get from Xero. We will use the OnInitializedAsync() method for getting data from Xero. It executes when the component is loaded and after initializing instance variables. In this case we use the /getfiles endpoint on our Server.

filesItems = await Http.GetFromJsonAsync<List<FileObject>>("getfiles");

Then in the controller on the Server we use the GetFilesAsync method of the SDK to get all the files from our Xero organisation.

Now that we have the files loading into our Files page, we can display them in the UI. Blazor makes this super easy as we can simply write a mix of HTML and C# code to programmatically put a table together with the list of files we’ve got.

And we will see in the GitHub repository that this is wrapped in an if else statement that shows some simple loading text while the files haven’t been loaded yet. There is also a fourth column in our table which holds a Delete button for deleting files, so let’s go ahead and see how that’s been implemented.

Deleting Files

Each row in the Files table has a Delete button for deleting a file. The @onclick function of the button calls the Delete method, passing the FileObject itself as a parameter.

<button @onclick="() => Delete(file)">Delete</button>

In Blazor even though we can write our application using only C# and html, it is still possible to invoke JavaScript functions from .NET and .NET methods from JavaScript functions (this is called JavaScript interoperability or JS interop). This is utilised by injecting the IJSRuntime abstraction into our Files component.

@inject IJSRuntime JsRuntime

Then we invoke a JavaScript confirm function which instructs the browser to display a dialog box with our formatted string message and returns a boolean of the result. If the user has confirmed the deletion, we will send a POST request to the /delete endpoint on our Server containing the object we want to delete, and then reload the list of files to update the display on the UI.

The delete logic in the controller is very similar to the upload and get endpoints:

Conclusion

Blazor WebAssembly apps are getting more and more traction and lots of updates even as I write this blog. I’m excited to see what other goodies the team at Microsoft will be releasing. There is some more functionality in the codebase for creating and deleting folders and associations if you’d like to check it out.

I hope you found this article useful to your own project or helped you understand Xero’s files API better.

Over 2 million businesses use Xero for accounting. Partner with us and join the 70k+ users of our developer platform to build awesome integrations and apps for the Xero ecosystem.

--

--