System.IO.FileNotFoundException when saving file on server - c#

I know that this error has more awnsers on this form but none seem to be working since they are having problems with localhost. But localhost works fine for me.
I'm trying to create a .xlsx file from a button click on the server.
I already contacted the hosting company to make sure that it is possible to place files like this on there server and they told me that I could. So.... that is not the probleme.
This works perfect on localhost. But when I move it to the webhost I get this error:
I use this code:
using (var stream = new MemoryStream())
{
// local path
//string path = #"D:\local\Test\order.xlsx";
// Server path
string path = HostingEnvironment.MapPath(#"~\Excel-Exports\order.xlsx");
workbook.SaveAs(path);
var content = stream.ToArray();
File(
content,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"order.xlsx");
}
Before this part of code I build the Excel file. So I don't think that is the probleme.
I think the probleme is with the path since the tells me that I cant not find the file.
For the record I do use the same method for reaching a path on a different location and this works just fine.
Working code on other location
string path = HostingEnvironment.MapPath(#"~/img/MetropolisGO_RGB-kleur1.png");
LinkedResource Img = new LinkedResource(path);
Does anyone have a solution for me to save this file on the server?

The error indicates that the project is missing "ClosedXML" version 0.95.4 that is reference or using it but there is no DLL or library or project to be used.
If it's in your project, check the order of the building.
If is third-party, check the DLL or library is "copy always" in the build

Related

Path error when accessing .cshtml file in Azure App Service

I have an asp.net core 5 application running on Azure App Service, which should fetch a .cshtml file that serves as an email template. I use the .ContentRootPath attribute of the IWebHostEnvironment interface to return the first part of the path, and I concatenate the rest of the path to the file, with a string. Locally, everything works fine, but there is something wrong with fetching the .cshtml file when the application is running in Azure.
When fetching the .cshtml, the following error is observed:
Could not find a part of the path '/home/site/wwwroot/wwwroot/Templates/Email/EmailRegistroAssinatura.cshtml'
But locally, none of that happens. I expected the .ContentRootPath attribute to return the first part of the path according to the environment where the application was running.
My code is the following:
using Microsoft.AspNetCore.Hosting;
string projectRootPath = _hostingEnvironment.ContentRootPath;
string file = "wwwroot/Templates/Email/" + fileName + ".cshtml";
string path = Path.Combine(projectRootPath, file);
using (StreamReader reader = File.OpenText(path))
{
htmlStringEmail = reader.ReadToEnd();
}
What to do to get the path correctly, using the same code in both environments?
After my test, I found the root cause. The reason is the static files(folder) not include when you deploy it. You can go to kudu site and check it.
I face the error message like below.
I check the static files under wwwroot, and can't find the Templates folder, then I add all the folders and file manually like below.
Then I test again and it works well.
Summary
You can search the official doc about how to include static files when you deploy the project. Or add it manually.
Pls not use .cshtml file as template, you should use .html file, as we know, the contents under wwwroot should be static files. Normally we will create new .cshtml files under Views folder.

How to get the path of the uploaded file within the AppBundle?

We are using Autodesk Forge's Design Automation API. We have an AppBundle ready and we put an .rfa file into the same folder which contains the .dll file. When the AppBundle is unzipped on the Forge servers, which path can lead to our .rfa file? (how can we access it?) Our goal is to place the attached Family file's contents into the input file which is being uploaded with the API, and the result should be a new file which contains the additions from the file which we uploaded within the AppBundle. The process works when testing with Revit locally, but it doesn't work with the API. In the report we are retrieving it's obviously pointing out that the attached file cannot be found:
Autodesk.Revit.Exceptions.FileNotFoundException: T:\Aces\Jobs\ced628d35ecf4412b68c024e2cec098b\something.rfa
On the code side, we are trying to access the .rfa file via this path:
static string currentDir = Environment.CurrentDirectory;
static string path_input = currentDir+#"\something.rfa";
This seemed as a logical path, but as it turned out, it's not..
Is there a way to access the .rfa file inside the uploaded AppBundle?
I took a look at the Restrictions but reading the file from the AppBundle is not mentioned as restricted or not approachable. Am I missing something?
A .NET assembly knows its own path. You can call System.Reflection.Assembly.GetExecutingAssembly().Location within it to find the current path of the dll. You can then compute the path of the .rfa file relative to the folder of the dll and use it / open it. Thus you should be able to open any file you package along with your addin in your appbundle.
You can simply modify your code to:
static string assemblyLocation = Assembly.GetExecutingAssembly().Location;
static string assemblyDirectory = Path.GetDirectoryName(assemblyLocation);
static string path_input = assemblyDirectory+#"\something.rfa";
One thing to note however, is that you only have readonly access to files in appbundle. If your code relies on modifying these during execution, then you may simply copy the source rfa file to the current working folder and then work with the copied file instead.
Also see more details in blog for similar ideas.
We have a blog post on how you can either pass in the app bundle path in the commandLine parameter or find the path via the location of the add-in dll:
https://forge.autodesk.com/blog/store-template-documents-appbundle

Can access private file in localhost, but not in production

I'm writing an ASP.NET Core app, and I'm trying to use a file's path without exposing it to the web. I set it to copy to output directory, so it loads when I test it on localhost, but it gives me an error when published to the web:
The system cannot find the file specified.
This is the code that generates the path:
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config", "filename.p12");
I've also tried
Path.Combine(Environment.CurrentDirectory, "Config", "filename.p12");
I'm guessing AppDomain.CurrentDomain.BaseDirectory and Environment.CurrentDirectory point to a different location when published? Or filename.p12's 'Copy to Output Directory' property doesn't carry over to the published version?
EDIT:
I also tried:
Path.Combine(environment.ContentRootPath, "Config", "file.p12");
Where environment is an IHostEnvironment, to the same effect. I'm getting the feeling that the file isn't being copied over into the published version. So, I changed the filename I put in this question to be file.p12 instead of file.txt, which is what I originally put it as, in case it doesn't copy over that type of file for security reasons.
The error said The system cannot find the file specified., but the file was actually there. I was actually missing the X509KeyStorageFlags.MachineKeySet flag when I read the .p12 file. I think the reason it didn't work in production was that the server's current user didn't own the file, so I needed to specify that the machine owns it with that flag.

Access a jpg in an Image folder of a project

I am working on a program that generates a PDF using a third party .dll. I am trying to add a header image to the PDF by sending in the string path of the jpg (Logo.jpg) in the project that is in a folder I created (Images), but it is not working using code like this..
PDFPage.AddHeaderImage("String path of the jpg in the project")
PDFPage.AddHeaderImage("~/Images/Logo.jpg))
There is a "could not find file" exception.
It works fine when I point to a file on my computer like this...
PDFpage.AddHeaderImage("C:/Source Code/Source/images/Logo.jpg");
But, I do not want to point to a file on my computer. I want to point to a the file in the Images folder in my project where I put Logo.jpg. I also put the image in Resources, but do not know what the string would be to access it. Either way would be fine.
the .AddHeaderImage is expecting a string path.
If you set Build Action = Content and Copy To Output Directory = Copy Always on the properties of the image file in Solution Explorer in Visual Studio, then the image file will be output to your bin folder along with the compiled application. You can then use a path relevant to the executable.
PDFPage.AddHeaderImage("Images/Logo.jpg));

Read from output file in installed WCF service

I included a text file as output in a WCF set up project.
The text file is correctly located in the same folder with the dll, exe, and config file after the project is installed (C:\Program Files\KLTesting\KLTestApp).
However when the program tries to read it, it looks under "C:\Windows\system32", what's the correct way to find & read it?
I have
string a = Directory.GetCurrentDirectory();
a += "/R0303.txt";
string content = File.ReadAllText(a);
Thanks.
You should use AppDomain.CurrentDomain.BaseDirectory or AppDomain.CurrentDomain.SetupInformation.ApplicationBase instead, to get the Directory of your .exe file.
First you should not call Directory.GetCurrentDirectory() and concatenate with the file name. The service is running within a web server like IIS or some other type of container, so GetCurrentDirectory will not give you what you are thinking as you found out. (On a quick tangent, as a recommendation in the future if you want to do path combining you should use Path.Combine method as it will handle all the corner cases and be cross platform.)
There are a few ways to do this:
Assembly myAssembly = Assembly.GetAssembly(SomeTypeInAssm.GetType());
string fullFileName = Path.Combine(myAssembly.Location, "MyFile.txt");
The fullFileName should be what you are looking for. Make sure you use a type that is actually in an assembly located and referenced from the directory in question. However be aware because this file in your question in the Program Files area this is a secure area on Vista and higher OS's and you may not have access to do anything but read the file.
Also you could have the installer of the application place in the registry the install path. Then your service if on the same box can pull this information.
Also you could make sure the file you want to load is within the web server environment that is accessable to the WCF service in question.

Categories

Resources