Problems with nusoap in Windows Phone - c#

I have problems with Nusoap and Windows Phone and I hope that perhaps you could help me.
But first let me explain what I did:
First I created a webservice
<?php
require_once('./lib_095/nusoap.php');
$server = new soap_server();
$server->configureWSDL('test_wsdl', 'urn:test_wsdl');
$server->wsdl->schemaTargetNamespace = 'urn:test_wsdl';
$server->register('test', // method name
array('var' => 'xsd:string'), // input parameters
array('return' => 'xsd:string'), // output parameters
'urn:test_wsdl', // namespace
'urn:test_wsdl#test', // soapaction
'rpc', // style
'literal', // use
'Test-Methode des Webservices' // documentation
);
function test($var)
{
return "test fine: $var";
}
// Use the request to (try to) invoke the service
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>
For my first test I wrote a console application in visual studio 2013:
ServiceReference1.test_servicePortTypeClient c = new ServiceReference1.test_servicePortTypeClient();
string check = "Milburn";
var result = c.test("Hallo");
Console.WriteLine(result);
This little programm works fine.
So I thought I could transfer the experience to Windows Phone - take the same code for that. But this didn't work. I even tried this code:
ServiceReference1.test_servicePortTypeClient c = new ServiceReference1.test_servicePortTypeClient();
string check = "Milburn";
var result = c.testAsync(check);
System.Diagnostics.Debug.WriteLine("Hallo"+result);
And as a result the program returned a task. So what can I do to get a string as a result ?
Thx for your help

The generated service uses async methods on Windows Phone (your test changed to testAsync) so you need to await them
var result = await c.testAsync(check);

Related

BLE host with Xamarin

