WCF endpoints information in the config file for different environments - web-services

i wanted to know what is the best approach to save WCF endpoints information in the config file for different environments(DEV,TEST,PRE-PROD, PROD).
i am familiar with 1 way of doing this - 1. Maintain different config files(for each env) and deploy them accordingly.
Can someone please suggest the best way to do this ??

You can configure the endpoint at runtime with endpointbehaviors. In this behaviors you can get the machinename for example. Depending on the machinename you could set yout endpointaddress for your endpoint, and then start the service.
Here is a link : https://msdn.microsoft.com/en-us/library/vstudio/ms730137%28v=vs.100%29.aspx
EDIT:
So you write:
class CustomEndpointBehavior : IEndpointBehavior{
public void Validate(ServiceEndpoint endpoint)
{
// get here the address and rewrite it dependig on the machinemane e.g.
// remember to set the new address to the endpoint!
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
}
And in the class where you start the service, you need to set the CustomEndpointBehavior to the serviceHost, like:
serviceHost.Description.Behaviors.Add(new CustomEndpointBehavior());

I think this is the link. Create multiple configuration and then use pre build event to copy it. http://www.hanselman.com/blog/ManagingMultipleConfigurationFileEnvironmentsWithPreBuildEvents.aspx
In you have visual studio 2010 and above then it will be able to merge the config. https://msdn.microsoft.com/en-us/library/dd465326(v=vs.110).aspx

Related

Set a Pub Sub topic in Micronaut as per environment

I am following this guide to initialise a GCP Pub/Sub publisher.
The coding syntax is as follows:
#PubSubClient
public interface PubSubService {
#Topic("topic-a")
void send(final A a);
#Topic("topic-b")
void send(final B b);
}
I want to set this topic value based on the environment, as I will have a different topic for QA/DEV (say topic-a-qa and topic-b-qa).
Is there any way for me to set this String value in the #Topic annotation via or based on environment properties?
I do not have an option of have a different Project under the GCP account, also creating a different class for QA overriding this one is not so graceful when maintaining environments.
You can use placeholders inside Micronaut's annotations.
#PubSubClient
public interface PubSubService {
#Topic("${topic.a.name:topic-a}")
void send(final A a);
#Topic("${topic.b.name:topic-b}")
void send(final B b);
}
The expression ${topic.a.name:topic-a} instructs Micronaut to search for the value in the configuration under the topic.a.name key, and fall back to the value topic-a if the configuration key is not found. Then you can configure different topic names using e.g. application-qa.yml configuration file:
src/main/resources/application-qa.yml
topic:
a:
name: topic-a-qa
b:
name: topic-b-qa
Lastly, just make sure that when you run the application in the QA environment you set a proper active environment, e.g.
$ java -Dmicronaut.environments=qa -jar myapp.jar

Using a HTTP Module on a Virtual Directory in IIS

I have a default website in my IIS where I have created one virtual directory "wsdls".
I would want to gather statistics on how many requests are triggered to my virtual directory. This would need a request interception at web server level and gather statistics. "HTTPModule" was one of the many solutions I have considered which is suitable for such scenario. Hence I have started building one.
For testing purpose, I wanted to create a HTTP Module and apply it on a particular extension files (say *.wsdl) and on every GET request of any .wsdl files in this virtual directory, I will want to redirect the application to "www.google.com". This would demonstrate a good example of how HTTP Module can be used and deployed on IIS.
HTTPModule which is written using Visual Studio is shown below,
namespace Handler.App_Code
{
public class HelloWorldModule : IHttpModule
{
public HelloWorldModule(){
}
public String ModuleName{
get { return "HelloWorldModule"; }
}
// In the Init function, register for HttpApplication
// events by adding your handlers.
public void Init(HttpApplication application){
application.BeginRequest +=
(new EventHandler(this.Application_BeginRequest));
application.EndRequest +=
(new EventHandler(this.Application_EndRequest));
}
private void Application_BeginRequest(Object source,
EventArgs e)
{
// Create HttpApplication and HttpContext objects to access
// request and response properties.
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Redirect("www.google.com");
}
private void Application_EndRequest(Object source, EventArgs e)
{
//Nothing to be done here
}
public void Dispose() { }
}
}
Now I have done a build of this project for x64 version and I am able to browser successfully the "dll" file. Now I have to register this dll in IIS and whenever I try to access the *.wsdl files, the requests automatically divert to "www.google.com". Here is the next step I have done,
Then I have enabled the Handler mappings as shown below,
I am assuming that is it!! Nothing more to be done. I should be able to intercept the requests for all HTTP requests which are of the form "*.wsdl". This means whenever I access any wsdl from the server, control should be going back to google(Because of the logic written in begin request ). But unfortunately, I failed in achieving it. What can be done here?
One thing I noticed is that when you are trying to redirect to an external URL use
http://
So change
context.Response.Redirect("www.google.com");
to
context.Response.Redirect("http://www.google.com", true);
I could solve the problem what I am facing and below are the observations which were missing in my understanding and which helped me in solving my problem:
Locating proper web.config file :
Every website in IIS will be having a web.config file to have control over the application.
Since I am working with "Default Website", this refers to the directory "C:\\inetpub\\wwwroot"
There will be a "web.config" file which would be present in this director. Please create it if not already present.
Modifying web.config :
Once you have identified the file which needs to be modified, just add necessary module configuration to web.config
In this case, we would want to add a Module to the default website, the probably setting would be shown below,
Adding contents to bin directory :
Now if you try to run the application, the IIS would not find any dll or executable to run and hence we would need to keep the executables at a particular location.
Create a director if not already present with the name "bin" at the root of the directory and place all the dlls which you would want this website to execute. Sample shown below,
General Points to be considered:
Proper access must be given for the folder which consists of dll.
It is ideally not suggested to modify the entire website. It would be ideal if one works only on their web application.
If web.config is not found, we can create one.
If bin is not present in the web root directory, we can create one.

Persisting data in an axis object

Forgive me if this is a dumb question, I unfortunately have an assignment due! I am running apache axis under tomcat and need to deploy a simple web service class, see below.
I installed the counter file below as "MyCounter.jws" in the /tomcat/webapps/axis/ folder. Tomcat finds it and makes a corresponding MyCounter.xml. I use WSDL2Java on the XML file and client calls seem to work, but internal state is not saved:
Every time I call MyCounter.call from the client side, the return value is always 1. It seems the constructor is always called before the method call. How can I make it so the mycounter integer persists across requests?
public class MyCounter
{
int mycounter;
public MyCounter()
{
mycounter = 0;
}
public int call()
{
mycounter++;
return mycounter;
}
}
I think persisting is maybe the wrong word, I think what you mean is that the Java Class is not instantiated every time you call the service.
See: https://axis.apache.org/axis/java/user-guide.html#Scoped_Services
So you would need to change the Service definition yo achieve this.
I don't think that with the JWS files you will be able to configure the session scope. As the docs say:
https://axis.apache.org/axis/java/user-guide.html#JWS_Java_Web_Service_Files_-_Instant_Deployment
Quote:
Important: JWS web services are intended for simple web services. You
cannot use packages in the pages, and as the code is compiled at run
time you can not find out about errors until after deployment.
Production quality web services should use Java classes with custom
deployment.
So if you want to use such features you should consider using some of the other ways Axis offers to setup a WebService.
Also I would strongly recommend using Axis2 instead of Axis1:
http://axis.apache.org/axis2/java/core/
Axis1 can be quite complicated with the WSDD files to setup. Apart from Axis1 no more actively developed/maintained.

Azure Webjobs - Define QueueName trigger on app.config

With the new release of Azure Webjobs 3.0.0 SDK it was announced the:
http://azure.microsoft.com/blog/2014/06/18/announcing-the-0-3-0-beta-preview-of-microsoft-azure-webjobs-sdk/
Improved function discovery
We added an ITypeLocator and INameResolver to enable customizing how the WebJobs SDK looks >for functions. This enables scenarios such as the following:
You can define functions where the QueueName is not explicit. You can read Queue names from a config source and specify this value at runtime.
Restrict function discovery to a particular class or assembly.
Dynamic functions at indexing time: you can define the function signature at runtime.
But there's no sample code on how to do it.
Does anyone know how to define the queue name at runtime (e.g. from app.config)?
If you take advantage of the new INameResolver in the configuration you can make your own implementation of the interface and replace it in the JobHostConfiguration. Take a look at this blog post where I made a small POC on the topic.
To use an external runtime service to define the name of the queue:
public class QueueNameResolver : INameResolver
{
public string Resolve(string practiceId)
{
//define in appsettings the queuename property
return CloudConfigurationManager.GetSetting("queuname");
//or some other service of your design
}
}
In the WebJob Code, Program.cs:
public void init()
{
// Retrieve storage account from connection string.
string azureJobStorageConnectionString = ConfigurationManager.ConnectionStrings["AzureWebJobsStorage"].ConnectionString;
var config =
new JobHostConfiguration(azureJobStorageConnectionString)
{
NameResolver = new QueueNameResolver()
};
host = new JobHost(config);
host.RunAndBlock();
}
as per azure doco

Web Service in SSIS

I am trying to use a web service as part of a dataflow task in SSIS. Right now i have a script task within a data flow with a web service reference.
What the task has to ultimately do is: collect all postal codes from an inernal database > use the web service i created to get the lay/long of thos postal codes > export the lat/long to a table.
As i said before i have the scrip set up and looks to be working, but when i go to execute the package i get an CannotCreateUserComponentException error.
Any help on this would be awesome, or another approach to it? I am new to the web services in SSIS so this is the best solution i could come up with.
Edit:
Right now the script is accepting the postal code from an OLE DB Source and will ouput a string in for format of "lat,long" (presumably). The web Service was created by someone within the company and has one method called FindCoordinates which takes in a string value (Postal code)(which i think calls the google geocode xml, not exactly sure what he did). Here is the code that is currently in my script:
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using SC_6c1b642acd544cd5b01c032b6f8dfd03.csproj.MyService;
using System.Xml;
using System.Web.Services;
[WebService(Namespace = "http://microsoft.com/webservices/")]
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public override void PreExecute()
{
base.PreExecute();
/*
Add your code here for preprocessing or remove if not needed
*/
}
public override void PostExecute()
{
base.PostExecute();
/*
Add your code here for postprocessing or remove if not needed
You can set read/write variables here, for example:
Variables.MyIntVar = 100
*/
}
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
String postal = Row.PostalCode;
Service service = new Service();
Row.LatLong = service.FindCoordinates(postal);
}
}
Hope this help.