Is there a consistent way for a .net core webapp & console app to determine path to datafiles folder? - asp.net-core

I have two apps that share a data files folder. One is an asp.net core web app. The other is a .net core console app. Folder structure is:
WebApp
WorkflowApp
Datafiles
If I use any of these in the console app:
string en = Environment.CurrentDirectory;
string dr = Directory.GetCurrentDirectory();
string ad = AppDomain.CurrentDomain.BaseDirectory;
string sa = System.AppContext.BaseDirectory;
they all point to: workflow\bin\Debug\netcoreapp2.0
If I use them in the webapp, then en & dr point to "webapp" and the others point to "webapp\bin\Debug\netcoreapp2.0
I'm using appsettings.json to set the path to Datafiles. This file is shared by WebApp and WorkflowApp. I was setting it to "../Datafiles" and then getting the full path using:
Path.Combine(Directory.GetCurrentDirectory(), datafiles);
But this only works in WebApp. I would like to find a common method that works for both. And I don't want to set an absolute path in appsettings.json.
I could use AppDomain.CurrentDomain.BaseDirectory and then use:
#"..\..\..\..\Datafiles"
to move back from a "bin\Debug\netcoreapp2.0" folder. But this seems a bit convoluted. Is there a better way?
EDIT: An answer to this question might solve my problem (at least when in development): How can I get the path to the project folder (where the .csproj file is located) from in the code?

Try this way.
var requiredPath = "";
var address = "DataFiles";
var rootDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
if (rootDir != null)
{
requiredPath = Path.Combine(rootDir, address);
}

I would not let the application figure out the directory / path of where the data files are but rather externalize the paths into a config such as in appSettings.json or something similar.
If you then want to take it a step further and have the apps share the same config you can use a cetnralized store such as Consul or Etcd
https://github.com/etcd-io/etcd
https://www.consul.io/api/kv.html

Related

ConnectionString in .NET Core 6

I'm playing around in .NET Core 6 Web API's. But I can't seem to figure out how the connection string works now.
The first part here that is commented out works fine. But I need to be able to throw the program on different systems and change the connection string with appsettings.json.
The second part is what I attempted but that doesn't work.
Config connection string in .net core 6 is where I got it from.
//builder.Services.AddDbContext<TodoContext>(opt =>
// opt.UseSqlServer(#"Data Source=JOHANDRE\\SQL2017; Database=ToDoItems; User=xxx; Password=xxx;"));
builder.Services.AddDbContext<TodoContext>(opt =>
opt.UseSqlServer(builder.Configuration.GetConnectionString("ToDoItemsDatabase")));
My appsettings.json:
"ConnectionStrings": {
"ToDoItemsDatabase": "Server=JOHANDRE\\SQL2017; Database=ToDoItems; User=xxx; Password=xxx;"
},
I want to add that it does not throw errors. it just does not seem to find the connection.
Problem is how you start your Web API from the service. You are using Process without setting ProcessStartInfo.WorkingDirectory to the folder containing exe and configuration and the started process shares the working directory with parent one, so either move appsettings.json to the parent project folder or set the WorkingDirectory to match the directory containing the exe:
toDoTest.StartInfo.UseShellExecute = false;
toDoTest.StartInfo.WorkingDirectory = "C:\\Develop\\ToDoMVCtutorial\\bin\\Release\\net6.0\\publish\\";
Also you can try redirecting your Web API output to capture the logs.

How to get Physical Path for virtual path in .NET 6 RC1?

The question is related to Blazor wasm hosted App.
I am resolving _webHostingEnvironment in constructor of the controller.
_webHostingEnvironment = serviceProvider.GetRequiredService<IWebHostEnvironment>();
I am running into issue where I don't get correct value for the virtual director's physical path.
My app generates a QR code which I need to store in the images folder of virtual directory.
var webRootPath = "";
if (string.IsNullOrWhiteSpace(_webHostingEnvironment.WebRootPath))
webRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
else
webRootPath = _webHostingEnvironment.WebRootPath
Firstly _webHostingEnvironment.WebRootPath is always null, hence the code always gets the path from Directory.GetCurrentDirectory().
Directory.GetCurrentDirectory provides the path of Server, but not the actual deployed path of wwwroot which is further down like /bin/debug/net6.0/wwwroot.
Here is the screenshot of the code in question
Now I could append that static path to get full path, but no sure what to use when I deploy it on Azure App Service or while using other deployment models

