Intro
I like to make small projects from time to time, where I check out new technologies or updates from already existing tech. And this time, it’s Blazor Interactive SSR (Server Side Render). And this project is a small one. In essence, I want this project to be a video conversion website, where you can upload a video, and convert it to a different codec and container.
In this blogpost, I will outline solutions to problems I discovered doing the development of this project. I will also show some tip and tricks to leverage your project.
Problem
One problem I ran into was trying to make a file upload form. The way Microsoft shows how to do it in their documentation does not work with Interactive SSR, only with Blazor WebAssembly and Blazor Hybrid. The way I got it working was to wrap the InputFile
in a form. Plus there is also some other inputs in the form.
<EditForm Model="@File" OnSubmit="Upload">
<InputFile OnChange="OnFileSelected"></InputFile>
<InputSelect @bind-Value="Codec">
@foreach (FFOptionsCodecs codec in Enum.GetValues<FFOptionsCodecs>())
{
<option value="@codec">@codec</option>
}
</InputSelect>
<InputSelect @bind-Value="Filters">
@foreach (FFOptionsFilters filter in Enum.GetValues<FFOptionsFilters>())
{
<option value="@filter">@filter</option>
}
</InputSelect>
<button type="submit">Upload</button>
</EditForm>
Handlers
I have two handlers, plus their interfaces, that handles (pun intended) various parts of the solution.
FileHandler.cs
handles creation and deletion of files from the user input.
This class is really simple. It contains 3 methods.
Task SaveFile(IBrowserFile file)
Task<bool> DeleteTempFile(string filePath)
string GetFileReference(string filename)
VideoHandler.cs
handles conversion of video files.
There is a bit more meat on this one, not in terms of method count, but more in terms of lines.
bool ConvertVideo(string filePath, FFOptionsCodecs codecs, FFOptionsFilters filters, out string newFilePath)
string ChooseCodec(FFOptionsCodecs codecs)
string ChooseContainer(FFOptionsCodecs codecs)
Helpers/Extension Methods
To better handle file saving and just about handling files, I have created two extension methods. One to remove the file ending of a file. Such as .mp4
, so it’s easier to save the file with a different container, such as .webm
.
The other method is to get a filename from the given path. It’s so I can better move the file to another directory.
Extension methods:
static string RemoveFileEnding(this string fileName)
static string GetFileNameFromPath(this string path)
They are incredibly simple:
public static string RemoveFileEnding(this string fileName)
{
int endingIndex = fileName.LastIndexOf('.');
return fileName.Remove(endingIndex);
}
public static string GetFileNameFromPath(this string path)
{
return path.Split('/')[^1]; // "Index from end expression". Same as final.length - 1
}
csproj
The .csproj
file can become quite handly once you know what you need and don’t need in your project.
Here is a list of flags I usually add to my .csproj
file:
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
<InvariantGlobalization>true</InvariantGlobalization>
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
<StartupHookSupport>false</StartupHookSupport>
For example, in this project, I don’t have any code that handles dates or time, so I don’t need any kind of timezone support. Therefor I add <BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
.
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
link<InvariantGlobalization>true</InvariantGlobalization>
link<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
link<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
link<StartupHookSupport>false</StartupHookSupport>
link
Misc
With C# evolving, new syntax gets added. And one of the new syntax features I feel is pretty cool is the “Index from end expression” collection syntaxt. It looks like this [^1]
. It can help de-clutter code. Here is a before and after example, of how I used it:
Before:
public static string GetFileName(this string path)
{
string[] final = path.Split('/');
return final[final.Length - 1];
}
After:
public static string GetFileNameFromPath(this string path)
{
return path.Split('/')[^1]; // "Index from end expression". Same as final.length - 1
}
Quite neat huh? Do be aware that this does not change anything in the performance department. It it strictly syntax sugar, since it compiles down to the excact same IL code.
Code
I have set up a small Git repo with the code. There are some stuff I haven’t added yet, such as filtering the video. That might get added in the future, but I have made some preperations for it to be implemented.
Code can be found on my self hosted gogs instance at git.rbwr.dk