I have a Silverlight 5 app, that makes use of a WCF service. The proxy client that has been generated has only asychronous methods (by default, when generating from the SL client).
I want to make use of the Task-based Asynchronous Pattern (TAP), now within VS2012RC.
What is the best approach to consume the async methods from the generated client proxy ?
(the issue is, that the WCF proxy generator creates code that is based on the Event-based Asynchronous Pattern (EAP) and not TAP....)
Based on this document:
http://www.microsoft.com/en-us/download/details.aspx?id=19957
I have found a solution for this.
See code below:
public class MyDataListProvider : IMyDataListProvider
{
private <ObservableCollection<IMyData>> myDataList;
public Task<ObservableCollection<IMyData>> GetMyData()
{
TaskCompletionSource<ObservableCollection<IMyData>> taskCompletionSource = new TaskCompletionSource<ObservableCollection<IMyData>>();
MyWCFClientProxy client = new MyWCFClientProxy();
this.myDataList.Clear();
client.GetMyDataCompleted += (o, e) =>
{
if (e.Error != null)
{
taskCompletionSource.TrySetException(e.Error);
}
else
{
if (e.Cancelled)
{
taskCompletionSource.TrySetCanceled();
}
else
{
foreach (var s in e.Result)
{
var item = new MyData();
item.Name = s.Name;
item.Fullname = s.Fullname;
this.myDataList.Add(item);
}
taskCompletionSource.TrySetResult(this.myDataList);
}
}
};
client.GetMyDataAsync();
return taskCompletionSource.Task;
}
}
Client SL code:
private async void SetMyDataList()
{
this.MyDataList = await this.myDataListProvider.GetMyData();
}
I don't know if it was available in the RC, however as of the SDK 8.0A (the one included with VS2012) svcutil.exe will generate async methods using the TAP pattern.
It will use TAP by default so be sure to NOT include /async as that will make it fall back to the old APM method of generating the methods.
You can see if the version of svcutil is new enough to use the TAP by looking at the first lines of the program it will include that it is at least version 4.0 of the tool.
Microsoft (R) Service Model Metadata Tool [Microsoft (R) Windows (R)
Communication Foundation, Version 4.0.xxxxx.xxxxxx]
Related
I'm trying to send an activity through DirectLineClient library to my bot :
var directLineClient = new DirectLineClient($"{secret}");
directLineClient.BaseUri = new Uri($"https://directline.botframework.com/");
var conversation = await directLineClient.Conversations.StartConversationAsync().ConfigureAwait(false);
var activity = new Microsoft.Bot.Connector.DirectLine.Activity();
activity.From = new Microsoft.Bot.Connector.DirectLine.ChannelAccount();
activity.From.Name = "Morgan";
activity.Text = message;
activity.Type = "message";
var resourceResponse = await directLineClient.Conversations.PostActivityAsync(conversation.ConversationId, activity).ConfigureAwait(false);
await ReadBotMessagesAsync(directLineClient, conversation.ConversationId);
resourceResponse is always null.
Edit after Nicolas R answer
I added a method to wait for a response from the bot :
private static async Task ReadBotMessagesAsync(DirectLineClient client, string conversationId)
{
string watermark = null;
while (true)
{
var activitySet = await client.Conversations.GetActivitiesAsync(conversationId, watermark);
watermark = activitySet?.Watermark;
foreach (Microsoft.Bot.Connector.DirectLine.Activity activity in activitySet.Activities)
{
Console.WriteLine(activity.Text);
if (activity.Attachments != null)
{
foreach (Microsoft.Bot.Connector.DirectLine.Attachment attachment in activity.Attachments)
{
Console.WriteLine(attachment.ContentType);
}
}
}
if (activitySet.Activities.Count > 0)
{
return;
}
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
}
}
But I never get out of ReadBotMessagesAsync.
I precise that I can communicate with my bot through HTTP request (tested with Postman), and it should be sending a response message whenever a message is sent.
Edited after OP precision
Methods always returns null
Based on the documentation/samples, it looks like this PostActivityAsync return is never used so the value may not be relevant.
From the samples:
await client.Conversations.PostActivityAsync(conversation.ConversationId, userMessage);
See example here.
For those who want more details, because this answer is only limited to the comparison with the sample use, this package is sadly not open-source: https://github.com/Microsoft/BotBuilder/issues/2756
Remarks (for those who would be using the wrong packages)
I would not recommend to use this DirectLineClient Nuget package located here:
https://www.nuget.org/packages/DirectLineClient as it is not maintained since May 2016 and the Bot Framework has changed a lot since that time.
Moreover, it is using DirectLine API 1.0, which is not the best practice at the time. See documentation here:
Important
This article introduces key concepts in Direct Line API 1.1 and
provides information about relevant developer resources. If you are
creating a new connection between your client application and bot, use
Direct Line API 3.0 instead.
I'm trying to add custom headers to the HTTP requsets a SPARQL endpoint connector issues. The connector can use a custom remote endpoint, which inherits an ApplyCustomRequestOptions method I can override. Documentation for that method says
[...] add any additional custom request options/headers to the request.
However my overridden method is never called (so my custom options are not applied, so I can't add the headers).
The following code works as expected, except that my ApplyCustomRequestOptions is never invoked:
using System;
using System.Net;
using VDS.RDF.Query;
using VDS.RDF.Storage;
class Program
{
static void Main(string[] args)
{
var endpointUri = new Uri("https://query.wikidata.org/sparql");
var endpoint = new CustomEndpoint(endpointUri);
using (var connector = new SparqlConnector(endpoint))
{
var result = connector.Query("SELECT * WHERE {?s ?p ?o} LIMIT 1");
}
}
}
public class CustomEndpoint : SparqlRemoteEndpoint
{
public CustomEndpoint(Uri endpointUri) : base(endpointUri) { }
protected override void ApplyCustomRequestOptions(HttpWebRequest httpRequest)
{
// This is never executed.
base.ApplyCustomRequestOptions(httpRequest);
// Implementation omitted.
}
}
Is this the correct way to use these methods? If it isn't, what is it?
BTW this is dotNetRdf 1.0.12, .NET 4.6.1. I've tried multiple SPARQL endpoints, multiple queries (SELECT & CONSTRUCT) and multiple invocations of SparqlConnector.Query.
This is a bug. I've found the problem and fixed it and submitted a PR. You can track the status of the issue here: https://github.com/dotnetrdf/dotnetrdf/issues/103
I'm currently using SignalR to communicate between a server and multiple separate processes spawned by the server itself.
Both Server & Client are coded in C#. I'm using SignalR 2.2.0.0
On the server side, I use OWIN to run the server.
I am also using LightInject as an IoC container.
Here is my code:
public class AgentManagementStartup
{
public void ConfigurationOwin(IAppBuilder app, IAgentManagerDataStore dataStore)
{
var serializer = new JsonSerializer
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
TypeNameHandling = TypeNameHandling.Auto,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
};
var container = new ServiceContainer();
container.RegisterInstance(dataStore);
container.RegisterInstance(serializer);
container.Register<EventHub>();
container.Register<ManagementHub>();
var config = container.EnableSignalR();
app.MapSignalR("", config);
}
}
On the client side, I register this way:
public async Task Connect()
{
try
{
m_hubConnection = new HubConnection(m_serverUrl, false);
m_hubConnection.Closed += OnConnectionClosed;
m_hubConnection.TraceLevel = TraceLevels.All;
m_hubConnection.TraceWriter = Console.Out;
var serializer = m_hubConnection.JsonSerializer;
serializer.TypeNameHandling = TypeNameHandling.Auto;
serializer.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
m_managementHubProxy = m_hubConnection.CreateHubProxy(AgentConstants.ManagementHub.Name);
m_managementHubProxy.On("closeRequested", CloseRequestedCallback);
await m_hubConnection.Start();
}
catch (Exception e)
{
m_logger.Error("Exception encountered in Connect method", e);
}
}
On the server side I send a close request the following way:
var managementHub = GlobalHost.ConnectionManager.GetHubContext<ManagementHub>();
managementHub.Clients.All.closeRequested();
I never receive any callback in CloseRequestedCallback. Neither on the Client side nor on the server side I get any errors in the logs.
What did I do wrong here ?
EDIT 09/10/15
After some research and modifications, I found out it was linked with the replacement of the IoC container. When I removed everything linked to LightInject and used SignalR as is, everything worked. I was surprised about this since LightInject documented their integration with SignalR.
After I found this, I realised that the GlobalHost.DependencyResolver was not the same as the one I was supplying to the HubConfiguration. Once I added
GlobalHost.DependencyResolver = config.Resolver;
before
app.MapSignalR("", config);
I am now receiving callbacks within CloseRequestedCallback. Unfortunately, I get the following error as soon as I call a method from the Client to the Server:
Microsoft.AspNet.SignalR.Client.Infrastructure.SlowCallbackException
Possible deadlock detected. A callback registered with "HubProxy.On"
or "Connection.Received" has been executing for at least 10 seconds.
I am not sure about the fix I found and what impact it could have on the system. Is it OK to replace the GlobalHost.DependencyResolver with my own without registering all of its default content ?
EDIT 2 09/10/15
According to this, changing the GlobalHost.DependencyResolver is the right thing to do. Still left with no explanation for the SlowCallbackException since I do nothing in all my callbacks (yet).
Issue 1: IoC Container + Dependency Injection
If you want to change the IoC for you HubConfiguration, you also need to change the one from the GlobalHost so that returns the same hub when requesting it ouside of context.
Issue 2: Unexpected SlowCallbackException
This exception was caused by the fact that I was using SignalR within a Console Application. The entry point of the app cannot be an async method so to be able to call my initial configuration asynchronously I did as follow:
private static int Main()
{
var t = InitAsync();
t.Wait();
return t.Result;
}
Unfortunately for me, this causes a lot of issues as described here & more in details here.
By starting my InitAsync as follow:
private static int Main()
{
Task.Factory.StartNew(async ()=> await InitAsync());
m_waitInitCompletedRequest.WaitOne(TimeSpan.FromSeconds(30));
return (int)EndpointErrorCode.Ended;
}
Everything now runs fine and I don't get any deadlocks.
For more details on the issues & answers, you may also refer to the edits in my question.
I am new here and I hope that i will find a solution for my problem. The background of the problem is as follows:
I am trying to build an expert system that constitute a C# front-end which is interacting with Swi-prolog.
I have downloaded SwiPlCs.dll (A CSharp class library to connect .NET languages with Swi-Prolog)
And added a reference to it in a Visual Studio project(Win form app) that I have created to test if I can query prolog from c# (I followed the example used in the documentation found here).
It worked fine.
Then, in a more complicated scenario, I have built a WCF service that will act as an intermediary layer between Swi-Prolog and C# client application (it consumes the service).
The service is hosted in IIS 7.0.
For the sake of simplicity, lets say my service contains three methods.
The first method initializes the prolog engine, consults prolog source file then queries the file.
The second method performs another query.
The third method calls PlCleanup().
Method#1:
public void LaunchAssessment()
{
Dictionary<string, string> questions = new Dictionary<string, string>();
#region : Querying prolog using SwiPlCs
try
{
if (!PlEngine.IsInitialized)
{
String[] param = { "-q" };
PlEngine.Initialize(param);
PlQuery.PlCall("consult('D:/My FYP Work/initialAssessment')");
using (var q = new PlQuery("go(X, Y)"))
{
foreach (PlQueryVariables v in q.SolutionVariables)
{
questions.Add("name", v["X"].ToString());
questions.Add("age", v["Y"].ToString());
}
}
}
}
catch (SbsSW.SwiPlCs.Exceptions.PlException exp)
{
throw new FaultException<PrologFault>(new PrologFault(exp.Source), exp.MessagePl);
}
#endregion
Callback.PoseQuestion(questions, ResponseType.None);
}
Method#2:
public void DetermineAgeGroup(int age)
{
//Determine age group
string age_group = string.Empty;
try
{
using (var query = new PlQuery("age_group(" + age + ", G)"))
{
foreach (PlQueryVariables v in query.SolutionVariables)
age_group += v["G"].ToString();
}
}
catch (SbsSW.SwiPlCs.Exceptions.PlException exp)
{
throw new FaultException<PrologFault>(new PrologFault(exp.Source), exp.MessagePl);
}
//Check whether age_group is found or not
if (string.IsNullOrEmpty(age_group))
{
throw new FaultException<NoSolutionFoundFault>(new NoSolutionFoundFault("No solution found"), "Age specified exceeds the diagnosis range!");
}
else
{
Callback.RespondToUser(age_group, ResponseType.Age);
}
}
Method#3:
public void QuitProlog()
{
if (PlEngine.IsInitialized)
{
PlEngine.PlCleanup();
}
}
The client invokes the first method just fine and a result of the first query is successfully returned. When client tries to call the second method an exception is thrown with message (attempted to read or write protected memory) which causes the application to freeze. I checked the event viewer and this is what I get:
Application: w3wp.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
Stack:
at SbsSW.SwiPlCs.SafeNativeMethods.PL_new_term_ref()
at SbsSW.SwiPlCs.PlQuery..ctor(System.String, System.String)
at SbsSW.SwiPlCs.PlQuery..ctor(System.String)
at PrologQueryService.PrologQueryService.DetermineAgeGroup(Int32)
I also tried to use the interface for a .NET project.
Looking in the official repository of the CSharp interface to SWI-Prolog I noticed that the project is very old and the latest updates do not seem included in the binaries available in the download page of the official website.
Then I did the following steps:
The contrib repository dedicated to .NET indicates that the compatible SWI-Prolog version (at the time of writing) is "8.0.3-1" (look in the README file).
-> Then I uninstalled from my computer the latest stable and installed the indicated one. I got it from the full list of downloads of the old versions at this link.
I cloned the SWI-Prolog/contrib-swiplcs repository, unloaded the incompatible projects from the solution, in my case, since I don't use Visual Studio.
-> I set the target framework to Net Framework 4.8 and recompiled it (you can also do this with standard NET). Beware of some pragma directives defined in the old project file (For example I re-defined _PL_X64 variable via code.
I brought the main unit test methods into a new project with xUnit wiht the appropriate changes.
I set the target to x64, recompiled and rebuilt the tests and the "hello world" example.
It worked!
I was able to use SWI-Prolog both for Net 4.8 and in other Net Core applications (if you make the needed changes in order to target the Net Standard). You should not have any problem in both cases).
This is my fork as a preliminary example.
Finally, I can load a *.pl Prolog file with a program in my C# application and use it to evaluate some business logic rules (example with boolean answer [Permitted/Not-Permitted]):
[Fact]
public void ShouldLoadAProgramAndUseIt()
{
var pathValues = Environment.GetEnvironmentVariable("PATH");
pathValues += #";C:\Program Files\swipl\bin";
Environment.SetEnvironmentVariable("PATH", pathValues);
// Positioning to project folder
var currentDirectory = Directory.GetCurrentDirectory().Split('\\').ToList();
currentDirectory.RemoveAll(r => currentDirectory.ToArray().Reverse().Take(3).Contains(r));
var basePath = currentDirectory.Aggregate((c1, c2) => $"{c1}\\{c2}");
var filePath = $"{basePath}\\prolog_examples\\exec_checker.pl";
String[] param = { "-q", "-f", filePath };
PlEngine.Initialize(param);
try
{
var query = "exutable('2020-08-15',[('monthly', ['2019-12-30', '2020-03-10'])])";
_testOutputHelper.WriteLine($"Query: {query}");
using (var q = new PlQuery(query))
{
var booleanAnswer = q.NextSolution();
_testOutputHelper.WriteLine($"Answer: {booleanAnswer}");
Assert.True(booleanAnswer);
}
query = "exutable('2020-08-15',[('daily', ['2019-12-30', '2020-08-15'])])";
_testOutputHelper.WriteLine($"Query: {query}");
using (var q = new PlQuery(query))
{
var booleanAnswer = q.NextSolution();
_testOutputHelper.WriteLine($"Answer: {booleanAnswer}");
Assert.False(booleanAnswer);
}
}
finally
{
PlEngine.PlCleanup();
}
}
Try to close engine in the end of the first method and initialize it in the second again.
You can check this as the answer to the question unless you object.
I was wondering if there are any SWF workflow C# sample code available for the AWS .NET SDK?
AWS Forum Post: https://forums.aws.amazon.com/thread.jspa?threadID=122216&tstart=0
As part of getting familiar with SWF, I ended up writing a common case library that I hope others can use as well. It's called SimpleWorkflowFramework.NET and is available as open source at https://github.com/sdebnath/SimpleWorkflowFramework.NET. It definitely could use a lot of help, so if you are interested, jump right in! :)
I have developed an open source .NET library- Guflow to program Amazon SWF. Here is how you can write a workflow to transcode the video:
[WorkflowDescription("1.0")]
public class TranscodeWorkflow : Workflow
{
public TranscodeWorkflow()
{
//DownloadActivity is the startup activity and will be scheduled when workflow is started.
ScheduleActivity<DownloadActivity>().OnFailure(Reschedule);
//After DownloadActivity is completed TranscodeActivity activity will be scheduled.
ScheduleActivity<TranscodeActivity>().AfterActivity<DownloadActivity>()
.WithInput(a => new {InputFile = ParentResult(a).DownloadedFile, Format = "MP4"})
ScheduleActivity<UploadToS3Activity>().AfterActivity<TranscodeActivity>()
.WithInput(a => new {InputFile = ParentResult(a).TranscodedFile});
ScheduleActivity<SendConfirmationActivity>().AfterActivity<UploadToS3Activity>();
}
private static dynamic ParentResult(IActivityItem a) => a.ParentActivity().Result();
}
In above example I have left out task routing for clarity.
Here is how you can create an activity:
[ActivityDescription("1.0")]
public class DownloadActivity : Activity
{
//It supports both sync/async method.
[ActivityMethod]
public async Task<Response> Execute(string input)
{
//simulate downloading of file
await Task.Delay(10);
return new Response() { DownloadedFile = "downloaded path", PollingQueue = PollingQueue.Download};
}
public class Response
{
public string DownloadedFile;
}
}
For clarity I'm leaving out examples of other activities. Guflow it supported by documentation, tutorial and samples.