-1

I have run into an issue I cannot seem to wrap my head around. We have an api which handles certain requests. When these requests fail, our api is supposed to send an email to certain people to notify them of the issue.

For this purpose I have created a new folder in our project and wrote a couple of .html files (templates) to use for sending emails. These have certain fields that are dynamically filled in depending on the called function and the error that could occur.

I have tested this quite extensively on localhost and here everything works fine. After publishing the app to our IIS, the problems start.

First call I make to the controller to send an email returns this error :

{
    "ClassName": "System.IO.DirectoryNotFoundException",
    "Message": "Could not find a part of the path 'C:\\inetpub\\wwwroot\\API\\HtmlTemplates\\LastCodeTemplate.html'.",
    "Data": null,
    "InnerException": null,
    "HelpURL": null,
    "StackTraceString": "   at System.IO.FileStream.OpenHandle(FileMode mode, FileShare share, FileOptions options)\r\n   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)\r\n   at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize)\r\n   at API.Core.Services.Service1.<GetLastCodeTemplate>d__5.MoveNext() in C:\\Users\\User\\Documents\\Projects\\API\\API\\Core\\Services\\Service1.cs:line 90\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at API.Core.Services.Service2.<SendProblemEmail>d__6.MoveNext() in C:\\Users\\User\\Documents\\Projects\\API\\API\\Core\\Services\\Service2.cs:line 101\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at API.Core.Services.Service3.<SendEmail>d__10.MoveNext() in C:\\Users\\User\\Documents\\Projects\\API\\API\\Core\\Services\\Service3.cs:line 311\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at API.Controllers.Controller2.<SendEmail>d__4.MoveNext() in C:\\Users\\User\\Documents\\Projects\\API\\API\\Controllers\\Controller2.cs:line 51",
    "RemoteStackTraceString": null,
    "RemoteStackIndex": 0,
    "ExceptionMethod": null,
    "HResult": -2147024893,
    "Source": "System.Private.CoreLib",
    "WatsonBuckets": null
}

The code for fetching the template from the folder :

public async Task<string> GetLastCodeTemplate(string startDate, string endDate)
{
    string body;
    var logo = _config["Logo:logoUrl"];
    var currentFolder = Environment.CurrentDirectory;

    using (var reader = new StreamReader(currentFolder + @"\HtmlTemplates\LastCodeTemplate.html"))
    {
        body = await reader.ReadToEndAsync();
    }

    body = body.Replace("{startDate}", startDate);
    body = body.Replace("{endDate}", endDate);
    body = body.Replace("{logo}", logo);

    return body;
}

The error is quite clear, the api cannot find the folder in the specified location. I've checked and the folder is not there on our IIS.

So now for the question(s):

  • Is this an issue caused by publishing the app and the folder not being contained in the publish files?

  • If yes, how would i go about fixing this issue so the folder and subsequent files are included? I would rather not create the folder and files manually since I feel these should be included in the project

  • If no, what could be the cause of this? Could I be looking in the wrong location when fecthing the file?

Haraldur
  • 227
  • 1
  • 3
  • 16
  • `Environment.CurrentDirectory` is not a sensible thing to be using within an `asp.net` application. There are *specific* tools designed to help you locate the physical path mapped to your application's structure. – Damien_The_Unbeliever Aug 01 '18 at 07:20
  • @Damien_The_Unbeliever could you be so kind as to give an example of these tools? – Haraldur Aug 01 '18 at 07:23
  • @mjwills will rework the question as requested but that is basically the issue I am experiencing – Haraldur Aug 01 '18 at 07:24
  • A client app does not have the credentials to read/write files on a IIS server. All temp files must be put on a drive that users have access to read/write. Not on the IIS. – jdweng Aug 01 '18 at 07:25
  • @jdweng this! This was indeed the issue. After moving the file to our public drive and having the code fetch the file from there it worked. – Haraldur Aug 01 '18 at 07:29

1 Answers1

1

If you want to find your application folder, under "classic" ASP.Net, you'd be looking for the MapPath function. (This concept was copied from "classic classic ASP").

Under asp.net Core, you should look to have the IHostingEnvironment injected into locations where you want to find file paths.

You should never (in any system, asp, console, etc.) assume the Environment.CurrentDirectory points anywhere useful, unless you're querying it immediately after startup. (In asp.net, any of your code is well divorced from the actual startup code)

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
  • Decided to give this a try and after looking into IHostingEnvironment i also got it to work on our IIS. Thanks! – Haraldur Aug 01 '18 at 08:00