Design Question - Handling .NET App Config at a DLL level - wcf

I have an existing .NET 3.5 based framework that is extended using custom plugins. In summary plugins implement a common interface and the core framework invokes these via reflection. The framework works perfectly and all is good, however...
I now have a requirement that requires a plugin that communicates with the WCF service. At face value this is simple, add a service reference to the plugin, call the client proxy code and off we go. However...
Due to the way that .NET configuration works the WCF service client configuration should reside within the app.config of the executing application. In this case this is my plugin invoker application. The problem with this is that it breaks the plugin "model" as the generic invoker application now has to have plugin specific configuration within it.
So the question is does anybody know of an alternative mechanism for handling the WCF service client configuration without putting it into the core invoker application configuration?
Having done a little hunting around there are mechanisms to allow a DLL to use its own config file. The issue here is that I don't have access to the underlining code of the service proxy creation and therefore seemingly can't redirect the config reads.

A WCF client's endpoint can be configured programmatically as well.
Here's an example that shows how to invoke a WCF service without the need for a configuration file:
var myBinding = new BasicHttpBinding();
var myEndpoint = new EndpointAddress("http://localhost/myservice");
var client = new MyServiceClient(myBinding, myEndpoint);
try
{
client.MyServiceOperation();
client.Close();
}
catch
{
if (client != null)
{
client.Abort();
}
}
Related resources:
ClientBase<TChannel> Constructor (Binding, EndpointAddress)

