260

Since Microsoft Web API isn't MVC, you cannot do something like this:

var a = Request.MapPath("~");

nor this

var b = Server.MapPath("~");

because these are under the System.Web namespace, not the System.Web.Http namespace.

So how do you figure out the relative server path in Web API ?
I used to do something like this in MVC:

var myFile = Request.MapPath("~/Content/pics/" + filename);

Which would give me the absolute path on disk:

"C:\inetpub\wwwroot\myWebFolder\Content\pics\mypic.jpg"
Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
Zachary Scott
  • 20,968
  • 35
  • 123
  • 205

8 Answers8

506

You can use HostingEnvironment.MapPath in any context where System.Web objects like HttpContext.Current are not available (e.g also from a static method).

var mappedPath = System.Web.Hosting.HostingEnvironment.MapPath("~/SomePath");

See also What is the difference between Server.MapPath and HostingEnvironment.MapPath?

Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • 1
    This is nice, but there's no easy way to mock HostingEnvironment since it is a static class instance... :-( – Josh G Jun 03 '15 at 13:59
  • 6
    Sure, but in your controller or other logic layer that you want to test, you would take only a dependency on your own abstraction, like `IPathMapper` (you'll probably roll this up with a bunch of other concerns into a bigger toolbelt / utility interface) with the method `string MapPath(string virtualPath)`. Only the concrete implementation for your `WebApi IPathMapper` needs to know about `System.Web.Hosting.HostingEnvironment` – StuartLC Jun 03 '15 at 14:05
  • 1
    @JoshG - you can abstract HostingEnvironment.MapPath via Func GetWebPath = HostingEnvironment.MapPath and then overwrite GetWebPath at test time with a mock. – Sean B Sep 17 '15 at 20:23
  • looks like this is having trouble with relative paths like `../images/` – AaA Jul 26 '18 at 08:17
  • Its giving the controller path, so can I get the service path by using the "HostingEnvironment"? – Md Aslam Dec 11 '18 at 09:20
17
string root = HttpContext.Current.Server.MapPath("~/App_Data");
Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
DLL_Whisperer
  • 815
  • 9
  • 22
  • 17
    You don't want to use HttpContext.Current in WebAPI. What about self-hosted APIs? You cannot rely in HttpContext.Current to be there. Also it is not test friendly. – Trevor de Koekkoek Mar 17 '14 at 18:40
  • It is not test-friendly that's correct. But in self-hosted apps there is still HttpContext ;) – DLL_Whisperer Mar 24 '21 at 14:05
2

As an aside to those that stumble along across this, one nice way to run test level on using the HostingEnvironment call, is if accessing say a UNC share: \example\ that is mapped to ~/example/ you could execute this to get around IIS-Express issues:

#if DEBUG
    var fs = new FileStream(@"\\example\file",FileMode.Open, FileAccess.Read);
#else
    var fs = new FileStream(HostingEnvironment.MapPath("~/example/file"), FileMode.Open, FileAccess.Read);
#endif

I find that helpful in case you have rights to locally test on a file, but need the env mapping once in production.

Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
Nathan Teague
  • 825
  • 6
  • 11
  • Fyi, the `HostingEnvironment` class is in the `System.Web.Hosting` namespace. – Dermot May 13 '15 at 04:49
  • 2
    What is the alternative to `HostingEnvironment ` for DNX core 5.0? – roydukkey May 14 '15 at 00:41
  • The new Startup.cs class now Injects an public Startup(IHostingEnvironment env){} on construction, the property slips my mind, just did this the other day. that allows you to also control an environment per instance, and using #if directives build an app that can cross tier deploy easily in multiple environments. – Nathan Teague May 30 '15 at 17:17
1

I can't tell from the context you supply, but if it's something you just need to do at app startup, you can still use Server.MapPath in WebApiHttpApplication; e.g. in Application_Start().

I'm just answering your direct question; the already-mentioned HostingEnvironment.MapPath() is probably the preferred solution.

sellotape
  • 8,034
  • 2
  • 26
  • 30
0

Since Server.MapPath() does not exist within a Web Api (Soap or REST), you'll need to denote the local- relative to the web server's context- home directory. The easiest way to do so is with:

string AppContext.BaseDirectory { get;}

You can then use this to concatenate a path string to map the relative path to any file.
NOTE: string paths are \ and not / like they are in mvc.

Ex:

System.IO.File.Exists($"{**AppContext.BaseDirectory**}\\\\Content\\\\pics\\\\{filename}");

returns true- positing that this is a sound path in your example

Giulio Caccin
  • 2,962
  • 6
  • 36
  • 57
Guest
  • 31
  • 1
0

Little bit late answering that but there we go.

I could solve this using Environment.CurrentDirectory

  • Could you add a bit more context on what your solution brings compared to the others and an example on how you would implement it ? – Sylvaus Nov 17 '20 at 00:42
-1

The selected answer did not work in my Web API application. I had to use

System.Web.HttpRuntime.AppDomainAppPath
Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
Zoomzoom
  • 1,042
  • 2
  • 13
  • 32
  • 1
    Although it seems this is the only way you can get path to your WebApi app, this gives you root of your application but doesn't translate relative paths such as `~\folder` or `../images/` to physical paths – AaA Jul 26 '18 at 08:15
-2

You can try like:

var path="~/Image/test.png"; System.Web.Hosting.HostingEnvironment.MapPath( @ + path)