I need an application which is use for advertise some services.
I installed some BLE plugin from NUGet and ı readed their documentation on github. Generally they explain scanner mode, except this plugin of BluetoothLE ( https://github.com/aritchie/bluetoothle) .
I tried that advertiser code :
protected override void OnStart()
{
var server = CrossBleAdapter.Current.CreateGattServer();
var service = server.AddService(Guid.NewGuid(), true); //ı got error on this line
var characteristic = service.AddCharacteristic(
Guid.NewGuid(),
CharacteristicProperties.Read | CharacteristicProperties.Write ,
GattPermissions.Read | GattPermissions.Write
);
var notifyCharacteristic = service.AddCharacteristic
(
Guid.NewGuid(),
CharacteristicProperties.Indicate | CharacteristicProperties.Notify,
GattPermissions.Read | GattPermissions.Write
);
IDisposable notifyBroadcast = null;
notifyCharacteristic.WhenDeviceSubscriptionChanged().Subscribe(e =>
{
var #event = e.IsSubscribed ? "Subscribed" : "Unsubcribed";
if (notifyBroadcast == null)
{
this.notifyBroadcast = Observable
.Interval(TimeSpan.FromSeconds(1))
.Where(x => notifyCharacteristic.SubscribedDevices.Count > 0)
.Subscribe(_ =>
{
Debug.WriteLine("Sending Broadcast");
var dt = DateTime.Now.ToString("g");
var bytes = Encoding.UTF8.GetBytes(dt);
notifyCharacteristic.Broadcast(bytes);
});
}
});
characteristic.WhenReadReceived().Subscribe(x =>
{
var write = "HELLO";
// you must set a reply value
x.Value = Encoding.UTF8.GetBytes(write);
x.Status = GattStatus.Success; // you can optionally set a status, but it defaults to Success
});
characteristic.WhenWriteReceived().Subscribe(x =>
{
var write = Encoding.UTF8.GetString(x.Value, 0, x.Value.Length);
// do something value
});
}
Error is that;
CS1061 'IObservable' does not contain a definition of 'AddService' and no accessible extension methods 'AddService' were found that accept a first argument of type 'IObservable' (could you be missing a using directive or assembly reference?)
What can ı do about that? Do you know another plugin can do advertiser ?
That plugin you are using is now out of service from reading the notice on the link you included. They have now shifted the functionality over to Shiny
I would strongly recommend looking at Shiny as it has some nice documentation on how to get setup with BLE Hosting here:
https://shinylib.net/blehosting/
Given that Shiny is written by the same person that wrote the plugin you were initially trying and looking over the documentation it shouldn't be too difficult to shift to this approach as large amounts of the code looks similar if not the same.

How to call google.apis.dialogflow.v2 in C#

I am new to Google APIs. I want to know how to call Google Dialogflow API in C# to get intent form the input text. But I can't find any example to call Dialogflow using C#.
Please provide some example to call Dialogflow from C#.
If I understand your question correctly you want to call the DialogFlow API from within a C# application (rather than writing fulfillment endpoint(s) that are called from DialogFlow. If that's the case here's a sample for making that call:
using Google.Cloud.Dialogflow.V2;
...
...
var query = new QueryInput
{
Text = new TextInput
{
Text = "Something you want to ask a DF agent",
LanguageCode = "en-us"
}
};
var sessionId = "SomeUniqueId";
var agent = "MyAgentName";
var creds = GoogleCredential.FromJson("{ json google credentials file)");
var channel = new Grpc.Core.Channel(SessionsClient.DefaultEndpoint.Host,
creds.ToChannelCredentials());
var client = SessionsClient.Create(channel);
var dialogFlow = client.DetectIntent(
new SessionName(agent, sessionId),
query
);
channel.ShutdownAsync();
In an earlier version of the DialogFlowAPI I was running into file locking issues when trying to re-deploy a web api project which the channel.ShutDownAsync() seemed to solve. I think this has been fixed in a recent release.
This is the simplest version of a DF request I've used. There is a more complicated version that passes in an input context in this post:
Making DialogFlow v2 DetectIntent Calls w/ C# (including input context)
(Nitpicking: I assume you know DialogFlow will call your code as specified/registered in the action at DialogFlow? So your code can only respond to DialogFlow, and not call it.)
Short answer/redirect:
Don't use Google.Apis.Dialogflow.v2 (with GoogleCloudDialogflowV2WebhookRequest and GoogleCloudDialogflowV2WebhookResponse) but use Google.Cloud.Dialogflow.v2 (with WebhookRequest and WebhookResponse) - see this eTag-error. I will also mention some other alternatives underneath.
Google.Cloud.Dialogflow.v2
Using Google.Cloud.Dialogflow.v2 NuGet (Edit: FWIW: this code was written for the beta-preview):
[HttpPost]
public dynamic PostWithCloudResponse([FromBody] WebhookRequest dialogflowRequest)
{
var intentName = dialogflowRequest.QueryResult.Intent.DisplayName;
var actualQuestion = dialogflowRequest.QueryResult.QueryText;
var testAnswer = $"Dialogflow Request for intent '{intentName}' and question '{actualQuestion}'";
var dialogflowResponse = new WebhookResponse
{
FulfillmentText = testAnswer,
FulfillmentMessages =
{ new Intent.Types.Message
{ SimpleResponses = new Intent.Types.Message.Types.SimpleResponses
{ SimpleResponses_ =
{ new Intent.Types.Message.Types.SimpleResponse
{
DisplayText = testAnswer,
TextToSpeech = testAnswer,
//Ssml = $"<speak>{testAnswer}</speak>"
}
}
}
}
}
};
var jsonResponse = dialogflowResponse.ToString();
return new ContentResult { Content = jsonResponse, ContentType = "application/json" }; ;
}
Edit: It turns out that the model binding may not bind all properties from the 'ProtoBuf-json' correctly (e.g. WebhookRequest.outputContexts[N].parameters),
so one should probably use the Google.Protobuf.JsonParser (e.g. see this documentation).
This parser may trip over unknown fields, so one probably also wants to ignore that. So now I use this code (I may one day make the generic method more generic and thus useful, by making HttpContext.Request.InputStream a parameter):
public ActionResult PostWithCloudResponse()
{
var dialogflowRequest = ParseProtobufRequest<WebhookRequest>();
...
var jsonResponse = dialogflowResponse.ToString();
return new ContentResult { Content = jsonResponse, ContentType = "application/json" }; ;
}
private T ParseProtobufRequest<T>() where T : Google.Protobuf.IMessage, new()
{
// parse ProtoBuf (not 'normal' json) with unknown fields, else it may not bind ProtoBuf correctly
// https://github.com/googleapis/google-cloud-dotnet/issues/2425 "ask the Protobuf code to parse the result"
string requestBody;
using (var reader = new StreamReader(HttpContext.Request.InputStream))
{
requestBody = reader.ReadToEnd();
}
var parser = new Google.Protobuf.JsonParser(JsonParser.Settings.Default.WithIgnoreUnknownFields(true));
var typedRequest = parser.Parse<T>(requestBody);
return typedRequest;
}
BTW: This 'ProtoBuf-json' is also the reason to use WebhookResponse.ToString() which in turn uses Google.Protobuf.JsonFormatter.ToDiagnosticString.
Microsoft's BotBuilder
Microsoft's BotBuilder packages and Visual Studio template.
I havent't used it yet, but expect approximately the same code?
Hand written proprietary code
A simple example of incoming request code (called an NLU-Response by Google) is provided by Madoka Chiyoda (Chomado) at Github. The incoming call is simply parsed to her DialogFlowResponseModel:
public static async Task<HttpResponseMessage> Run([...]HttpRequestMessage req, [...]CloudBlockBlob mp3Out, TraceWriter log)
...
var data = await req.Content.ReadAsAsync<Models.DialogFlowResponseModel>();
Gactions
If you plan to work without DialogFlow later on, please note that the interface for Gactions differs significantly from the interface with DialogFlow.
The json-parameters and return-values have some overlap, but nothing gaining you any programming time (probably loosing some time by starting 'over').
However, starting with DialogFlow may gain you some quick dialog-experience (e.g. question & answer design/prototyping).
And the DialogFlow-API does have a NuGet package, where the Gactions-interface does not have a NuGet-package just yet.

Why aren't server-side changes being reflected in my app?

I have a simple C# Windows UAP project that uses a HttpClient to call a PHP script on a web server. The script returns an XML document that contains some GUIDs (*.xml files with the extension omitted, leaving a GUID). My app then uses that data. If I make a change on the server, coincidently causing the PHP script to return different data, my app still uses the old data (to be exact, it does this until the app is restarted). If a call the script using a browser, the data appears how I expect it to, but the app doesn't do what it should with the data. It almost seems like the first response is being cached.
Here's an example:
Say I start with one file in the folder where my PHP script finds all *.xml files (eef8401a-b5cd-4da7-ad36-0fb7a8fa6c62.xml in this case).
The script should and does return:
<?xml version="1.0"?>
<eventlist>
<id>eef8401a-b5cd-4da7-ad36-0fb7a8fa6c62</id>
</eventlist>
When I run the app, its response is the same.
So far, all is working as it should.
However, say I add a new XML file in the folder (now eee8401a-b5cd-4da7-ad36-0fb7a8fa6c62.xml and eef8401a-b5cd-4da7-ad36-0fb7a8fa6c62.xml). The script returns just like I expect it to:
<?xml version="1.0"?>
<eventlist>
<id>eee8401a-b5cd-4da7-ad36-0fb7a8fa6c62</id>
<id>eef8401a-b5cd-4da7-ad36-0fb7a8fa6c62</id>
</eventlist>
The app's response this time is still the previous one (with only one id element).
This persists until the app restarts. After that, it works like it should--until I make another change in the folder.
Here's my PHP script:
<?php
header('Content-type: text/xml');
$handler = opendir('C:\path\to\folder\\');
$ids = '';
while (($file = readdir($handler)) !== FALSE) {
if (strpos($file, '.xml') !== FALSE) {
$ids .= '<id>'.str_replace('.xml', '', $file).'</id>';
}
}
closedir($handler);
exit('<eventlist>'.$ids.'</eventlist>');
?>
And my app's C# code:
public static async Task<string> ContactServer(ApiMethod m, IProgress<double[]> prog, params KeyValuePair<string, string>[] args) {
using (var client = new HttpClient()) {
var path = m.ToString().ToLower() + "/"; // in this case, is 'list/'.
//...
// other stuff, omitted for simplicity
//...
var fullUrl = "http://example.com/path/to/api/" + path; // in this case, is 'http://example.com/path/to/api/list/'.
var d = await client.GetAsync(new Uri(fullUrl));
var data = await d.Content.ReadAsStringAsync();
Debug.WriteLine(data);
return data;
}
}
Again, my PHP script works fine, but my app gets a different response than I do when I run the script in my browser manually.
Why is this happening?
Windows Runtime which provides the HTTPClient has a very aggressive webcaching strategy to save user's bandwidth. Unless your server explicitly sets a cache duration header, it will return all** requests with the same Uri directly from the cache without even contacting your server.
You can turn off this behaviour by:
Setting a cache duration header (cache-control: no-cache, etc.).
var request = (HttpWebRequest)WebRequest.Create(url.ToString());
if (request.Headers == null)
request.Headers = new WebHeaderCollection();
request.Headers.Add("Cache-Control", "no-cache");
Adding a random number to your requests query string.
string uri = "http://host.com/path?cache=" + Guid.NewGuid().ToString();
Or, as CodeCaster suggested, you could also avoid the caching by using the If-Modified-Since header
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
if (request.Headers == null)
request.Headers = new WebHeaderCollection();
// Make sure that you format time string according RFC.
request.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.UtcNow.ToString("r");
or you can add to every request the client makes with
httpClient.DefaultRequestHeaders.IfModifiedSince = DateTime.UtcNow.ToString("r");
Using Windows.Web.Http you could also use
var httpFilter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
httpFilter.CacheControl.ReadBehavior =
Windows.Web.Http.Filters.HttpCacheReadBehavior.MostRecent;
var httpClient = new Windows.Web.Http.HttpClient(httpFilter);
** I have said all requests, but I don't know if that is strictly correct, I will take a look and check and update here, though CodeCaster has suggested GET and HEAD only; I have certainly seen on GET, unsure about others off the top of my head

Can you use LiveSDK from Console Application?

I'm trying to make a console application which accesses my SkyDrive account, however I cannot figure out how to get the Live SDK working.
I'm running on Live SDK version 5.4 and this is the code I'm trying to run - the loginResult.Status is always "Unknown":
private static async Task<LiveConnectClient> ConnectToLive()
{
LiveAuthClient authClient = new LiveAuthClient("my live ID");
var loginResult = await authClient.IntializeAsync(new[] { "wl.basic" });
if (loginResult.Status == LiveConnectSessionStatus.Connected)
return new LiveConnectClient(loginResult.Session);
return null;
}
A few things I'm not certain about (since the SDK documentation is somewhat lackluster at best):
"My live ID" - is this just my e-mail address used for my personal Live account, or is it some sort of application specific ID that you have to create somewhere ?
Is InitializeAsync the proper method to call for authenticating ? All examples I've found mention a "LoginAsync", but that method is not available in the DLL.
Is it even possible to use the SDK outside of Windows Phone / Metro apps ?
I got the following code to work using a SkyDriveClient downloaded from http://skydriveapiclient.codeplex.com/releases/view/103081
static void Main(string[] args)
{
var client = new SkyDriveServiceClient();
client.LogOn("YourEmail#hotmail.com", "password");
WebFolderInfo wfInfo = new WebFolderInfo();
WebFolderInfo[] wfInfoArray = client.ListRootWebFolders();
wfInfo = wfInfoArray[0];
client.Timeout = 1000000000;
string fn = #"test.txt";
if (File.Exists(fn))
{
client.UploadWebFile(fn, wfInfo);
}
}

How to access WinRM in C#

I'd like to create a small application that can collect system information (Win32_blablabla) using WinRM as opposed to WMI. How can i do that from C#?
The main goal is to use WS-Man (WinRm) as opposed to DCOM (WMI).
I guess the easiest way would be to use WSMAN automation. Reference wsmauto.dll from windwos\system32 in your project:
then, code below should work for you. API description is here: msdn: WinRM C++ API
IWSMan wsman = new WSManClass();
IWSManConnectionOptions options = (IWSManConnectionOptions)wsman.CreateConnectionOptions();
if (options != null)
{
try
{
// options.UserName = ???;
// options.Password = ???;
IWSManSession session = (IWSManSession)wsman.CreateSession("http://<your_server_name>/wsman", 0, options);
if (session != null)
{
try
{
// retrieve the Win32_Service xml representation
var reply = session.Get("http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Service?Name=winmgmt", 0);
// parse xml and dump service name and description
var doc = new XmlDocument();
doc.LoadXml(reply);
foreach (var elementName in new string[] { "p:Caption", "p:Description" })
{
var node = doc.GetElementsByTagName(elementName)[0];
if (node != null) Console.WriteLine(node.InnerText);
}
}
finally
{
Marshal.ReleaseComObject(session);
}
}
}
finally
{
Marshal.ReleaseComObject(options);
}
}
hope this helps, regards
I've got an article that describes an easy way to run Powershell through WinRM from .NET at http://getthinktank.com/2015/06/22/naos-winrm-windows-remote-management-through-net/.
The code is in a single file if you want to just copy it and it's also a NuGet package that includes the reference to System.Management.Automation.
It auto manages trusted hosts, can run script blocks, and also send files (which isn't really supported but I created a work around). The returns are always the raw objects from Powershell.
// this is the entrypoint to interact with the system (interfaced for testing).
var machineManager = new MachineManager(
"10.0.0.1",
"Administrator",
MachineManager.ConvertStringToSecureString("xxx"),
true);
// will perform a user initiated reboot.
machineManager.Reboot();
// can run random script blocks WITH parameters.
var fileObjects = machineManager.RunScript(
"{ param($path) ls $path }",
new[] { #"C:\PathToList" });
// can transfer files to the remote server (over WinRM's protocol!).
var localFilePath = #"D:\Temp\BigFileLocal.nupkg";
var fileBytes = File.ReadAllBytes(localFilePath);
var remoteFilePath = #"D:\Temp\BigFileRemote.nupkg";
machineManager.SendFile(remoteFilePath, fileBytes);
Hope this helps, I've been using this for a while with my automated deployments. Please leave comments if you find issues.
I would like to note that this shows an interop error by default in Visual Studio 2010.
c.f. http://blogs.msdn.com/b/mshneer/archive/2009/12/07/interop-type-xxx-cannot-be-embedded-use-the-applicable-interface-instead.aspx
There appear to be two ways to solve this. This first is documented in the article listed above and appears to be the correct way to handle the problem. The pertinent changes for this example is:
WSMan wsManObject = new WSMan();
This is in lieu of IWSMan wsman = new WSManClass(); which will throw the error.
The second resolution is to go to the VS2010—>Solution Explorer—>Solution—>Project—>References and select WSManAutomation. Right click or hit Alt-Enter to access the properties. Change the value of the "Embed Interop Types" property of the wsmauto reference.

Categories