Connecting a Test project to a WCF Service Automatically - c#

I have written a WCF web service (not a web site, just JSON over HTTP) intended to run in Azure. I need to write tests for it.
I know how to do this, but it seems amateurish:
Run the web service,
Copy the root URL (e.g. http://localhost:81/)
Apply the root URL to my test project,
Run the test project.
I would like to be able to do this:
Hit F5
--> web service starts running
--> tests start running, automatically finding where IIS decided to run the service.
Is there a way?

There are 2 ways you can do this. Since you're using Windows Azure I assume you're using the emulator. Using the emulator means that the RoleEnvironment is available and you can get a list of roles, their instances, and their endpoints that are available.
var endpoint = RoleEnvironment.Roles["WebRole1"].Instances.First().InstanceEndpoints["Endpoint1"];
var siteUrl = String.Format("{0}://{1}", endpoint.Protocol, endpoint.IPEndpoint);
This code will get the role named WebRole1, get the first instance on this role (you could use this to test if your web service supports load balancing) and get the InstanceEndpoint. The instance endpoint will give you all info you need like protocol (http/https) and the IP/port (these are things you configure in the ServiceConfiguration).
Note: This also works for processes running outside the emulator (like your test project). The only thing you'll need to do is reference Microsoft.WindowsAzure.ServiceRuntime.
Besides that you can also try to use the ServerManager class to find the current sites running in IIS, but I don't think this will work if you're running in IIS Express (which is also possible if you're working with Azure).

Fix the port number of the WCF project: go to the properties of your project, set "use dynamic ports" to false then specify a fixed number, for example 81.
Specify multiple startup projects in your solution: right mouse button on solution: select "set startup projects", then check the radiobutton "multiple startup projects", include your WCF service project in the startup list.
I hope this meets your needs...

Related

Connection to a basic WebAPI fails

I am trying to test the possibility to convert all my WCF service to WebAPI but so far it's a mess. WCF is easy because you create a default project and add 1 or 2 sample method that return anything then add as a service by using the http address and it works out of the box.
On WebAPI you add connected service and type the address and it throw errors so obviously out of the box it has errors and is missing stuff to actually work.
My question is what is missing to WebAPI made with .NET6 to be able to be connected to ?
Following Microsoft example what i should do is to run the service obviously. Then use the path of the json file generated by swagger and input that in the URL of the connected services, give it a namespace and a classname and your good to go.
Step 1 : Running the service
This works i can call the basic 3 method i made for test purpose that return string, List<string> and List<List<string>> and i can execute the "tryout" button and they output everything that it needs
Step 2 : Copy the json file path provided by Swagger
I assumed that this url is good by default. I can click it and i see the definition which seems good.
Step 3 : Create and empty console app and add the connected service
When adding the connected service i pick OpenAPI as it's the only option anyway.
Then it asks for File or URL that i put my value form the service that is running. In this case this is : https://localhost:44341/swagger/v1/swagger.json. I then choose the namespace of WebTest1 and classname of WebTest2 as i dont care and click next
Step 4 : Configuration progress
This is where i have the error which is where i see that the service that can actually run cannot be connected to
Checking project for required NuGet packges... Downloading service
reference from https://localhost:44341/... ErrorFailed adding service
reference(s). Failed to download metadata file from :
https://localhost:44341/.
I finally figured out the temporary fix. I was also able to copy this project over to a colleague and the issue is the same. The problem lies into Visual Studio defaulting for some reason on the debug option of IIS Express which does properly run the service when you press F5 and your browser open normally and you can test things out. The problem is that when you project runs under IIS (actually configured like it would be the real deal) or IIS Express (the only IIS option in the debug setting) you cannot from another application connect to that service.
However if you switch the debug option to the project name and run your WebApi with that instead it also works as expected from the browser that it open but you now can actually add that service from another application without any error.
Personally i have a third option which is WSL which i "guess" is the linux sub system i can't tell as this crash when i try to start and there is no help for the UI of Visual Studio to help understand these menu options.
Now i still have a problem to attach to one running in a real IIS which is probably linked to the same reason why IIS Express debug doesn't work. So i now know that the base code works and now it's an issue of finding why the default doesn't let other application consume from IIS / IIS Express.
For reference purpose this is the debug menu in question where the IIS Express option is not working but selecting the project name like pointed out on the picture actually works.

Deploy a callback API to a VM with IIS

I am hoping to deploy a web api to handle callbacks from a 3rd party.
I'm a beginner at C#, but I've written a simple Web API using Visual Studio in order to handle the callbacks.
To test on my dev machine I click the green run button with IIS selected on localhost, and the dll is created. I can feed it some 3rd party test JSON files (using Postman) and the database is updating correctly. So far so good.
Now I'm looking at deployment to a test server, which can receive live (test) callbacks. To do this, I've run up a new VM with a public IP address, installed SQL Express and also installed IIS.
I am assuming the next step is to publish (web deploy) from VS.
But I'm becoming confused with regard to domain name, URL and IP address.
a) Do I need to register a domain name for the IP address? (There is no UI, just the callback endpoint)
b) When setting up the publishing profile for web deploy, what is the Destination URL?
There is a lot of information available on the subject, but there are clearly a few important gaps in my knowledge, and I can't seem to fill 'em.
Thanks
If I am understanding your question correctly - no you do not need a domain name to test your application. You can use a tool like Swagger to test your API. Read more here: https://www.blazemeter.com/blog/getting-started-with-swagger-ui
Good luck!

