IIS Hosted WCF accessing file - wcf

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();

Related

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

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

Can AzureReader2 read Azure storage configuration settings from the service config rather than the web.config?

Is there any way for the AzureReader2 plugin to read its connection string and endpoint config values from the service config file rather than just the web.config?
The problem is that we build Azure package files (.cspkg) and web.config files are embedded within the package. Therefore we strive to keep our web.config files constant across all different deployments (test, dev, and production). We normally deploy using a package file and a service config file.
Install AzureReader 2 via code during application startup instead, and you can pass it the connection string directly:
var nvc = new NameValueCollection();
nvc["endpoint"] = "http://127.0.0.1:10000/devstoreaccount1/";
nvc["connectionString"] = "UseDevelopmentStorage=true";
new AzureReader2Plugin(nvc).Install(Config.Current);

Programmatically configure and host WCF Service in IIS

How can i programmatically configure and host WCF Service in IIS. I have created my WCF service example /WCFServices/Service1.svc". I want to programmatically configure and host this service in IIS. Can anyone help me on this?
The class you want is Microsoft.Web.Administration.ServerManager
http://msdn.microsoft.com/en-us/library/microsoft.web.administration.servermanager(v=VS.90).aspx
It has methods for manipulating most aspects of IIS, for example, adding application pools and applications. for example, this code configures a new IIS application
//the name of the IIS AppPool you want to use for the application - could be DefaultAppPool
string appPoolName = "MyAppPool";
//the name of the application (as it will appear in IIS manager)
string name = "MyWCFService";
//the physcial path of your application
string physicalPath = "C:\\wwwroot\mywcfservice";
using (ServerManager serverManager = new ServerManager())
{
Configuration config = serverManager.GetApplicationHostConfiguration();
ConfigurationSection sitesSection = config.GetSection("system.applicationHost/sites");
ConfigurationElementCollection sitesCollection = sitesSection.GetCollection();
ConfigurationElement siteElement = sitesCollection[0];
ConfigurationElementCollection siteCollection = siteElement.GetCollection();
ConfigurationElement applicationElement = siteCollection.CreateElement("application");
applicationElement["path"] = name;
applicationElement["applicationPool"] = appPoolName;
ConfigurationElementCollection applicationCollection = applicationElement.GetCollection();
ConfigurationElement virtualDirectoryElement = applicationCollection.CreateElement("virtualDirectory");
virtualDirectoryElement["path"] = #"/";
virtualDirectoryElement["physicalPath"] = physicalPath;
applicationCollection.Add(virtualDirectoryElement);
siteCollection.Add(applicationElement);
serverManager.CommitChanges();
}
In general, the calss is just a thin wrapper around the IIS config file. You can understand it by looking at your exisiting file, or even by looking at what you have to do in IIS Manager to configure the service manually, then translating that into the resulting configuration changes.
You can do all (at least lots of) the the IIS configuration in this way (e.g. configure application throttling, enable authentication schemes etc.).
The WCF part of the configuration is just normal WCF. you can do it either in code or in configuration.
What you are looking for is called Publish. You can find it from the right-click context menu on the WCF Service project. You can publish from there or create a package for publishing later or distributing it to a remote site. There are a lot of tutorials on the net.
If you have a specific question about this feature, feel free to ask.
Have a look at msdeploy, a command line packaging and deployment tool:
http://blogs.iis.net/msdeploy/
http://vishaljoshi.blogspot.de/2009/02/web-deployment-with-vs-2010-and-iis.html
http://msdn.microsoft.com/en-us/vs2010trainingcourse_webdevelopment_topic8#_Toc282089433

Get folder on server from WCF

On the first code, on the localhost I get the Bin folder - which I expect. On the server I get an error. These are all the methods I have tried.
AppDomain.CurrentDomain.BaseDirectory
Hosting.HostingEnvironment.ApplicationPhysicalPath
System.Web.HttpContext.Current.Server.MapPath("~") 'for the root
Can anyone enlighten me on how I can get the root directory on the server from WCF service?
Error:
According to the accepted answer in this question you should use
string path = HostingEnvironment.MapPath("~");
add [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
to class and try

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!