Invoke WCF Workflow Service using different endpoint addresses - wcf

I created a Workflow Foundation workflow which will eventually invoke another Workflow Service. I added the call to this service by dragging the appropriate shape from the toolbox onto the designer. The shape was available because I added the Workflow Service as a service reference as recommended.
How can I specify a specific endpoint address for this web service? I can't find a way to programmatically specify the address.
The workflow always uses the address specified in the web.config. But based on certain conditions I want to use different addresses.
Edit
Here is a picture I created to illustrate the problem:

Look for the place where you make a call to the Workflow Service. Somewhere there you define a client. It should look something like this:
client.InvokeService(); // or whatever method you call;
If you want to change address you should change endpoint address before this call, ideally when you define the client:
client.ChannelFactory.Endpoint.Address = new EndpointAddress("http://something.com/service.wsdl");
But keep in mind that this is not recommended practice. If you intend to change it programmatically it's better to get rid of services section in your web.config completely and set properties programmatically when creating client.

Related

How to reference the WCF service by code-behind in UWP?

Now I need to reference a WCF service in a UWP program. However, the address of the WCF service may change frequently in the future.
I don't want to rebuild/republish the project every time when the address change.
So I want to use a LocalSettings to Save/Load the address of WCF service. Every the program begins, it will reload the address from the LocalSettings. And if the address changes, I just only let the customer change the LocalSettings from UI but not need to rebuild/republish the project.
How can I do it? Or there is any other better to do it?
If it's a RESTful service, you could use HttpClient relevant APIs to consume a REST service in UWP.
Please note that REST is a resource that implements a uniform interface using standard HTTP GET, POST, PUT methods that can be located by URI. So, you could use HttpClient to call it in code-behind. You will get response after you send http request, then you could analysis the response result.
The similar thread for your reference: Calling web service asynchronously in page constructor.
Using LocalSettings for such thing is a good solution.
LocalSettings are just a dictionary where you can assign values you want to store and later take out.
ApplicationData.Current.LocalSettings["ServiceAddress"] = "something";
Debug.WriteLine(ApplicationData.Current.LocalSettings["ServiceAddress"]);
Such setting will survive app restart and is stored in applicaton's private storage.
You will probably want to seed this setting with a default value at first startup.

single WCF endpoint for all commands in Nservicebus

We are trying to build a Nservicebus service that can communicated with form and wpf based clients using WCF. I have read that you can inherit from WcfService.
like:
public class ThirdPartyWebSvc : WcfService<ThirdPartyCmd, ThirdPartyCmdResponse>
And then you simple create a endpoint in the app.config and you done like described here. but the problem is that i have to create a endpoint for every command.
I would like to have a single endpoint that excepts any command and returns its response.
public class ThirdPartyWebSvc : WcfService<ICommand, IMessage>
Can someone point me in the right direction? Using Nservicebus for client communication can't be done for us and i don't want to build a proxy like server unless thats the only way to do it.
Thanks
So from what I can gather, you want to expose a WCF service operation which consumers can call to polymorphically pass one of a number of possible commands to, and then have the service route that command to the correct NServiceBus endpoint which then handles the command.
Firstly, in order to achieve this you should forget about using the NserviceBus.WcfService base class, because to use this you must closely follow the guidance in the article you linked in your post.
Instead, you could:
design your service operation contract to accept polymorphic requests by using the ServiceKnownType attribute on your operation definition, adding all possible command types,
host the service using a regular System.ServiceModel.ServiceHost(), and then configure an NserviceBus.IBus in the startup of your hosted WCF service, and
define your UnicastBusConfig config section in your service config file by adding all the command types along with the recipient queue addresses
However, you now have the following drawbacks:
Because of the requirement to be able to pass in implementations of ICommand into the service, you will need to recompile your operation contract each time you need to add a new command type.
You will need to manage a large quantity of routing information in the config file, and if any of the recipient endpoints change, you will need to change your service config.
If your service has availability problems then no more messages to any of your NSB endpoints.
You will need to write code to handle what to do if you do not receive a response message from the NSB endpoints in a timely manner, and this logic may depend on the type of command sent.
I hope you are beginning to see how centralizing this functionality is not a great idea.
All the above problems would go away if you could get your clients to send commands to the bus in the standard way, but without msmq how can you do that?
Well, for a start you could look at using one of the other supported transports.
If none of these work for you and you have to use WCF hosted services, then you must follow the guidance in the linked article. This guidance is there to steer you in the correct direction - multiple WCF services sounds like a pain, until you try to centralize them into a single service - then the pain gets bigger, not less.

