WinRT - consume WCF service - wcf

I have a windows service, which acts as a propagator for data received from external source. This windows service hosts WCF ServiceHost with NetNamedPipeBinding(). ServiceContract also defines CallbackContract
There is also a client DLL component, which consumes the server and bubbles up parsed data as an event. Data is bubbled upon receiving callback from the server.
The code works in desktop app, however when I try to reference client DLL in WinRT app I get following error:
The pipe name could not be obtained for the pipe URI: Access is denied. (5, 0x5)
I presume this is because WinRT (to my knowledge) lacks support for named pipes.
How to go about consuming such service in WinRT? I can alter WCF side to any requirement, but it has to be hosted as windows service (it has non WinRT consumers). Communication will always occur within the same machine, polling is the last resort.

First you need to switch to basicHttpBinding, because net.namedpipe is not supported.
Actually supported are BasicHttpBinding, NetTcpBinding, NetHttpBinding
Secondly in WinRT there's a policy in place, which prevents you from accessing localhost over the network stack.
To overcome this security policy you need to add a LoopbackExempt for your app.
CheckNetIsolation.exe LoopbackExempt -s
See details on MSDN:
http://msdn.microsoft.com/en-us/library/windows/apps/Hh780593.aspx
For the duplex way either POLLING is an aption (only works, when the app is focused).
Or using push notifications: http://blogs.msdn.com/b/jimoneil/archive/2012/10/15/windows-8-notifications-push-notifications.aspx

Use the HttpClient class.. that's the only simple workaround, and works as well.
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));
httpClient.DefaultRequestHeaders.Add("SOAPAction", "http://ws.cdyne.com/WeatherWS/GetCityWeatherByZIP");
var soapXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><GetCityWeatherByZIP xmlns=\"http://ws.cdyne.com/WeatherWS/\"><ZIP>23454</ZIP></GetCityWeatherByZIP></soap:Body></soap:Envelope>";
var response = httpClient.PostAsync("http://wsf.cdyne.com/WeatherWS/Weather.asmx", new StringContent(soapXml, Encoding.UTF8, "text/xml")).Result;
var content = response.Content.ReadAsStringAsync().Result;
Try this? I hope this is what you're looking for - https://quirkd.wordpress.com/2015/01/24/shorts-consuming-a-wcf-asmx-web-service-in-winrt/

Related

SignalR firing OnConnectedAsync for users in a hub on another machine

Our Azure SignalR application is a bit of a hybrid, outgoing messages go into ActiveMQ then get picked up by a listener in a hosted service that receives them and sends them to the NotificationsHub (in the same API project). e.g. await _notificationsHub.Clients.All.SendAsync("PerformAction", action, payload);
Recently I tried to extend this so that a second application using a different authentication scheme (this one is external facing, the existing one is internal facing) could connect and receive some messages (and send others back). I did a POC and everything seemed fine.
public class NotificationsHub : Microsoft.AspNetCore.SignalR.Hub {
public override async Task OnConnectedAsync() {
await Groups.AddToGroupAsync(Context.ConnectionId, "foo");
await base.OnConnectedAsync();
await Clients.Caller.SendAsync("SetConnectionId", Context.ConnectionId);
}
}
Today I was debugging in Visual Studio the new application API and in the Hub's OnConnectedAsync method I kept receiving the "connected" events for users on a completely different server.
So my question is, does SignalR fire the "OnConnected" event for every hub connected to the same endpoint (for every instance of that hub)?
Even if that is the case wouldnt these two Hub classes be considered separate and not share their groups (see multiple hubs)?
Edit
For reference the project is targeting netcoreapp3.1, and using Microsoft.Azure.Signalr 1.8.1 in the original project and 1.16.1 in the new one.
It turns out that SignalR uses the name of the "Hub" class when connecting to the Azure SignalR service, i.e. 'wss://foo.service.signalr.net/server/?hub=notificationshub&cid={guid}'.
All hubs with the same name are treated as the same hub. I couldnt find that in the docs anywhere but it is implied in ApplicationName property of ServiceOptions which says "Gets applicationName, which will be used as a prefix to apply to each hub name"

How to store configuration in Window8 RT Application?

I need to connect Win8 app to WCF service. The WCF client is created using Add Service Reference.
The requirement is to change the End point URL at runtime. Win 8 does not have app.config and instead use Application Data settings.
The problem is that App needs the URL at the startup. If URL is invalid, or cannot be reached, the app is terminated.
The question is, How to manage scenarios, where configuration settings are required for app startup, and to be set up at runtime?
When you create an instance of the client, before you start using it you can change the address for the service by accessing the Endpoint property of the client. Something like the code below.
var client = new ServiceReference1.ServiceClient();
client.Endpoint.Address = new EndpointAddress(yourNewUri);

Windows service using WCF NetNamedPipe to communicate to client

