I have a folder of files (form templates) that need to be accessed from both a .NET Web API application and a separate .NET MVC application. The folder for these form templates is outside of the websites. Ideally, I'd like to be able to store the path in the Web.Config files so that the applications can be easily tested in a local environment.
I tried setting up virtual directories on the hosted site but couldn't figure out how to reference them in the Web API. I tried several means of referencing the Virtual Directory that did not work. Most posts suggested trying Server.MapPath("MyVirtualDirectory") but that returns "....\wwwroot\MyApiController\Action\MyVirtualDirectory", not the physical path of the virtual directory.
I removed the Virtual Directory and attempted to "navigate" to the correct path but was blocked by "Cannot use a leading .. to exit above the top directory".
So what is the correct way to access a resource using a virtual directory in .NET Web API application? Is the same method going to work for the .NET MVC application?
You need to use HostingEnvironment, like:
public static string MapPath(string path){
string result;
result = HostingEnvironment.MapPath(path);
return result;
}
Additionally HostingEnvironment provides features like ApplicationPhysicalPath:
result = HostingEnvironment.ApplicationPhysicalPath + "App_Data\\somefile.xml";
Related
I have hosted ASP.net Core application in IIS, I have added a virtual directory into the wwwroot\images folder. But I am not able to access the contents in the folder. Can anyone help me? I need to share images between multiple ASP.net Core sites, so I tried using Virtual directory.
I fased same problem couple of weeks ago.
If your project is crossplatform you need to use virtual folders like this:
app.UseFileServer(new FileServerOptions()
{
FileProvider = new PhysicalFileProvider(#"D:\files"),
RequestPath = new PathString("/files"),
EnableDirectoryBrowsing = false // you make this true or false.
});
seting in iis will not work
I know I can get WebRoot by HostingEnvironment (Microsoft.AspNet.Hosting namespace).
I need to get a physical path according to a virtual path created in IIS within my web application. In IIS, the website root points to wwwroot of my published site and there is a virtual directory added in IIS which points to a folder outside of my wwwroot. I hope I can get the physical path of that virtual directory. In MVC 5 or earlier version, I can use HostingEnvironment.MapPath (System.Web namespace) or Server.MapPath, what should I do in MVC 6?
EDIT:
It's not the virtual path but the virtual directory added in IIS. I hope I can get the physical path of that virtual directory. I think virtual directory is a particular feature of IIS, which looks like a sub path of a full virtual path but can be a folder outside of physical web root folder.
Oct 4, 2015
Refer to this issue in ASP.NET 5 Hosting repo, So far, it doesn't seem we can get the physical path of a virtual directory in IIS.
You can use IApplicationEnvironment for that, which contains the property ApplicationBasePath
private readonly IApplicationEnvironment _appEnvironment;
public HomeController(IApplicationEnvironment appEnvironment)
{
_appEnvironment = appEnvironment;
}
public IActionResult Index()
{
var rootPath = _appEnvironment.ApplicationBasePath;
return View();
}
On Azure Web Apps, you'll find the wwwroot is in a different place:
All of the source code gets copied to D:/Home/site/approot/src/{WebsiteName} except the wwwroot. IApplicationEnvironment.ApplicationBasePath points here.
The wwwroot goes in D:/Home/site/wwwroot. IHostingEnvironment.WebRootPath points here.
It still won't work with IIS virtual directories. There is a WebRootFileProvider property on the IHostingEnvironment interface which provides an IFileProvider with methods like GetFileInfo(string subpath). I read the code and found subpath is a physical one, not a virtual one.
Obviously, in a self-hosted setup, there is no IIS. If you rely on IIS and really must do this, you'll probably have to reference System.Web.
HTH.
If I have an assembly library (dll) that is referenced from within an ASP.NET MVC app, is it possible for the assembly to get to the server path without having to pass it in from the MVC app, or have access to HttpContext?
If I use a relative path, it will return the processes path. In the case of running locally in debug, it is:
C:\Program Files\IIS Express
However, the file lives in the bin output, with this DLL, and the rest of the site's binaries.
Is my only choice to pass the path in from the web app?
UPDATE
For now, I'm just using HttpContext.Current.Server.MapPath(), but I don't like having to use HttpContext, in the event that we consume this API from something other than a web app.
To get the IIS server path that holds the web site you need HttpContext.Request.FilePath.
I pass the HttpContext into my library function, when I need to know where the web site is located.
However if you want to know the DLL's installed location, then I have seen it done using Assembly.Location
I'm trying to create a 'shared' MVC application, which can be used for all common data that is used by other MVC and legacy Web applications.
For example, I have two Virtual Directories setup on my server:
mysite.com/Report
mysite.com/Base
So what I'd like to be able to do is this to include a view from the 'base' folder in the 'Report' one;
#Html.Partial("/Base/Views/Shared/_NavigateMenu.cshtml")
Note that ~ in Report will go to mysite.com/Report, I cant use that.
However doing so results in the following exception:
The virtual path '/Base/Views/Shared/_NavigateMenu.cshtml' maps to another application, which is not allowed.
I know about areas however there are a lot of downsides in using them, firstly I cant (or is very difficult) to migrate the existing legacy applications into a area, also logistically it is nicer to have each MVC application separated and have a space for common objects. (Not just views, but css, images, etc.)
So the question is how do I 'allow' MVC to map and thus access to other applications?
Trying to share a MVC aplication is basically trying to share several different components :
Controllers should be shared through a separate class library, reachable through area registrations
Models can be in any referenced class library
for views, I assume base Base application root folder contains the application web.config. Views, hosting the views, can contain a web.config relative to views rendering (say for razor configuration)
To use Views in application Report, you have to create a virtual directory SharedViews (or whatever name you want) in Report, which will point to the physical path of Base/Views.
Then you will be able to write :
#Html.Partial("~/SharedViews/Shared/_NavigateMenu.cshtml")
The points are :
having a virtual directory in Report, to avoid switching from an app to another
having this virtual directory not reference the root directory of Base, to avoid app configuration conflicts
you can resolve this problem using the char ~ before virtual path i.e.
#Html.Partial("~/Base/Views/Shared/_NavigateMenu.cshtml")
or else
if it is specified path set up as a Virtual Directory in IIS than it may treat it as another application even though it's in the same directory as the main application.
I want to be able to have a folder which allows regular access like the \content folder except that it holds a ClickOnce application. I can't seem to be able to achieve this using Mvc, but I'd like to have this folder accessible without Mvc seeing it as a controller action.
I tried using routes.Ignore(theUrl), but this seemed to have no effect.
There are two ways you can do this. The first is where you are currently going, which is to satisfy it with routing. You should be able to use the following to ignore the intended route:
routes.IgnoreRoute("...")
However, this might not be the right approach from a security stand point. I would recommend you define an explicit action to download your click-once exe. Have a look at this q/a as an example of using the FileContentResult class.
The reason for this is that you can control security for that file without having to open up access levels to other directories.
Edit: If this is for an entire directory, you can still follow this same approach.
Set up the folder as a virtual folder in the website on IIS. then you can set the url in the code to point to the machine serving the request and to the virtual folder on the web server.