Zero dependency from the client configuration files for WCF services - wcf

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!

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.

using a wcf service with a custom config path

I am struggling with calling a WCF service inside an assembly library with a custom config file. The WCF service runs within a Citrix Xen Server environment which is probably the cause of the problem.
I have setup a console application that references the assembly library and calls a public method inside that library that connects to the WCF Service endpoint and display the data derived from a call of a WCF function inside a Win Forms Datagrid.
Right now I am setting the config path for the current app domain inside the constructor of the Win Forms class 'E2ADokumente' that is displayed by the assembly library:
var assembly = Assembly.GetAssembly(typeof(E2ADokumente));
var assemblyFilePath = assembly.Location;
var assemblyDirectory = Path.GetDirectoryName(assemblyFilePath);
var dllName = assembly.GetName().Name + ".dll.config";
string configPath = Path.Combine(assemblyDirectory, dllName);
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", configPath);
The WCF proxy is build like so:
WSTrustChannelFactory channelFactory = new WSTrustChannelFactory("STSEndpunkt")
"STSEndpunkt" is the name of the endpoint and is defined in the config file.
All works if I run the code locally but the config file won't be located if I run the same app within the Terminal Services environment. The error messages states that "STSEndpunkt" cannot be found.
It works inside the Terminal Services environment though if I run the assembly library inside a new app domain. But having a separate layer and calling method through reflection is a little too much overhead so I am searching for a simpler solution.
How can I set the path for a config file with the WCF configuration details inside an Assembly library that runs within Terminal Services?
Building the WCF channel setup in code is not an option.
I found a solution after a lot of google-fu.
The setting of the config path for the assembly library works if its done inside the static constructor of the class.
static E2ADokumente()
{
var assembly = Assembly.GetAssembly(typeof(E2ADokumente));
var assemblyFilePath = assembly.Location;
var assemblyDirectory = Path.GetDirectoryName(assemblyFilePath);
var dllName = assembly.GetName().Name + ".dll.config";
string configPath = Path.Combine(assemblyDirectory, dllName);
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", configPath);
}
After that the config file for the WCF service was loaded by the assembly library.
I have no idea what differences the fact that the application is running within Terminal Services contributes but at least this is a simple fix.

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

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

DeploymentCatalog security error

I'm trying to use the DeploymentCatalog to load my service implementations by MEF. I have the implementation in a single xap. when I use the following code to download it , every thing is ok :
var catalog = new DeploymentCatalog("MyXap.xap");
catalog.DownloadAsync();
I put my xap on a remote server , say on http://ip:90/Myxap.xap, when I write the same code but with the uri , it throws a deployment exception:
var catalog = new DeploymentCatalog(new Uri("http://ip:90/MyXap.xap",UriKind.Absolute));catalog.DownloadAsync();
Any help .
Thanks in advance ...
If the XAP you are trying to download is hosted at a different domain (or different port, I think) than your Silverlight App is, you will need a cross domain policy file on the site that hosts your XAP to allow your Silverlight App to access it.
If that's not the problem, you'll need to provide more information. Edit your question to include the full text of the deployment exception you get.