Is it possible, in WCF, to add a global message inspector?

There are a bunch of questions regarding global error handlers and such but none of those address what I need.
Is there any way to add a behavior that will attach to every endpoint or service through .config?
*Specifically what I want to do is add a logger that will capture and log every SOAP request/response. But I would prefer that behavior to be automatically added to every service I have instead of having to manually add it to each.
I looked into behavior extensions and thought that would be the solution but no, you have to add the behavior to every service.*
You may be able to use the <commonBehaviors> section of your machine.config file to define a behavior which would be applied to all services in your machine. Notice that updating the machine.config is really like using a bazooka to solve your problem (and in many scenarios the group policy may forbid you from doing that), so it may not work for all scenarios. You'll also need to make sure that the behavior extension is registered (also in machine.config), and that whatever application you're using with WCF has access to the assembly referenced in the extension (possibly via GAC).
Another alternative would be to use a common library for creating the service hosts (either directly for self-hosted services or via a service host factory for webhosted services), and use that library (which would in turn add the inspector).
Its always good to have a message inspector to get rid of this kind of problem. Message Inspector is an implementation of WCF extension which works nicely to track every incoming request(s) and outgoing response(s) for your service, even if its fails in Message Validation it has an option to trap and work accordingly. More precisely the message inspector can configure using configuration files without making changes in your existing service.
More details about your Message inspector and its implementation can be found Here
Hope this helps !!
Happy Coding :)

How can I add a header/datamember to all DataContracts in a WCF service?

I am looking to extend existing services and add Authorization to every call being made. The problem I have is that I don't know how to do this in the best possible manner. What I need to do is to send the name of the module calling the WCF service. I already send the username and password for the service and now I need to extend that with the name of the module calling the service. This is because we might allow a user to open a module and display data from another module but not from a third.
If we would have used message contracts I would just add a MessageHeader for this and set that header when I create the request. That is unfortunately not an option with DataContracts so I was considering the following two alternatives.
Adding a DataMember in a base class with Order=1000 or something like that. I don't know what will happen if we add another DataMember before that though?
Create the property for the module name and set a header in the transport instead. Not really fond of this one though. It's pretty abstract and hard to follow.
Which one is the least evil or do you have a better suggestion?
EDIT 1: The problem is not how to send a header to the service the problem is how to send a header with a specific value to the server. In the message inspector I can only create generic instances with message.GetBody<DataContract>(); this means I have to know the type which I don't know how to.
EDIT 2: The issue here is that in our application we want to restrict access to a call based on from where the call is made so I need to pass this information. Let's say I make the call to MyService from FindUserModule then I need to add the id of that module in a header so that the AuthorizationManager can check if that user really should be authorized. This is due to service calls being used from many modules.
Handle this as SOAP header in custom message inspector.

WCF customizing metadata publishing

I have a universal service hosted on IIS7 that accepts a Message and returns Message ( with Action="*"). This service still publishes meta for the clients.
This metadata is explicitly specified using LocationUrl property in ServiceMetadataBehavior.
We have a requirement that the metadata can change during lifetime of the service, so in essence metadata has a lifetime.
I tried adding IWsdlExportExtension to the service endpoint behavior, but the ExportEndpoint method only gets called once (when the service is loaded first time). Is there a way for me to invalidate the loaded metadata so that anytime there is a call for wsdl using HttpGet, the behavior gets called ?
What you are asking for (changing the published service definition at runtime) is not possible - you need to remove the requirement which specifies that the metadata can change over time.
Once you've published a service, the only reason the service specification should change is because the service has been upgraded.
You should look closer at the business requirement which is making this technical requirement necessary, and try to find another way to satisfy it (perhaps post in programmers.stackexchange). Perhaps you can have multiple services available, and switch between the services over time - but this is a bit of a stab in the dark without knowing the business requirement.
No there is no way. Moreover if you needed you are up to your fully custom solution because this is out of scope of web services. Changing metadata means changing the service itself = its internal logic which always result in restarting the hosting process and publishing new metadata.