Answering my own question:
I seem to have found a solution to the problem here:
http://weblogs.asp.net/cibrax/archive/2007/10/19/loading-the-wcf-configuration-from-different-files-on-the-client-side.aspx
In summary this allows you to specify a custom configuration file that contains the WCF configuration as it is generated by Visual Studio - this means that the config can be maintained easily.
Having run a couple of quick tests it seems that it works as it should (with a few tweaks here and there (see the comments on the page).

Related

wcf wp7 service reference - session/coockie

i have and app that use a wcf service reference with the enableHttpCookieContainer="true" in the binding.
enableHttpCookieContainer is not really compatible in visual studio, i need every time that i need to update to delete it.
after few searchs i founded other methods to pass cookies in the wcf requests like this:
using (new System.ServiceModel.OperationContextScope(Channel))
{
System.ServiceModel.Channels.HttpRequestMessageProperty request = new System.ServiceModel.Channels.HttpRequestMessageProperty();
request.Headers["Cookie"] = CoockieContainer;
System.ServiceModel.OperationContext.Current.OutgoingMessageProperties[System.ServiceModel.Channels.HttpRequestMessageProperty.Name] = request;
}
but this don't work for me in wp7.
my question is, what is the officially, clean, compatbile way, to have a session in wcf when use from wp7 service reference? if wcf is hosted in a windows service instead a web site, there is not session, so i really think that the enableHttpCookieContainer is a fail and not clean way...

Ninject Di bindings using a WCF service

I recently created a WCF service library. I am planning on hosting it in IIS. Since I want to reuse my repository layer I decided to go use Ninject in my WCF service as well (I use it in other projects in the solution).
I installed the Ninject Wcf Extensions. I configured it using the NinjectServiceHostFactory in the svc file. I added a Global.asax file to override the CreateKernel() that inherits from NinjectWcfApplication but I am not sure if I am using the bindings correctly. I first started with:
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
But I quickly realized that this does not work since no data was saved to my database. It appears that the WCF service does not use the ASP.NET pipeline. I went ahead and tried both of these as well just to see if my data was committed to the database:
Bind<IUnitOfWork>().To<UnitOfWork>().InThreadScope();
Bind<IUnitOfWork>().To<UnitOfWork>().InTransientScope();
No luck. I then decided to try:
Bind<IUnitOfWork>().To<UnitOfWork>().InSingletonScope();
This worked but I don't want my database context to be shared by every single request that comes in to the WCF service. I then did some research and found the following approach:
Bind<IUnitOfWork>().To<UnitOfWork>().InScope(c => OperationContext.Current);
This works but is it correct? I wan t something to resemble the InRequestScope for a MVC application. Each request to the service should get its own Database context.
I suggest to have a look at the latest build from the CI-Server http://teamcity.codebetter.com
You need Ninject, Ninject.Web.Common, Ninject.Extensions.Wcf
With this version you can use InRequestScope for Wcf.
I am new to Ninject, but I can tell you that OperationContext.Current is the equivalent to HttpContext.Current for web application.
So your first thought was to use .InRequestScope(); (which is equivalent to .InScope(c => HttpContext.Current);)
so I guess that using .InScope(c => OperationContext.Current); for WCF is pretty correct.

Create WCF endpoint configurations in the client app, in code?

I am trying to consume a WCF web service from a .NET client application, and I think I need to be able to programmatically create endpoints, but I don't know how. I think I need to do this because, when I try to run the application, I am getting the following error:
Could not find default endpoint
element that references contract
'IEmailService' in the ServiceModel
client configuration section. This
might be because no configuration file
was found for your application, or
because no endpoint element matching
this contract could be found in the
client element.
While troubleshooting this error, I created a simple windows forms application, in which I try to consume the same web service. With this test application I can connect to the web service successfully, and I get a valid response. But, I can reproduce the exact error cited above within in my test app by removing the system.serviceModel node and all of its child nodes from the application's app.config file (I might not have to remove ALL of that section, I'm not sure). So, my first thought was that I need to add that section to the app.config file for the real app, and everything should be fine. Unfortunately, for ridiculous reasons that I won't get into here, that is not an option. So, I am left with having to generate this information in code, inside the client app.
I am hoping someone here can help me work through this, or can point me toward a good resource for this sort of problem.
Is it possible to create endpoint configurations in the client app, in code?
By default, when you do an Add Service Reference operation, the WCF runtime will generate the client-side proxy for you.
The simplest way to use it is to instantiate the client proxy with a constructor that takes no parameters, and just grab the info from the app.config:
YourServiceClient proxy = new YourServiceClient();
This requires the config file to have a <client> entry with your service contract - if not, you'll get the error you have.
But the client side proxy class generated by the WCF runtime also has additional constructors - one takes an endpoint address and a binding, for instance:
BasicHttpBinding binding = new BasicHttpBinding(SecurityMode.None);
EndpointAddress epa = new EndpointAddress("http://localhost:8282/basic");
YourServiceClient proxy = new YourServiceClient(binding, epa);
With this setup, no config file at all is needed - you're defining everything in code. Of course, you can also set just about any other properties of your binding and/or endpoint here in code.
An east way to consume a WCF service if you have a reference to the assembly which defines the interface, is using the System.ServiceModel.ChannelFactory class.
For example, if you would like to use BasicHttpBinding:
var emailService = ChannelFactory<IEmailService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress(new Uri("http://some-uri-here.com/));
If you don't have a reference to the service assembly, then you can use one of the overloaded constructors on the generated proxy class to specify binding settings.

Does client consuming WCF service require Interface definition?

I have been going through the book "Learning WCF" trying to get my head around creating and using WCF web services. The first part of the book walks the reader through creating and then consuming a simple "Hello World" web service.
The problem I am having is that the client application seems to have no know the structure of the WCF Interface when calling it. How can this be necessary if a web service could be called from any number of programming languages?
I have listed the relevant example code below ...
Here is the code for the Interface
[ServiceContract(Namespace="http: //www.thatindigogirl.com/samples/2006/06")]
public interface IHelloIndigoService
{
[OperationContract]
string HelloIndigo();
}
Here is the code for the Service that hosts the web service
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(HelloIndigo.HelloIndigoService) ,
new Uri("http: //localhost: 8000/HelloIndigo")))
{
host. AddServiceEndpoint(typeof(HelloIndigo. IHelloIndigoService) ,
new BasicHttpBinding(), "HelloIndigoService");
host. Open( );
Console. WriteLine("Press <ENTER> to terminate the service host") ;
Console. ReadLine();
}
}
Here is the code for the client app that consumes the WCF service
This is where I get confused. Since this client application could be any language capable of calling a web service why is there a necessity of knowing the definition of the interface?
using System. ServiceModel;
[ServiceContract(Namespace = "http: //www.thatindigogirl.com/samples/2006/06")]
public interface IHelloIndigoService
{
[OperationContract]
string HelloIndigo( );
}
static void Main(string[ ] args)
{
EndpointAddress ep = new
EndpointAddress("http: //localhost: 8000/HelloIndigo/HelloIndigoService") ;
IHelloIndigoService proxy = ChannelFactory<IHelloIndigoService>.
CreateChannel(new BasicHttpBinding(), ep);
string s = proxy. HelloIndigo();
Console. WriteLine(s) ;
Console. WriteLine("Press <ENTER> to terminate Client.") ;
Console. ReadLine();
}
Am I missing an important point here? Perhaps my understanding of what is needed to consume a web is lacking. My goal is to be able to use WCF to create a .NET service that could be called from any programming language or environment.
Might anyone suggest a good tutorial on creating "cross platform consumable" web services from within .NET? Thanks!
This approach is based on shared interface (the book acutally does not share the interface but instead it uses local copy) and is successfully applied in environment where both client and server are written in .NET. This approach is not usable for interoperability or SOA solutions.
Other approach uses metadata exposed by the service. Metadata are defined as WSDL document plus several XSD documents. These metadata files are way to provide information about your service to both .NET and non .NET developers. The book contains definition of Metadata (mex) endpoint so you will definitely read about that.
Using metadata in .NET means creating service proxy. You can do it automatically using Visual studio's Add service reference or command line utility svcutil.exe. Anyway generated proxy code will probably still contain the interface created from metadata. It is used to create transparent abstraction of the service for the client.
'The interface' doesn't mean a .NET interface file, it means the more general programming interface - a set of objects with properties, and methods with parameters. This is also called the service contract.
The reason that the client and the service need to share (i.e. both know about) the interface is simple when you think about it - if the client doesn't know the interface, how do they know what operations are available and what the expected request/response objects should look like?
Every WCF service is composed of
A - address
B - binding
C - contract
The contract is declared using an interface on the serverside. It declares which methods are available to the client. If you are using a http binding you can invoke a service operation by issuing a http request (using a http client in any library or language - or even a web browser) pointed at the correct address. So the client does not need any interface reference at all. It just needs to follow the ABC of the service.
Here is a nice blog on WCF and Java interopability.
To answer your question on how to develop 'cross platform consumable' web services, consider the REST approach. Making REST-style web services truly makes them independent of the platform that consumes them. Simply put, they use the already well established HTTP protocols everything supports: GET and POST Http methods.
You could then have a Java app simply make POST calls to your WCF services with your own custom XML content in the payload without having to fiddle with more complex stuff like making SOAP wrappers and the like. Check out Rob Bagby's article on REST:
http://www.robbagby.com/rest/rest-in-wcf-part-i-rest-overview/

