I have what I thought was a simple .NET Remoting Client/Server (Code Below)... When hosting/running in a Console application it works fine, but when hosted in a Windows Service, all calls to members of proxies returned from Activator.GetObject result in a NullReferenceException.
To simplify things I placed all this in a single Console and it worked fine... Created a basic Windows Service and placed the same code on the OnStart method and once I access the "TheString" property I get a NullReferenceException.
I can confirm there are no other exceptions, the ports are available, and the service is run as an administrator. Also, my solution will require a singleton which is why I am using that.
At the moment this is being hosted on Windows 7 which may be a factor. If I could learn how to see more of what underlying error may be causing this, I may be able to figure it out... How can I see what might be happening underneath (ex. sink, formatter, etc...)?
Server Code:
var provider = new BinaryServerFormatterSinkProvider
{
TypeFilterLevel = TypeFilterLevel.Full
};
IDictionary properties = new Hashtable();
properties["port"] = 20001;
properties["exclusiveAddressUse"] = false;
_channel = new TcpChannel(properties, null, provider);
ChannelServices.RegisterChannel(_channel, false);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(HostClass), "TheHost", WellKnownObjectMode.Singleton);
Client Code:
var retInstance = (HostClass)Activator.GetObject(typeof(HostClass),
string.Format("tcp://{0}:{1}/TheHost", "MyHostName", 20001));
string host = retInstance.TheString; //This is where the NullReference is experienced
Remoting Object:
public class HostClass : MarshalByRefObject, IHostClass
{
public HostClass()
{
TheString = "Hello World";
}
public override object InitializeLifetimeService()
{
return null;
}
public string TheString { get; set; }
}
Any ideas would be appreciated.
As it turns out the limitation relates to the remoting engines inability to serialize and proxy interface types, which while not part of my sample (sorry) was ultimately the root of the issue.
Related
I have a Windows service hosting multiple WCF services. All of it running on a local machine (using NamePipe).
Is there a simple way to have these WCF services share a property? (I would rather not have them sharing a file).
I need this as each session instantiated within each WCF service will be getting a hold on a given hardware and the other WCF services need to know what is still available in order to be able to instantiate another session.
Each WCF service implements a different protocol, which is why I did not merge the lot. There will be one proxy for each host.
I don't know of a super simple way of getting service instances to share a property, but you could create a custom host that derives from ServiceHost and have it implement a particular interface, say something like:
public interface ISharedStateContainer
{
SharedState State { get; set; }
}
This interface would have to be known your services. Then, in your windows service project, you could make a custom service host:
public class CustomServiceHost: ServiceHost, ISharedStateContainer
{
SharedState state;
public SharedState State{ get{ return state; } set{ state=value; } }
}
...and then when the windows service creates the wcf service host instances, it could inject the shared state:
var sharedState = new SharedState();
myServiceHost = new CustomServiceHost( typeof( MyService ) );
((ISharedStateContainer) myServiceHost).State = sharedState;
myOtherHost = new CustomServiceHost( typeof( OtherService ) );
((ISharedStateContainer) myOtherHost).State = sharedState;
myServiceHost.Open();
myOtherHost.Open();
...and then, in a running instance of a service, you could get to shared state like this:
var sharedState = ((ISharedStateContainer)OperationContext.Current.Host).State
Where I've got SharedState, you could make it any type you want...but making it a reference type that itself has properties means you can use it to share as many properties as you need. Note that with any shared state, you'll have race conditions to protect against.
I've done a windows service the same way (multiple different wcf service types)...and this is more-or-less how they share state.
EDIT:
I don't know why I didn't think about this sooner, but another nice way to share state is using a singleton. This is probably more straightforward than the earlier approach. I have this pattern going on, too...for a somewhat different reason, but it would serve for shared state, too:
public class SharedState
{
//--> singleton instance...
static readonly SharedState current;
//--> use static initializer to create the current instance...
static SharedState( )
{
current = new SharedState();
}
//--> hide ctor...
private SharedState(){}
public static SharedState Current
{
get { return current; }
}
//--> all your shared state instance methods and properties go here...
public string SomeString
{
get
{
return //...
}
}
}
...and then you can get to this object from anywhere in your service, even from code not running in the context of a client operation. I use this for long running background task that the service needs to perform periodically, but shared properties are super easy:
var someValue = SharedState.Current.SomeString;
I have a publisher / subscriber pattern WCF Duplex ServiceHost that is hosted by a Windows Service. The Windows Service receives events from a separate process. OnEvent I would like to force my WCF Host to publish that data to all subscribed clients. Typically if a Client is calling this is straight forward. But when my Service Host needs to do this - I can't get my head around HOW to do that.
I have 2 questions:
1: I do not know how to create a Channel in WCFHost from my Windows Service so that it can use to publish to the Subscribers.
2: I read Creating WCF ChannelFactory so I do know I am creating a DuplexChannelFactory (2 per second ) which might be too much overhead.
Any help examples, hints are greatly appreciated. I am not a WCF expert and currently know more about it than I thought I should have to know in order to use it.
I had read on SO
Can I call a Method in a self hosted wcf host locally?
So then I have created a method inside my WCFHost like so:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,
AutomaticSessionShutdown = false,
IncludeExceptionDetailInFaults = true)]
[CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class ServerHost<TService> : ServiceHost where TService : class
{
public T GetDuplexClientChannel<T, Cback>(BindingType bindingType, EndpointAddress endPointAddress) where T : class
{
ServiceEndpoint sep = GetContractServiceEndPoint<T>(bindingType, endPointAddress);
lock (_syncRoot)
{
DuplexChannelFactory<T> factory = new DuplexChannelFactory<T>(typeof(Cback), sep);
return factory.CreateChannel(endPointAddress);
}
}
}
I get an error of course that there is no InstanceContext because I am constructing using typeof(Cback) ..
"This CreateChannel overload cannot be called on this instance of DuplexChannelFactory, as the DuplexChannelFactory was initialized with a Type and no valid InstanceContext was provided."
So I am not sure how I can go about performing this ?
And for those that say read the error : yes I read the error.
Now how to do that with an InstanceContext that does not exist as OperationContext.Current does not exist at this point as I am calling this method form my Hosting Process into my WCFHost.
So if I could have a nice example of how to do this - even if I must use the code example on the 2nd link (of course implementing the DuplexChannelFactory) I would greatly appreciate it.
EDIT
Basically the windows Service is doing some heavy work monitoring other services, about 2 times a second it then must publish that to "Subscribed" Clients via WCF.
I think you have got very confused about how everything is wired together and are mixing concepts from the client in with the service. You haven't provided much concrete information about your scenario to go on so I'm going to provide a small example and hopefully you will be able to apply the ideas to your problem.
[ServiceContract(CallbackContract=typeof(IMyServiceCallback))]
public interface IMyService
{
[OperationContract]
void Register();
}
public interface IMyServiceCallback
{
[OperationContract]
void ReceiveData(string data);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MyService : IMyService
{
static HashSet<IMyServiceCallback> s_allClients = new HashSet<IMyServiceCallback>();
static object s_lockobj = new object();
public void Register()
{
lock(s_lockobj)
{
_allClients.Add(OperationContext.Current.GetCallbackChannel<IMyServiceCallback>());
}
}
public static void SendDataToClients(string data)
{
HashSet<IMyServiceCallback> tempSet;
lock(s_lockobj)
{
tempSet = new HashSet<IMyServiceCallback>(_allClients);
}
foreach(IMyServiceCallback cb in tempSet)
{
try
{
cb.ReceiveData(data);
}
catch(Exception)
{
lock(s_lockobj)
{
_allClients.Remove(cb);
cb.Abort();
cb.Dispose();
}
}
}
}
}
In your OnEvent method, you would call something similar to this inside your event method.
MyService.SendDataToClients(mydata);
This uses static data to store the list of clients. If you wanted to do something like segment your clients for different endpoints, you would need to do something different. There is a potential out of order message and scaling problem with this code if your OnEvent method can be called again while the previous call hasn't completed. For example, if you receive 2 messages, the first being large and the second being small, you could potentially send the second smaller message to clients later in the HashSet iteration order before they have been sent the first message. Also this won't scaled to a large number of clients as you could block timing out on one client holding up messages being sent to other clients. You could use something similar to Task's to dispatch multiple message deliveries. If this needs to scale, I would suggest looking at Reactive Extensions for .Net
I have a client application that consumes a number of services. It's not always immediately obvious when a service is down or incorrectly configured. I own the service side code and hosting for most of the services, but not all of them. It's a real mixed bag of client proxies - different bindings (basichttp/wshttp/nettcp), some have been generated using svcutil.exe, while others are made programatically with ChannelFactory where the contract is in a common assembly. However, I always have access to the address, binding and contract.
I would like to have a single component in my client application that could perform a basic check of the binding/endpoint config and the service availability (to show in some diagnostic panel in the client). As a minimum I just want to know that there is an endpoint at the configured address, even better would be to find out if the endpoint is responsive and supports the binding the client is trying to use.
I tried googling and was surprised that I didn't find an example (already a bad sign perhaps) but I figured that it couldn't be that hard, all I had to do was to create a clientchannel and try to open() and close() catch any exceptions that occur and abort() if necessary.
I was wrong - in particular, with clients using BasicHttpBinding where I can specify any endpoint address and am able to open and close without any exceptions.
Here's a trimmed down version of my implementation, in reality I'm returning slightly more detailed info about the type of exception and the endpoint address but this is the basic structure.
public class GenericClientStatusChecker<TChannel> : ICanCheckServiceStatus where TChannel : class
{
public GenericClientStatusChecker(Binding binding, EndpointAddress endpoint)
{
_endpoint = endpoint;
_binding = binding;
}
public bool CheckServiceStatus()
{
bool isOk = false;
ChannelFactory<TChannel> clientChannelFactory = null;
IClientChannel clientChannel = null;
try
{
clientChannelFactory = new ChannelFactory<TChannel>(_binding, _endpoint);
}
catch
{
return isOk;
}
try
{
clientChannel = clientChannelFactory.CreateChannel() as IClientChannel;
clientChannel.Open();
clientChannel.Close();
isOk = true;
}
catch
{
if (clientChannel != null)
clientChannel.Abort();
}
return isOk;
}
}
[Test]
public void CheckServiceAtNonexistentEndpoint_ExpectFalse()
{
var checker = new GenericClientStatusChecker<IDateTimeService>(new BasicHttpBinding(), new Endpointaddress("http://nonexistenturl"));
// This assert fails, because according to my implementation, everything's ok
Assert.IsFalse(checker.CheckServiceStatus());
}
I also tried a similar technique with a dummy testclient class that implemented ClientBase with the same result. I suppose it might be possible if I knew that all my service contracts implemented a common CheckHealth() method, but because some of the services are outside my control, I can't even do that.
So, is it even possible to write such a simple general purpose generic service checker as this? And if so how? (And if not, why not?)
Thanks!
Have you looked at WCF Discovery?
WCF Discovery allows a client to search for a service based on
different criteria including contract types, binding elements,
namespace, scope, and keywords or version numbers. WCF Discovery
enables runtime and design time discovery. Adding discovery to your
application can be used to enable other scenarios such as fault
tolerance and auto configuration.
For a first attempt, you could query the endpoint to see if it supports the expected contract.
The big benefit is that you can have the client “discover” which service it wants to talk to at runtime. Which removes a lot of the client side configuration errors that you are likely used to seeing.
You need to check out SO-AWARE. It is a web service management tool that can manage SOAP or REST WCF-based service across your organization. Further it has a Test Workbench!
Here are a couple of videos that show it off too:
Part 1
Part 2
To put it in perspective, this is so complex that these people make a living doing it, I don't think it's something you want to realistically build on your own.
I have a WCF Host with something like this:
[ServiceContract]
public interface IMountToOs
{
[OperationContract]
char GetMountDriveLetter();
[OperationContract]
MyTestClass MyTest();
}
public class MyTestClass
{
public string A { get; set; }
public string B { get; set; }
}
Client
private IMountToOs _proxy;
public IMountToOs Proxy
{
get
{
if (_proxy == null)
{
NetTcpBinding binding = new NetTcpBinding();
binding.MaxReceivedMessageSize = 2147483647;
binding.OpenTimeout = TimeSpan.FromMilliseconds(50000);
EndpointAddress address = new EndpointAddress("net.tcp://localhost:1234/MountToOsHost");
//_proxy = new MountToOsClient(binding, address);
ChannelFactory<IMountToOs> factory = new ChannelFactory<IMountToOs>(binding);
_proxy = factory.CreateChannel(address);
}
return _proxy;
}
}
While I can access
MessageBox.Show("Okay - " + Proxy.GetMountDriveLetter());
I can't call this method:
MessageBox.Show("Okay - " + Proxy.MyTest().A);
The complete extension is not working. But only while using it in an extension. Even if I insert a Messagebox in the first line of the extension it is not hit. I don't know why. It seems to run a pre-check and find the call of the custom class which is refused or so...
If I use a winform or so there is no problem.
.net 3.5
curious is that I have a break-point and a message of the hosts side. So I see that the method is not called
Update
now I moved the wcf-call in the Load Method of the extension and get a exception:
System.MissingMethodException: method not found:
"Contracts.Interfaces.MyTestClass
Contracts.Interfaces.IMountToOs.MyTest()".
My winform test and this extension use the same interface so that the method should known from both. no contract or so is outdated
According to what I found here and in the comments of the post: "For creating dynamic service proxy using client channel factory method, you will need datacontracts of the service. If you don't have datacontracts but you have the service URL, then you could use reflection to create proxy at runtime and call the service method."
Seems that the MyTestClass type is not known on the client side, so I think you could use reflection, or share the class between the client and server or much more simple, use the datacontract attribute.
Also, found something on MSDN that says something like this:
"When to use a proxy?
We create proxy using svcutil.exe. The output of this tool gives a proxy class and makes corresponding changes to the application configuration file. If you have a service that you know is going to be used by several applications or is generic enough to be used in several places, you'll want to continue using the generated proxy classes. We use proxy in WCF to be able to share the service contract and entities with the client. Proxies have several restrictions like they need to have gets and sets , contructors can't be exposed , methods other than the service contract cannot be exposed, repetition of code, everytime that we add/modify a service contract/data contract/message contract we need to re-generate the proxy for the client.
When to use ChannelFactory
The other option is using the ChannelFactory class to construct a channel between the client and the service without the need of a proxy . In some cases, you may have a service that is tightly bound to the client application. In such a case, it makes sense to reference the Interface DLL directly and use ChannelFactory to call your methods using that. One significant advantage of the ChannelFactory route is that it gives you access to methods that wouldn't otherwise be available if you used svcutil.exe..
When to use a ChannelFactory vs Proxy class?
A DLL is helpful if the client code is under you control and you'd like to share more than just the service contract with the client -- such as some utility methods associated with entities and make the client & the service code more tightly bound. If you know that your entities will not change much and the client code is less, then a DLL would work better than a proxy. If the client to your service is external to the system, such as API, it makes sense to use a proxy, because it makes sharing the contract easier by giving a code file rather than a DLL."
We cant see the class
MountToOsClient: IMountToOs
So we can only assume it is ok.
[DataContract] // Missing
public class MyTestClass
{
[DataMember] // Missing
public string A { get; set; }
[DataMember] // Missing
public string B { get; set; }
}
MountToOsClient can not expose Mytestclass without these attributes.
I'm working with a 3rd party API whose objects I am exposing through a web service. Unfortunately the API has some quirks, including throwing exceptions when trying to access some properties if the object's ID field is 0.
So I'm creating a valid instance of the object on the server and pushing it through a WCF service to the client. The problem occurs when the client receives the object. It seems that for whatever reason, the service inspects each of the properties of the object before it populates them on the client. So the objects are throwing exceptions when the client receives them but before I'm able to do anything with them. Here's some quick example code to demonstrate what is happening.
public class ExposedClass {
public int Id { get; set; }
List<OtherClass> _other;
public List<OtherClass> Other {
get {
if (Id == 0) throw new Exception("Can't access field 'other' if object not initialized");
return _other;
}
}
}
In the service:
[ServiceContract]
public MyService {
[OperationContract]
public ExposedClass GetThing() {
ExposedClass c = new ExposedClass();
c.Initialize(); // makes the Id field valid
return c;
}
}
And the client:
[TestMethod]
public void GetThingFromService {
var svcClient = new MyClient();
var c = svc.GetThing(); // exception thrown here on client
Assert.IsNotNull(c);
}
Any ideas?
Usually a DataContract class should not contain any programming logic. It is used as a sort of container to store information which is passed to the client.
My approach would be to copy the information I need from the 3rd party object onto a custom DTO (Data Transfer Object) before sending it down the network.
Are the 3rd party classes actually required at the client end? If possible it would be a good idea to discard the 3rd party objects at the server, thus layering and insulating your users from buggy code which you have no control over.
There are two possibilities:
Contact the developer of the library and tell them that they need to fix their code.
Barring that use (if licensing allows) Reflector and tear apart the assembly, fix it yourself, and recompile.
An object should never depend on the order of fields being assigned for this exact reason.