UseStaticFiles uses Path.GetFullPath which causes issues with UNC paths

Jul 9, 2014 at 12:47 PM
I have a path at \sharedfolders\myproj\ and when I pass that into UseStaticFiles it throws a DirectoryNotFound exception as it converts it to c:\sharedfolders\myproj
Coordinator
Jul 9, 2014 at 4:11 PM
(Unless there's an HTML error...) \sharedfolders\myproj\ is not a UNC path, it's a path relative to the root of the current drive. \\sharedfolders\myproj would be a UNC path to machine 'sharedfolders', share 'myproj'.

The following worked fine for me:
            app.UseStaticFiles(new StaticFileOptions()
            {
                RequestPath = new PathString("/static"),
                FileSystem = new PhysicalFileSystem(@"\\MyOtherMachine\SomeShare")
            });
Jul 9, 2014 at 4:15 PM
Edited Jul 9, 2014 at 4:25 PM
Must be a HTML bug but it was \sharedfolders\myproj.

Not sure how that works for you as its the same as what I had

I had

.UseStaticFiles(new StaticFileOptions { FileSystem = new PhysicalFileSystem(Path.Combine(AssemblyDirectory, "static")), RequestPath = new PathString("/static") })


Path.Combine returned \Shared Folders\Projects\OwinTest\NowinHost\bin\Debug\static

But then throws saying \Shared Folders\Shared Folders\Projects\OwinTest\NowinHost\bin\Debug\static doesnt exist. I think its in the GetFullRoot of the PhysicalFileSystem constructor which is causing issue
Coordinator
Jul 9, 2014 at 4:25 PM
On codeplex you can use the backtick character to escape code fragments or triple-backticks before and after code blocks to escape multi-line segments.

Can you share the actual code?
Jul 9, 2014 at 4:29 PM
Coordinator
Jul 9, 2014 at 4:40 PM
Hmm, not directly related to your problem, but your AssemblyDirectory code is weird. Try this:
                string codeBase = Assembly.GetExecutingAssembly().CodeBase;
                Uri uri = new Uri(codeBase);
                var dir = uri.LocalPath;
                return dir;
That said, codeBase should not be returning a UNC path, unless your binaries are actually running from a UNC? (NOT recommended)
Jul 9, 2014 at 4:45 PM
My solution is on OSX and via a VM in Windows I share that folder so windows sees it as a UNC.

If I map a drive so I open the solution at z:\mysln.sln it all works fine.

Your code will return \\vmware-host\Shared Folders\Projects\OwinTest\NowinHost\bin\Debug\OwinCore.DLL
Coordinator
Jul 9, 2014 at 4:57 PM
Interesting... Well, I'd expect it to work based on my sample above. Try getting rid of this extra code and just hardcode the UNC path like I did.
Jul 9, 2014 at 4:58 PM
I did, it still failed
Jul 15, 2014 at 9:36 AM
Here's a screenshot.

My code seems to be returning the correct path in the "Watch" window

However, the middleware seems to add an extra "Shared Folders" in the path as shown in the exception

Image
Coordinator
Jul 17, 2014 at 9:37 PM
Repro: Execute the following code directly from a UNC share.
        static void Repro()
        {
            string codeBase = Assembly.GetExecutingAssembly().CodeBase;
            Console.WriteLine("Base: " + codeBase);

            UriBuilder uri = new UriBuilder(codeBase);
            string path = Uri.UnescapeDataString(uri.Path);
            Console.WriteLine("Path: " + path);

            var root = Path.GetDirectoryName(path);
            Console.WriteLine("Root: " + root);

            // Start of PhysicalFileSystem
            var applicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
            Console.WriteLine("Base: " + applicationBase);

            var merged = Path.Combine(applicationBase, root);
            Console.WriteLine("Merg: " + merged);

            var fullRoot = Path.GetFullPath(merged);
            Console.WriteLine("Full: " + fullRoot);
            Console.ReadKey();
        }
Output:
Base: file://chrross-svr1/shared/Http/AppContainer/ConsoleApplication45.exe
Path: /shared/Http/AppContainer/ConsoleApplication45.exe
Root: \shared\Http\AppContainer
Base: \\chrross-svr1\shared\Http\AppContainer\
Merg: \shared\Http\AppContainer
Full: \\chrross-svr1\shared\shared\Http\AppContainer
        static void Fix()
        {
            string codeBase = Assembly.GetExecutingAssembly().CodeBase;
            Console.WriteLine("Base: " + codeBase);

            Uri uri = new Uri(codeBase);
            string path = uri.LocalPath;
            Console.WriteLine("Path: " + path);

            var root =  Path.GetDirectoryName(path);
            Console.WriteLine("Root: " + root);

            // Start of PhysicalFileSystem
            var applicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
            Console.WriteLine("Base: " + applicationBase);

            var merged = Path.Combine(applicationBase, root);
            Console.WriteLine("Merg: " + merged);

            var fullRoot = Path.GetFullPath(merged);
            Console.WriteLine("Full: " + fullRoot);
            Console.ReadKey();
        }
Output:
Base: file://chrross-svr1/shared/Http/AppContainer/ConsoleApplication45.exe
Path: \\chrross-svr1\shared\Http\AppContainer\ConsoleApplication45.exe
Root: \\chrross-svr1\shared\Http\AppContainer
Base: \\chrross-svr1\shared\Http\AppContainer\
Merg: \\chrross-svr1\shared\Http\AppContainer
Full: \\chrross-svr1\shared\Http\AppContainer
Conclusion: The Uri processing code in AssemblyDirectory incorrectly drops a leading \ when it calls UriBuilder.Path. Uri.LocalPath correctly handles UNC paths.
Jul 23, 2014 at 11:21 AM
Thanks, that solved it :)