Rotativa file not found on server only

I am using Rotativa ActionasPDF() to generate a pdf from a view in my MVC4 project. It works flawlessly on my local instance, but I just copied the entire solution to my server and it does not work. I get the error "The system cannot find the file specified", but I'm not sure what file it is talking about. I assume it is talking about the Rotativa dll, but I've got the generated Rotativa folder on my server as well. The solution is an exact duplicate as my local copy. My site is hosted on IIS 8, windows 2012 server. Research has told me I could have a permissions issue with some folder, but I'm not sure which ones they would be. I just set all my controller & views to 777 permissions for the time being. No luck. Any ideas to what I'm missing, or how I can make sure the dll is registered on my server?
Here is my controller action method:
public ActionResult DownloadFile(int id = 0)
{
var filename = string.Format("Invoice{0}.pdf", id);
return new ActionAsPdf("Invoice" + "/" + id, new { name = "Invoice" + id }) { FileName = filename, PageSize = Size.Letter, PageOrientation = Orientation.Portrait, PageMargins = new Margins(0, 0, 0, 0) };
}
Check if you add all files in rotativa directory on server-
libeay32.dll
wkhtmltopdf.exe
etc.
Old thread but I had the same issue so I wanted to share the solution for people searching in the future.
Ensure you have the correct VS Redistributable installed on the server, or files in the Rotativa folder.
Use the server IP address instead of the DNS name. I do not know why this works but will edit this if I figure it out.
You need to have Visual C++ Redistributable Packages on the server. You can download the packages from here: http://www.microsoft.com/en-gb/download/details.aspx?id=40784
You need update Rotativa, Rotativa.Core, Rotativa.MVC in Nuget

IIS Hosted WCF accessing file

In development environment
string AppPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string path = AppPath + "\\options.xml";
Works.
When Hosted by production IIS7 server I put Options.xml in the bin environment but the path produced by the above code is a asp.net temp directory.
So what is the correct technique to access the file in both development and production environment?
thanks
Is this information you are using to support your service?
If so, is there any reason you couldn't just make a custom config class and read it as a section from your web.config?
You can use this:
string path = System.IO.Directory.GetCurrentDirectory();

Zero dependency from the client configuration files for WCF services

Our aim is to have Zero dependency from the client configuration files for WCF services.
we are using ConfigurationChannelFactory() to create the channel and specify the ConfigSettings.
ConfigSettings is loaded using the following code
ConfigurationManager.OpenExeConfiguration(ConfigFilePath);
So we have to provide the ConfigFilePath here.
we have both windows and web clients.
we have used below approaches to find out the path
AppDomain.CurrentDomain.BaseDirectory + "bin\\" + executingAssembly.GetName().Name + ".dll"
Web client : AppDomain.CurrentDomain.BaseDirectory gives root folder of the
web applicaton so its works fine
Windows client : AppDomain.CurrentDomain.BaseDirectory gives path upto Debug/Release folder
so, its throws error
Assembly.GetExecutingAssembly().Location
Web client : Assembly.GetExecutingAssembly().Location gives path to the ASP.Net temp.
files , where we dont have the config files. So its throws an error.
Windows client : Assembly.GetExecutingAssembly().Location gives the correct location,
so its works fine.
In order to make it works in web clients, we have to add the following key in client's web.config files.
<hostingenvironment shadowcopybinassemblies="false">
but it adds a dependency to the clients.
Can you guys please help me to find the path without worrying about the clients?
have you tried this? I used GetCallAssembly() instead of GetExecutingAssembly() as this lives in a utility class in our project.
public static string AssemblyDirectory
{
get{
string codeBase = assembly.GetCallingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
Could you just probe both paths? In other words, check the Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin") folder and if you can't find the config file in there, check the Assembly.GetExecutingAssembly().Location folder instead? Since you indicate that the first approach works for web but not Windows clients, while the second approach works for Windows clients but not web, go with both!