-1

Edit: Not a duplicate, see the solution please. Required different solution than given possible duplicate link.

I'm trying to do a simple insert of record into database which also consist imagePath thus requires file upload. Like so:

public async Task<IActionResult> CreateArtifact(CreateArtifactViewModel input)
        {
            try
            {
                var path="";
                if (input.File != null)
                {
                    var fileName = Path.GetFileName(input.File.FileName);
                    path = Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/Images/"), fileName);
                    file.SaveAs(path);
                }
//rest of the method (irrelevant)...

But in the part where i do MapPath, i get error that HttpContext does not exist inside System.Web.

Did some research and tried to "add reference". But "add reference" window is just empty, only side projects that are in the solution are visible. So i added the System.web.dll reference by browse. But still no chance. Am i missing something, what can i do ?

Thanks.

Skywarth
  • 623
  • 2
  • 9
  • 26
  • You have `IActionResult` as your return type - is this actually a .NET Core project? – Tieson T. Aug 21 '19 at 05:49
  • It was due to recent changes to file upload approach. We used to implement blob manager for file upload. So it's not so important. This is .Net Core 2.2 web project. – Skywarth Aug 21 '19 at 06:03
  • And .NET Core doesn't normally reference System.Web. You're supposed to inject an `IHostingEnvironment` instance into the controller, and use that to get the site root (or content root, depending on what you're trying to map). Also, that makes some of your tags incorrect - there is a specific tag for asp.net-core, which isn't asp.net-mvc or asp.net-mvc-4 – Tieson T. Aug 21 '19 at 06:14
  • 1
    Possible duplicate of [How to get HttpContext.Current in ASP.NET Core?](https://stackoverflow.com/questions/38571032/how-to-get-httpcontext-current-in-asp-net-core) – Orel Eraki Aug 21 '19 at 06:20

1 Answers1

1

In ASP.NET Core, Server and Server.MapPath don't exist - those are part of System.Web, which is not part of the .NET Core stack. Instead, you use an instance of the IHostingEnvironment plus System.IO.Path to build the correct path. Something like this:

public class YourController : Controller
{
    private readonly IHostingEnvironment hostingEnvironment;

    public YourController(IHostingEnvironment env)
    {
        hostingEnvironment = env ?? throw new ArgumentNullException(nameof(env));
    }
}

Then, your code changes to be something similar to this:

public async Task<IActionResult> CreateArtifact(CreateArtifactViewModel input)
{
    try
    {
        var path = "";
        if (input.File != null)
        {
            var fileName = Path.GetFileName(input.File.FileName);

            // this should yield something like:
            //     c:\inetpub\yourappname\wwwroot\images\image-file-name.png
            path = Path.Combine(hostingEnvironment.WebRootPath, "Images", fileName);

            using (var fs = System.IO.File.Open(path, FileMode.Create))
            {
                file.OpenReadStream().CopyTo(fs);

                fs.Flush();
            }
        }

    // ... the rest of your code
}

Whether you use WebRootPath or ContentRootPath depends on where ~/Images is located - WebRootPath maps to the wwwroot directory, which is where your servable files are normally located.

You would make a few changes to your Startup.cs file, in order to inject IHostingEnvironment this way:

public class Startup
{
    private readonly IHostingEnvironment hostingEnvironment;

    public Startup(IConfiguration configuration, IHostingEnvironment env)
    {
        Configuration = configuration;
        hostingEnvironment = env;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton(hostingEnvironment.ContentRootFileProvider);

        //... the rest of ConfigureServices
    }

    //... the rest of Startup.cs
}

After this, you can inject IHostingEnvironment into controllers, view components, etc. where you need to get the path to the site root, among other uses.

Tieson T.
  • 20,774
  • 6
  • 77
  • 92
  • I think this will lead to solution but what is env defined in the first snippet ? What are we supposed to pass to it ? Thank you by the way. – Skywarth Aug 21 '19 at 06:32
  • 1
    `env` is an instance of `IHostingEnvironment` that gets injected into your controller's constructor and resolved using whatever dependency injection service you've configured (ASP.NET Core has a baked-in, though somewhat simplistic, DI service). – Tieson T. Aug 21 '19 at 06:41
  • Another thing is that input.file.SaveAs(path) is not a valid method, input.file.CopyTo(path) is available but i get an "cannot convert from string to System.IO.Stream" – Skywarth Aug 21 '19 at 06:44
  • I just copied that from your code. Most likely, `input.File` is an instance of `IFormFile`, which doesn't have a Save method. – Tieson T. Aug 21 '19 at 06:49
  • True, it's an IFormFile. Should i change it to some other type or should i try to fit in CopyTo method ? – Skywarth Aug 21 '19 at 06:50
  • 1
    I've updated the example, to show one method of writing the file. – Tieson T. Aug 21 '19 at 06:51
  • Perfect fit for my problem. Thank you so much for your time and effort. It worked like a charm. – Skywarth Aug 21 '19 at 07:11