The reason I'm writing this question is that I seem to be getting the following error when I'm trying to communicate between a windows service and a WPF app via a WCF service with a NetNamedPipe binding:
System.ServiceModel.EndpointNotFoundException: There was no endpoint
listening at net.pipe://localhost/Pipe_SendInfo
Now the gory details.
Ok, I have a windows service that is periodically executing code, I wanted to let a user know what is happening inside the service. So I read that I could accomplish this via NetNamedPipe WCF service. I created two test apps and successfully was able to send a message from one process to another. I then attempted to send messages from the windows service to a client app(on the same machine) and have so far failed miserably :(.
My windows service essentially does this(trying to send info):
ChannelFactory<SkipSyncLib.ISendInfo> pipeFactory =
new ChannelFactory<SkipSyncLib.ISendInfo>(
new NetNamedPipeBinding(),
new EndpointAddress("net.pipe://localhost/Pipe_SendInfo"));
pipeFactory.CreateChannel();
pipeFactory.SendInfo(info);
and the application that is supposed to receive the information does this when it starts up:
public void Start()
{
HostService = new ServiceHost(this, new Uri[] { new Uri("net.pipe://localhost") });
HostService.AddServiceEndpoint(typeof(ISendInfo), new NetNamedPipeBinding(), "Pipe_SendInfo");
try
{
HostService.Open();
}
catch (Exception exc)
{
//Error handling
}
}
The kicker is that while the windows service is failing miserably to find the endpoint I have another console app that is able to send info to the running client app successfully. So logic would tell me that it probably has something to do with users. But I can't figure it out.
Any ideas? Should I just drop named pipes and go with an http binding?
I just found out about named pipes earlier today so please be gentle if the answer is obvious.
Thanks
I figured out a way for it to work. There's probably a more elegant way to do this, but if the windows service and the client app are run as the same user then the communication channel works.
Should you use the same endpoint address?
HostService = new ServiceHost(this, new Uri[] { new Uri("net.pipe://localhost/Pipe_SendInfo") });
add /Pipe_SendInfo in Uri

WCF Authentication and Socket Aborted Exception

here's the setup for the project.
I have a WCF Service that is hosted on a net.tcp binding in buffered mode and ReliableSession enabled.
The binding is configured to use TransportWithMessageCredential security. The certificate is a self signed certificate that I am identifying using the Thumbprint.
The UserNameValidator is a custom validator which for testing, never fails (it wasn't failing before but I removed the uncertainty)
The service and client are on the same machine and they both have access to the certificate.
The problem:
I am receiving a Socket Aborted exception when trying to consume a Method from the service. Here is the code I use to open a connection to the service. MonitorServiceCallbacks only contains empty methods to fulfil the requirements of the Interface.
_instanceContext = new InstanceContext(new MonitorServiceCallbacks());
_serviceInterface = new MonitorCallbackServiceClient(_instanceContext);
_serviceInterface.ClientCredentials.UserName.UserName = Environment.MachineName;
_serviceInterface.ClientCredentials.UserName.Password = "myPassword";
_serviceInterface.Open();
This appears to work fine as the _serviceInterface.State variable is set to State.Opened and the custom validator is called and returns without exception.
However, if I try to call a method using the _serviceInterface proxy, no code that I can break into is run on the service and the tracelog reveals no errors apart from a SocketAborted exception which occurs 1 minute after receiving what appears to be the message for the method.
There is no InnerException.
I have tried to google the issue but the results tend to say "just disable security and it will work fine". Unfortunately, this cannot be done.
I am extremely confused by this issue and any help would be greatly appreciated.
Many thanks,
Ehrys
This was actually a serialisation error.
The object I was trying to send to the service inherited from the data contract. So I was trying to send a cast down to the data contract to the service.
WCF doesn't appear to allow this.
I would like to thank John Saunders for reminding me that not only the service can have tracing enabled. Enabling client side tracing would have saved me a lot of time.
I was attempting to do the following:
_serviceInterface.Register((MyDataContract)MyParentObject, aVariable, anotherOne);
What I needed to do:
MyDataContract tempContract = MyParentObject.CreateMyDataContract();
_serviceInterface.Register(tempContract, aVariable, anotherOne);
/* Note: MyParentObject.CreateMyDataContract() is my own method which creates an instance
of the MyDataContract and copies the relevant information to it */

Web Service missing methods when called from Silverlight

I created WCF web service, deployed it, and debugged it. I wrote a console app, referenced the web service, and everything works.
Now, I'm attempting to consume the web service in a silverlight 3 application. I added the following code to a click event.
TagServiceClient client = new TagServiceClient();
Tag[] tags = client.GetTags();
client.Close();
VS is telling me it can't find the GetTags() and Close() methods. But VS has no problem with these methods in the console app.
I added a using statement for the service reference to the top of my file.
I placed a clientaccesspolicy.xml file in the root domain and in the folder containing the web service. Doesn't seem to change anything regardless where it is.
What's going on? Any suggestions? This is my first time consuming a web service in Silverlight so I may just be missing something.
You will need to generate a new client proxy to use in the Silverlight app - IOW, from the Silverlight app, add a new service reference, and point it to the service.
You will then see that things are a little different - you will find that there are async methods in the proxy, not the synchronous ones you will have seen in the proxy generated for the console app. So in the silverlight app, your code will end up looking something like this:
client.GetTagsCompleted += [my event handler];
client.GetTagsAsync();
and in your event handler:
if (e.Error == null)
if (!e.Cancelled)
List<Tag> tags = new List<Tag>(e.result);
When you add a the service reference to the silverlight app, make sure you have a poke around the advanced settings, because you can change what sort of collection the items are returned in, etc (the default return collection is an ObservableCollection<T>).
If you want to avoid this sort of thing (different proxies for different apps or modules), then consider using svcutil to generate your proxy instead of allowing VS to do it (VS doesn't use svcutil).