Identity of thread in self hosted WCF service when called from Web Application

I have a Windows Service that is self hosting a Wcf service, this Wcf service has a tcpBinding with default settings. The Windows service is running as LocalSystem.
The Wcf Service is referenced (default settings) by a Web application that is running in IIS 7.5 integrated pipeline within it's own application pool with its own identity.
Both are running on the same machine.
All is working fine, except that when in the Wcf Service when I check the identity of the current thread with:
Thread.CurrentPrincipal.Identity.Name
It returns the user of the Application Pool of the Web Application.. this is not what I expect. It looks like some sort of impersonation is going on in the Wcf service.
Is this standard behavior? I can't find any documentation on this.
And does it mean that when I try to access a database in the Wcf service i'm introducing a identity hop?
Edit, the config on service side:
Type serviceType = typeof(WcfService);
host = new ServiceHost(serviceType);
Binding tcpBinding = new NetTcpBinding( );
Uri tcpBaseAddress = new Uri("net.tcp://localhost:8001/Test");
host.AddServiceEndpoint(typeof (WcfService), tcpBinding, tcpBaseAddress);
host.Open();
On the client side:
NetTcpBinding tcpBinding = new NetTcpBinding(SecurityMode.Transport);
windowsService = new WindowsService.WcfServiceClient(tcpBinding, new EndpointAddress("net.tcp://localhost:8001/Test"));
I'm reading from Learning WCF by Michele Bustamante. I have used WCF for an application that I've refactored and we're interested in using WCF in new applications for the flexibility it offers. One of the downsides of WCF is that it can be tricky to use the .net attributes or .config files to get the settings just right. I have spent days tracking down issues with the WCF settings. I've even created automated tests that will check that my service runs the way it's supposed to.
In response to your question, Michele says very specifically in Chapter Seven that NetTcpBinding is secure by default, meaning that callers must provide Windows credentials for authentication. I believe that would explain why the thread appears to be running as the identity of the web service. This is to protect your service from being called by an unauthorized user.
I believe that the following quotation from pp. 419-420 will answer your question concisely. "If you are familiar with traditional .NET role-based security, you know that there is a security principal attached to each executing thread. That security principal holds the caller's identity, which may be tied to a Windows account or a custom database credential, and its roles."
That seems to state plainly that yes, this is standard behavior.
I believe that you can change the behavior through attributes and .config files. I recommend you get a good book on the subject. I spun my wheels in the sand a long time trying to get bits and pieces of information about WCF from the web.
To clearify:
I was checking the wrong property here. Because code would be executed under the WindowsIdentity.GetCurrent() identity.
By default this is NOT the same as the caller (which is in Thread.CurrentPrincipal.Identity). If you want this behaviour you can control this with:
host.Authorization.ImpersonateCallerForAllOperations = true;
and
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
We actually have integrated security set at the website, and then any calls from the website to the WCF service we wrap in:
using (((WindowsIdentity)HttpContext.Current.User.Identity).Impersonate())
{
That makes sure the credentials of the logged in user are passed through, rather than the IIS app pool credentials.
Works like magic!
More information is needed, but I'm guessing that it's somewhere in the configuration for the binding on either the server side or the client side that impersonation is enabled. When adding service references, svcutil.exe is VERY aggressive in setting EVERY possible binding property in configuration.
If you could provide more information for the configuration on the server and client side, it would be appreciated.