I'm building a Dotnet Core web app that needs to allow the Windows-Authenticated user to browse through the connected virtual directories and view and select files hosted there.
Is there a way for a Dotnet Core application to access a virtual directory? And barring that, is there a way for a regular Dotnet application to do it?
It is possible to do so. I've been working on this thing for two weeks now, looked everywhere to get an answer. Here is how I did it.
You will need to add in the configure app.UseFileServer() in the Configure method of the Startup.cs
app.UseFileServer(new FileServerOptions
{
PhysicalFileProvider("\\\\virtualPath\\photos\\wait\\"),
RequestPath = new PathString("/AROULETTE"),
EnableDirectoryBrowsing = true
});
How does this work?
The way it is set up, you would enter http://localhost:5000/AROULETTE
and it would open the virtual path provided in the PhysicalFileProvider in the browser. Of course this is not what I actually wanted.
I needed to create a directory and copy files into the virtual directory with C#.
Once I had the FileServer setup, I tried something like this which does not work.
if(!Directory.Exists("/AROULETTE/20170814"))
{
Directory.Create("/AROULETTE/20170814")
}
of course, neither does this
var path = Path.Combine("http://localhost:5000/", "AROULETTE/20170814")
if(!Directory.Exists(path)
{
Directory.Create(path)
}
Instead, you just use the actual virtual path of the folder.
if(!Directory.Exists("\\\\virtualPath\\photos\\wait\\20170814"))
{
Directory.Create("\\\\virtualPath\\photos\\wait\\20170814")
}
Thus UseFileServer is used to create a "bridge" between the application and the virtual folder the same way that you would create a virtual directory with ASP.Net 4.5
Hope this can help some people because most of the answers about this topic were not clear at all.
Related
I have a Blazor Server 6.0 app where I have links to download .msg files.
I have setup IIS to serve that mime-type trying both application/octet-stream and application/vnd.ms-outlook (and restarting IIS)
I have also tried to put in web.config the staticcontent tag like suggested here:
.msg file gives download error
And obviously in my program.cs I have app.UseStaticFiles();
I try to put the .msg in a non-blazor app and they work ok, so I think is not IIS related
So why I cannot download (or open automatically in outlook) this type of file, while other (docx, pdf, zip, etc.) are Ok ?
ASP.NET Core -- on the server side -- also needs to know about the files it has to serve. You can enable serving all unknown file types (I'd rather not include the relevant code as it is a major security risk), or you can add you own additional mappings like so:
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".msg"] = "application/vnd.ms-outlook";
// app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = provider
});
More info in the official docs: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-7.0#fileextensioncontenttypeprovider
Additionally, Blazor Server registers custom options for serving static files (like .server.js, which is different from just .js). It's not directly exposed as a public API to configure, but you can look at the source here as to what the AddServerSideBlazor extension method actually does. The solution there relies on you calling UseStaticFiles without explicitly specifying the options, so that it can retrieve the StaticFilesOptions instance from DI.
Armed with this knowledge, you can override an already configured options instance as follows:
builder.Services.PostConfigure<StaticFileOptions>(o =>
{
((FileExtensionContentTypeProvider)o.ContentTypeProvider).Mappings[".msg"] = "application/vnd.ms-outlook";
});
This configures the already initialized options instance registered in the DI (after all other configurations happened on it, thus PostConfigure).
Note that if you would for whatever reason decide to use a different IContentTypeProvider, the unsafe cast above would need to be revised as well.
Problem:
trying to get an image out of azure fileshare for manipulation. I need to read the file as an Drawing.Image for manipulation. I cannot create a valid FileInfo object or Image using uncpath (which I need to do in order to use over IIS)
Current Setup:
Attach a virtual directory called Photos in IIS website pointing to UNCPath of the Azure file share (e.g. \myshare.file.core.windows.net\sharename\pathtoimages)
This works as http://example.com/photos/img.jpg so I know it is not a permissions or authentication issue.
For some reason though I cannot get a reference to File.
var imgpath = Path.Combine(Server.MapPath("~/Photos"),"img.jpg")
\\resolves as \\myshare.file.core.windows.net\sharename\pathtoimages\img.jpg
var fi = new FileInto(imgpath);
if(fi.exists) //this returns false 100% of the time
var img = System.Drawing.Image.FromFile(fi.FullName);
The problem is that the file is never found to exist, even though I cant take that path and put it in an explorer window and return the img.jpg 100% of the time.
Does anyone have any idea why this would not be working?
Do I need to be using CloudFileShare object to just get a read of a file I know is there?
It turns out the issue is that I needed to wrap my code in an impersonation of the azure file share userid since the virtual directory is not really in play at all at this point.
using (new impersonation("UserName","azure","azure pass"))
{
//my IO.File code
}
I used this guys impersonation script found here.
Can you explain why DirectoryInfo.GetFiles produces this IOException?
I crated area/modular MVC5 application according to this tutorial:
This
it worked perfectly on local. but i got 404 error, when i deployed project on iis and clicked on specified area link.
and i didn't find any solution for that.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Sale
and this is my action links which are perfectly working on local run:
#Html.ActionLink("Sale","Index","Sale",new { Area="Sale"},null)
edited:
public class SaleAreaRegistration:AreaRegistration
{
public override string AreaName
{
get
{
return "Sale";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Sale_default",
"Sale/{controller}/{action}/{id}",
new { controller = "Sale", action = "Index", id = UrlParameter.Optional },
new string[] { "MVCPluggableDemo.Controllers" }
);
}
}
attention: according to the tutorial which i said in first line. i created my module project in another virtual project in solution(the real path is in area folder of main project like"~/ProjectName/Areas/"). but i think the publisher does't understand it...because i don't see any of my module views in deployed path.
its better to completing my help request by this obvious question:
How to deploy MVC project include areas, and the modules which are in areas folder?
Its simply obvious:
Check your page directory. The server cannot locate your the file,
it maybe in different folder.
Also try to Check this.
the main Reason of my problem was this:
VisualStudio doesn't include my Area folder, in publish path..why? i don't know
Solution: no solution yet!..but i added my module dll inside bin folder manually. and created my areas folder and his modules projects solution(dlls' are not not necessary) in main published solution, manually to ..
finally it worked, but i dont thing is the standard solution
I want my MVC3 web application to access %APPDATA% (e.g. C:\Users\MyUsername\AppData\Roaming on Windows 7) because I store configuration files there. Therefore I created an application pool in IIS with the identity of the user "MyUsername", created that user's profile by logging in with the account, and turned on the option "Load User Profile" (was true by default anyway). Impersonation is turned off.
Now I have the problem that %APPDATA% (in C#):
appdataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
resolves to c:\windows\system32\inetsrv instead of C:\Users\MyUsername\AppData\Roaming.
UPDATE: More exactly, the above C# code returns an empty string, so that Path.GetFullPath(Path.Combine(appdataDir, "MyAppName")) prepends the current path to my application name, resulting in c:\windows\system32\inetsrv\MyAppName.
I know I made this work before with the same web application on a Windows Server 2008 R2, and now I'm getting this problem with the same major version 7.5 of IIS on my Windows 7.
I used the same procedure as before: Created a new user, logged in as that user to create the profile and APPDATA directories, then added the application pool with this identity and finally added the web application to this pool.
Any ideas?
Open your %WINDIR%\System32\inetsrv\config\applicationHost.config and look for <applicationPoolDefaults>. Under <processModel>, make sure you don't have setProfileEnvironment="false". If you do, set it to true.
Application Pools - Your application Pool - Advanced settings ...
Process Model - Load user Profile set True.
It Helps me.
Taken from
https://blogs.msdn.microsoft.com/vijaysk/2009/03/08/iis-7-tip-3-you-can-now-load-the-user-profile-of-the-application-pool-identity/
I experienced the same problem recently. As mentioned by Amit, the problem is that the user profile isn't loaded. The setting is for all application pools, and is in the applicationHost.config (typically C:\Windows\System32\inetsrv\config\applicationHost.config). If you update the applicationPoolDefaults elements as follows, it will work;
<applicationPoolDefaults managedRuntimeVersion="v4.0">
<processModel identityType="ApplicationPoolIdentity" loadUserProfile="true" setProfileEnvironment="true" />
</applicationPoolDefaults>
We've tried this with IIS 7.5, and taken it through to production without problem.
You can automate this if you want;
appcmd set config -section:system.applicationHost/applicationPools /applicationPoolDefaults.processModel.setProfileEnvironment:"true" /commit:apphost
or if you prefer powershell
Set-WebConfigurationProperty "/system.applicationHost/applicationPools/applicationPoolDefaults/processModel" -PSPath IIS:\ -Name "setProfileEnvironment" -Value "true"
Hope this helps
I am experiencing the same problem. Have you by chance installed the Visual Studio 11 beta? I did recently, and I've noticed a couple of differences in how the 4.0 compatible .dlls for that work with our code. I'm still trying to track down the problem for certain, but I didn't have this problem before that.
Edit:
After comparing the decompiled sources from 4.0 and 4.5 for GetFolderPath (and related), there are differences. Whether they are the source of the problem...I'm not sure yet.
Edit 2: Here are the relevant changes. I'm working on trying both to see if I get different results. [code removed]
Edit 3:
I've now tried calling SHGetFolderPath directly, which is what the .NET Framework ends up doing, anyway. It returns E_ACCESSDENIED (-2147024891 / 0x80070005). I don't know what has changed where I'm getting that in some specific cases, but not in others.
Edit 4:
Since you're getting a empty string, you may want to switch your code to use SHGetFolderPath so you can get the HResult and at least know what exactly is happening.
void Main() {
Console.WriteLine( GetFolderPath( Environment.SpecialFolder.ApplicationData ) );
}
[System.Runtime.InteropServices.DllImport("shell32.dll")]
static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken, uint dwFlags, StringBuilder pszPath);
private string GetFolderPath( Environment.SpecialFolder folder ) {
var path = new StringBuilder( 260 );
var hresult = SHGetFolderPath( IntPtr.Zero, (int) folder, IntPtr.Zero, 0, path );
Console.WriteLine( hresult.ToString( "X" ) );
return ( (object) path ).ToString( );
}
The problem is with your IIS settings. The answer is here: Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) returns String.Empty
Given virtual directory and port can you find the actual path of a web application?
I can get the virtual directory and port via a visual studio setup project, and I'd like to make some modification to the web.config file after install (using a custom action).
You could use DirectoryEntry class:
using (var entry = new DirectoryEntry("IIS://server/W3SVC/1/root/VirtualDirectoryName"))
{
var physicalPath = entry.Properties["Path"].Value;
}