FileSystemProviders and Writing Files - Writes to all of them

I am trying to get my head around the virtualfilesources:

I registered two:

AddVirtualFileSources.Add(new AzureBlobVirtualFiles(AppSettings.Get<string>("storageConnection"), "logfiles2"));     
 AddVirtualFileSources.Add(new AzureBlobVirtualFiles(AppSettings.Get<string>("storageConnection"), "logfiles2"));

Then I did this:

Apphost.VirtualFileSources.WriteFile("test3a.txt", "test");
Apphost.VirtualFileSources.WriteFile("logfiles/test3b.txt", "test");
Apphost.VirtualFileSources.WriteFile("logfiles2/test3c.txt", "test");

What I got was all three files written to both the File system providers. I was kind of expecting it to be based off the /logfiles folder but that doesn’t seem to be the case. How does the cascading providers work when writing? Writes to all of them and I need to use the VirtualFiles instead?

Screen shots of what happens after those three lines execute:
logfiles1 container: https://db.tt/zkHJjR9FWk
logfiles2 container: https://db.tt/BhBqqp2a5L

VirtualFileSources is a readonly list of cascading VFS sources, the VirtualFiles is what you should assign to your single VFS you want to write files to.

I guess I’m not understanding something. First, the code I posted does write files, in fact it wrote files to both registered virtual file sources. I switched it to using VirtualFiles and in that case it only wrote to the first registered file source. I thought it would choose the file source to write to based off the folder path but that seems to be only for serving files which is fine. How can I control which VFS gets written to in a service if I have multiple and have multiple use cases and secondly if I want to add security to those folders do I need to do it via a global filter?

It doesn’t choose, you do, by assigning VirtualFiles to the VFS you want to write to.

VirtualFileSources contains multiple public VFS sources which should only be used to read files.

VirtualFiles should be assigned to a single VFS provider to write to, it can be configured to write to an internal FS since only VirtualFileSources are publicly readable.

They’re completely different properties which just share the same interface.

Nothing in ServiceStack writes to files, your Services do that by uploading/writing files to base.VirtualFiles. You could also ignore the VFS abstraction and write to the FS directly but then you wouldn’t be able to easily substitute the FS, test your Services, etc.

I was writing to them with the code I posted above in a unit test as well as a service. Okay, I think I understand. You are saying in the apphost config I should do something like this:

VirtualFiles = new AzureBlobVirtualFiles(AppSettings.Get(“storageConnection”), “logfiles”);

Do I still need to register it here? AddVirtualFileSources.Add(new AzureBlobVirtualFiles(AppSettings.Get(“storageConnection”), “logfiles2”));

all VirtualFiles.WriteFiles will go to that one and one only (VirtualFiles that was set in the appconfig). I can switch it out if I want but can only write to one virtual file provider in the app using the default base.VirtualFiles.

They’re different unconnected properties, if you also want VirtualFiles to be readable, add it to:

AddVirtualFileSources.Add(VirtualFiles);

1 Like

apologies for weighing in here - I had a thought relevant to my own development that might be contextual. If I have different APIs which use different file sources for different reasons (1 saves avatar images or internal web resources and another saves organisational documents to blob storage, for instance) - how would I selectively choose which VF providers to use? I wouldn’t want the organisational documents included as a read-source when looking for web assets (and vice versa), and I would selectively want to choose which VF source I was writing to depending on the context.

would the approach be to pull the providers out of the IOC container and use them directly in each use case?

would the approach be to pull the providers out of the IOC container and use them directly in each use case?

Based on what mythz wrote I think you’d have to do something outside the standard VirtualFiles base property. I’m guessing you could create them, inject them in your service and use them independently. Hopefully he can confirm that for you.

public class AvatarVirtualFiles : AzureBlobVirtualFiles  {
        public AvatarVirtualFiles(string a, string b) : base(a, b)
        {

        }
    };

Register<AvatarVirtualFiles>(new AvatarVirtualFiles("","");

Right, VirtualFiles is just a single property (unused by ServiceStack itself) whose convention is to specify the VFS your App is configured to write to. If your App requires multiple write sources, don’t use it, use your own classes / dependencies instead.

thanks for the feedback here guys, sorry for the late response. Using my own providers/dependencies was the way to go.