Weird Service Behavior

To give you some background, I've been trying to modify our local hosting arrangement so that an existing WCF service is hosted in IIS locally, dispensing of the current host console application.
I created a new WCF project which contains nothing more than a svc and web.config.
The svc references a servcie factory in the service assembly and the web.config is at the low end of complexity. This mimics how the service is deployed in our dev/test/uat/pre-prod environment.
The service has a service behavior that sets the certificate validator during the call to AddBindingParameters - this has worked for longer than I have been working at the company.
The problem is locally, AddBindingParameters gets called numerous times, but ultimately with the channel state set to "opened" and the service credentials object set to readonly, mushroom clouding.
I thought it may be environmental but I've scoured IIS looking for the "set to evil" flag, no luck. I tried deploying the service (file copy) to a known good server - no good, same issue. Environmental, I say. So I tried copy a known good service locally (file copy) - no good. OK, WTF. Checked the installer (the service is installed with a WiX installer) - it does create the virtual directory but nothing stands out.
I know I could move the authorisation logic into an authorisation policy but I'm reluctant to change something that has worked for so long without understanding the underlying issue.
At this point I'm ready to give up unless I get some good ideas!

Best Practice for storing settings for a .NET Windows Service: Service Property Settings, Serialization,

I am working on a .NET Windows Service where I am trying to store settings that will be used when the service is started and while it is running. I have searched through posts on SO and found that using the Settings in the properties of the project is great for use with console and winforms applications. However, Google and SO are silent when it pertains to storing these settings with a windows service.
Does anyone one know if it is proper to use these settings in a .NET service? If not, is Serialization my next best choice? Has anyone had practical uses for settings in a service and found that it is best to use a specific method?
I've had problems with using Settings.settings. For instance, if you need to make changes at run-time, there can be problems with the settings being overridden by those that were initially stored in the settings.settings file as opposed to what's shown should be stored per the app/web.config. Consequently I make all my Web Service proxy settings "static" in the properties and pull them manually from the app/web.config via a helper method and programmatically set them. This circumvents any problems.
An example of the issue we had: I pointed my development machine to a web service on a test server to test the code that consumed the web service. When the code was moved to our test server, no problems manifested - as the test server was still pointed at the same web service on the same test server. However, when we moved the application to the production server and reconfigured the web.config to point at the production server we started getting screwy results. It took quite a bit of effort to pinpoint that even though we had reconfigured the application to point at the production server's implementation of the web service, it was still connecting to the web service on the test server. It wasn't until we changed settings.settings on my development machine and recompiled the application that it worked. Further to this, we also noted that if there were DNS problems connecting to the production web service, rather than fail, it fell back to the original settings that were specified in the settings.settings from when we created the web service proxy in our application - the proxy generator actually hard codes them. Consequently when there were network outages, instead of getting easily diagnosed connection failures, it simply fell back to the test server and we started getting incomprehensible data issues. I'm not sure if this was a known problem or if it's been fixed, but it's certainly something you should be aware of.
Consequently, since then, I've always set the service properties to static and used a helper method to read the correct settings from the web.config directly and written them programmatically as this seems to circumvent the problem.
It may seem like the problem I had has nothing to do with yours because I was using Web Services which isn't anything to do with Windows Services, however, any environment where you need to be able to change the settings at runtime without having to recompile could be affected by this issue, so you should be aware that if you run in a Dev/Test/Production environment or indeed any environment where you need your app to be reconfigured at run-time (i.e. without having to recompile) that you can get unpredictable results when using settings.settings. Beware.
I normally use the registry to store information I need in my service i.e port etc.
string lsbkey = #"Software\mycompany\adas";
RegistryKey adaskey = Registry.LocalMachine.OpenSubKey(lsbkey, false);
try
{
object regip = adaskey.GetValue("IP");
object regport = adaskey.GetValue("PORT");
localip = regip.ToString();
localport = int.Parse(regport.ToString());
}
catch (NullReferenceException ne)
{
localip = null;
localport = 0;
writelog(#"Aborting Service, IP or PORT doesn't exist in \local machine\software\mycompany\adas : "+ne.Message);
status = 0;
}
I use the Settings.settings stuff for storing the config for my services and I've had no problems. Just the usual that the user settings that are changed will be stored in it's usual obscure location that you have to hunt around for if you want to edit them by hand.
I dont see any reason not to use Settings in the properties of the project as you would for a winForms app. We do this, and it works fine.

Passing a Windows Service Parameters for it to act on

I want to turn a program I have into a service so I can use it without logging it. Basically what it does is it backs up specified folders to a specified location using SSH. However the problem I'm running into is I don't know how to tell it these items. I only know how to start, stop, and run a custom command with only an integer with a parameter.
How can I do this?
Windows Service, not a Web Service
edit: The folders it backs up will not remain consistent and will be updated at every runtime
You can instantiate your service and pass command line arguments using the ServiceController class.
using (ServiceController serviceController = new ServiceController(serviceName))
{
string[] args = new string[1];
args[0] = "arg1";
serviceController.Start(args);
}
"arg1" will then be available as regular command line arguments in main() when Windows starts up the service.
I see that you (or someone) voted Sebastian Sedlak's answer down, because he mentioned hosting a WCF Service in the Windows Service. Your reply was
It's in nice bold lettering in the question. Not a Web Service, therefor WCF is out of the question
I think you misunderstood what he meant. He wasn't talking about a Web Service. He was talking about hosting a WCF Service within your Windows Service.
It's far from the same thing. You can host a WCF Service within any Windows (Forms/Console/Service) application. The point of doing so, is that the application is then reachable for communciation via its internal WCF Service, in the same fashion as you can communicate with a Web Service (you can also host WCF Services in IIS, btw, which would then make them "Web Services", in the sense you seem to be referring to).
In a Windows Service, this means you can send any command to it and also get any information you want from it - while it's running.
In fact, I am working on a project right now, which is a Windows Service that I need to be able to contact and pass commands to - and get information from - at runtime. For example, I want to be able to tell it where to store certain things, what to log, to have it reset/restart - and poll it for status messages. I do this by hosting a WCF Service inside the Windows Service. That WCF Service exposes a set of methods, that in my case includes receiving commands and returning status information. So when the Windows Service is running, I can contact it (even remotely), via its built-in WCF Service and tell it what to do.
This an extremely easy thing to implement, and in the case of Windows Services, can provide you with a much richer interface to the Service than through the basic standard commands.
However, you specified that you wanted your Windows Service to receive its folder settoings each time it starts up, which makes such a passive setup less than ideal (as it would be unable to do anything until you passed it the right folders).
One way to deal with this (using a hosted WCF Service), would be to have the Windows Service running all the time (i.e. automatic startup). Its default state would be idle. Then you could issue it a "start processing"-command, feeding it the correct folders to work on (through a call to the corresponding WCF Service method). Similarly, the WCF Service would expose methods giving you the status of the application (current folder, progress, busy/idle etc). Once the processing is done, it would go back into the idle state, waiting for the next set of folders to be supplied to it.
Doing it this way would make it very easy to control remotely - you could even make an online administration panel for it, accessible from anywhere.
The issue, is that, while passing in parameters is not difficult, when the machine restarts and windows tries to restart the service, those parameters are not there. they only exist when someone starts the service from the command line.
for example. I have a windows service which hosts a WCF service. I want the users to be able to specify a non-default port number for the WCF service to listen on. They do this by starting the windows service like so... MyService -port:xxxxx
Which works fine, until the server is rebooted, then windows restarts MyService (but without parameters) and the wcf service defaults to original port #
Any service is capable of receiving command line arguments at start-up.
Would it be possible to use a configuration file to specify these items?
Store the service's startup parameters in the registry: and then, when the registry starts, it should read its startup parameters from the registry.
Windows services have executables like any other. I believe you can write it to accept command-line parameters and specify those parameters in the Windows Service configuration. You can also have it read a config file. If you're using .NET, there are config file classes in the framework.
Why not just Host a WCF Service in the Windows Service to obatain such "admin" functions?
(Remoting is also possible)
RE: config file.
Of course a config file can be used.
And the file can be changed while the service is running.
This would be a nice solution if the config file changes in fact.
All my services use an XML config file, wrapped in a class for easy reuse.
The wrapper has an option to monitor the XML file using fileMonitor for changes, optionally refreshing the content of the config file automatically, and finally raises an event to the service class.
The service then has the option of "resetting" itself as needed to incorporate the new values in the XML configuration file.
Placing configuration into the registry has a few issues:
Security (ie: installer being granted access), depending on what tree is used
The service will not be aware of changes
Portability - although minor as the install should setup registry settings
Where an XML file is easy to copy, edit, share, view and understand.
Throw in some good COMMENT blocks and a detailed XSD file, and it becomes a source of good documentation too.
Look into XPath for easy navigation and extraction of values within the XML file.
$0.02
... david ...
Concerning the app.config file - I'm rather sure that your service will read and use those files as I write all my windows-services this way ;)
So just put everything you need in the app.config under "application" (not user) and put allway edit the "yourname.exe.config" in the folder where you "InstallUtil" the service from.

Categories