Microsoft Bot Framework works locally, but fails remotely - c#

I have this bot that is fairly complicated, but it works locally. But as soon as I publish it, it fails with the error:
Sorry, my bot code is having an issue.
I have tried using Application Insights, but it isn't showing the error details.
The error always happens at the same point:
/// <summary>
/// Start our response
/// </summary>
/// <param name="context">The current context</param>
/// <returns></returns>
public async Task StartAsync(IDialogContext context)
{
// Get our current step
_groups = await _groupProvider.ListAsync();
_group = _groups.First();
// Post the question header
await context.PostAsync(_group.Text);
// Wait for the users response
context.Wait(AskQuestion);
}
/// <summary>
/// When our message is recieved we execute this delegate
/// </summary>
/// <param name="context">The current context</param>
/// <param name="result">The result object</param>
/// <returns></returns>
private async Task AskQuestion(IDialogContext context, IAwaitable<IMessageActivity> result)
{
// Get our question and answers
var question = this._group.Questions[_currentQuestion];
var questionText = question.Text;
var answers = question.Answers.Select(m => m.Text).ToList();
var answerCount = question.Answers.Count;
// Create our options
var options = new PromptOptions<string>(questionText, options: answers);
// Ask our question
Choice<string>(context, GetAnswer, options);
}
/// <summary>
/// Get our answer and decide what to do next
/// </summary>
/// <param name="context">The current context</param>
/// <param name="result">The answer text</param>
/// <returns></returns>
private async Task GetAnswer(IDialogContext context, IAwaitable<string> result)
{
// Get our quest
var questions = _group.Questions;
var length = questions.Count;
var question = _group.Questions[_currentQuestion];
var selectedAnswer = await result;
// Assign our answer to our question
foreach (var answer in question.Answers)
if (answer.Text == selectedAnswer)
question.Answer = answer;
// If we have an answer, filter the products
if (question.Answer != null)
_productProvider.Score(await GetCurrentProducts(), _groups);
// Increase our index
_currentQuestion++;
// If our current index is greater or equal than the length of the questions
if (_currentQuestion == length)
{
// Create our dialog
var dialog = _dialogFactory.CreateSecondStepDialog(_dialogFactory, _groupProvider, _questionProvider, _productProvider, await GetCurrentProducts());
// Otherwise, got to the next step
await context.Forward(dialog, ResumeAfter, new Activity { }, CancellationToken.None);
return;
}
// Ask our next question
await AskQuestion(context, null);
}
So when this dialog starts, it posts the question introduction to the client.
I then invoke context.Wait and ask the question. The question is a choice. I believe that this is where the issue is, because it always throws that message as soon as the question appears.
Can anyone spot anything glaringly obvious with the code?

The error message you have cited, is given when your bot throws a 500. Looking at your code, my guess is that you have a null ref exception. In the section under "// Get our question and answers", try checking that group.Questions isn't null and that _currentQuestion is a valid index into that array.

Related

What does the operationTimeout in ISessionClient.AcceptMessageSessionAsync actually do?

Context: I have some code that's creating a message session for a particular session, using
ISessionClient.Task<IMessageSession> AcceptMessageSessionAsync(string sessionId, TimeSpan operationTimeout);
Question: What does the operationTimeout in AcceptMessageSessionAsync do? I tried setting it to one minute but, after a minute, nothing happened. Does this timeout just set a property that I need to check myself? Shouldn't a SessionLockLostException fire?
Code Sample:
var session = await sessionClient.AcceptMessageSessionAsync(0, TimeSpan.FromMinutes(1));
var gotSession = true;
if (gotSession)
{
while (!session.IsClosedOrClosing)
{
try
{
Message message = await session.ReceiveAsync(TimeSpan.FromMinutes(2));
if (message != null)
{
await session.CompleteAsync(message.SystemProperties.LockToken);
}
else
{
await session.CloseAsync();
}
}
}
}
OperationTimeout in AcceptMessageSessionAsync is the amount of time for which the call should wait for to fetch the next session.
You can find the Here is the complete implementation of the AcceptMessageSessionAsync method
/// <summary>
/// Gets a particular session object identified by <paramref name="sessionId"/> that can be used to receive messages for that sessionId.
/// </summary>
/// <param name="sessionId">The sessionId present in all its messages.</param>
/// <param name="operationTimeout">Amount of time for which the call should wait to fetch the next session.</param>
/// <remarks>All plugins registered on <see cref="SessionClient"/> will be applied to each <see cref="MessageSession"/> that is accepted.
/// Individual sessions can further register additional plugins.</remarks>
public async Task<IMessageSession> AcceptMessageSessionAsync(string sessionId, TimeSpan operationTimeout)
{
this.ThrowIfClosed();
MessagingEventSource.Log.AmqpSessionClientAcceptMessageSessionStart(
this.ClientId,
this.EntityPath,
this.ReceiveMode,
this.PrefetchCount,
sessionId);
bool isDiagnosticSourceEnabled = ServiceBusDiagnosticSource.IsEnabled();
Activity activity = isDiagnosticSourceEnabled ? this.diagnosticSource.AcceptMessageSessionStart(sessionId) : null;
Task acceptMessageSessionTask = null;
var session = new MessageSession(
this.EntityPath,
this.EntityType,
this.ReceiveMode,
this.ServiceBusConnection,
this.CbsTokenProvider,
this.RetryPolicy,
this.PrefetchCount,
sessionId,
true);
try
{
acceptMessageSessionTask = this.RetryPolicy.RunOperation(
() => session.GetSessionReceiverLinkAsync(operationTimeout),
operationTimeout);
await acceptMessageSessionTask.ConfigureAwait(false);
}
catch (Exception exception)
{
if (isDiagnosticSourceEnabled)
{
this.diagnosticSource.ReportException(exception);
}
MessagingEventSource.Log.AmqpSessionClientAcceptMessageSessionException(
this.ClientId,
this.EntityPath,
exception);
await session.CloseAsync().ConfigureAwait(false);
throw AmqpExceptionHelper.GetClientException(exception);
}
finally
{
this.diagnosticSource.AcceptMessageSessionStop(activity, session.SessionId, acceptMessageSessionTask?.Status);
}
MessagingEventSource.Log.AmqpSessionClientAcceptMessageSessionStop(
this.ClientId,
this.EntityPath,
session.SessionIdInternal);
session.UpdateClientId(ClientEntity.GenerateClientId(nameof(MessageSession), $"{this.EntityPath}_{session.SessionId}"));
// Register plugins on the message session.
foreach (var serviceBusPlugin in this.RegisteredPlugins)
{
session.RegisterPlugin(serviceBusPlugin);
}
return session;
}
You can find the complete sample in below link
https://github.com/Azure/azure-service-bus-dotnet/blob/dev/src/Microsoft.Azure.ServiceBus/SessionClient.cs
Hope it helps.

How to get a list of all forks of a GitHub repo?

I would like to get a list of all forks of a GitHub repo (e.g. https://github.com/eternicode/bootstrap-datepicker), however I am unable to find out how to do it using octokit.net.
I want also get a renamed repositories, I could not just search a name of a repository.
Any hints?
CLARIFICATION: The rest api is described here https://developer.github.com/v3/repos/forks/, but how to do it with octokit.net?
You can achieve that by visiting:
https://api.github.com/repos/<Author>/<Repo>/forks
Make sure to replace Author and Repo with suitable values.
The functionality has been added to octokit.net recently:
https://github.com/octokit/octokit.net/blob/b07ce6e11a1b286dda0a65ee427bda3b8abcefb8/Octokit.Reactive/Clients/ObservableRepositoryForksClient.cs#L31
/// <summary>
/// Gets the list of forks defined for a repository
/// </summary>
/// <remarks>
/// See API documentation for more information.
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
public IObservable<Repository> GetAll(string owner, string name)
{
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Ensure.ArgumentNotNullOrEmptyString(name, "name");
return GetAll(owner, name, ApiOptions.None);
}
Similar functions exist for other ways to specify repository.
Please feel free to edit in the full code for this use case here.
Threads a bit old but in case someone else ends up here from google thought Id necro it.
private static IReadOnlyList<Octokit.Repository> retrieveGitHubRepos()
{
Task<IReadOnlyList<Octokit.Repository>> getRepoList = null;
string appname = System.AppDomain.CurrentDomain.FriendlyName;
Octokit.GitHubClient client = new Octokit.GitHubClient(new Octokit.ProductHeaderValue(ConnectionDetails.appName));
client.Credentials = new Octokit.Credentials(ConnectionDetails.username, ConnectionDetails.password);
Task.Run(() => getRepoList = client.Repository.GetAllForUser(ConnectionDetails.username)).Wait();
return getRepoList.Result;
}

mocking testing merge of cells in excel

I have class working with excel worksheet.
How to you write test to prove that Merge method gets called.
/// <summary>
/// Merges the cells together.
/// </summary>
/// <param name="ws">The worksheet.</param>
/// <param name="cellsToMerge">The cells to merge.</param>
/// <exception cref="System.ArgumentNullException">ws;Worksheet has to be defined</exception>
/// <exception cref="System.ArgumentException">Cells cannot contain null or empty string;cellsToMerge</exception>
public void MergeCellsTogether(Worksheet ws, string cellsToMerge)
{
if(ws==null) throw new ArgumentNullException("ws","Worksheet has to be defined");
if(string.IsNullOrEmpty(cellsToMerge))throw new ArgumentException("Cells cannot contain null or empty string", "cellsToMerge");
var cells = ws.Cells[cellsToMerge]; // failing to setup
ws.Range[cells].Merge();
}
now my test is using MOQ
[TestMethod]
public void TestForMergingCellsTogether()
{
// assign
var cellsToMerge = "A1:C3";
// mock
var ws = new Mock<Worksheet>();
var range = new Mock<Range>();
ws.Setup(x => x.get_Range(It.IsAny<object>(), It.IsAny<object>())).Returns(range.Object);
// this is part that is giving my headake
ws.Setup(x => x.Cells[It.IsAny<object>(),It.IsAny<object>()]).Returns(range.Object);
range.Setup(x => x.Merge(It.IsAny<object>()));
// act
var ps = new RenderProcess("fileName");
ps.MergeCellsTogether(ws.Object, cellsToMerge);
// assert
range.VerifyAll();
}
I have found solution to my question.
My approach was incorrect.
My updated(simplified) code
/// <summary>
/// Merges the cells together.
/// </summary>
/// <param name="worksheet">The worksheet.</param>
/// <param name="cellsToMerge">The cells to merge.</param>
/// <exception cref="System.ArgumentNullException">ws;Worksheet has to be defined</exception>
/// <exception cref="System.ArgumentException">Cells cannot contain null or empty string;cellsToMerge</exception>
public void MergeCellsTogether(Worksheet worksheet, string cellsToMerge)
{
if(worksheet==null) throw new ArgumentNullException("worksheet","Worksheet has to be defined");
if(string.IsNullOrEmpty(cellsToMerge))throw new ArgumentException("Cells cannot contain null or empty string", "cellsToMerge");
worksheet.Range[cellsToMerge].Merge();
}
And my tests method:
// assign
var cellsToMerge = "A1:C3";
// mock
var ws = new Mock<Worksheet>();
var range = new Mock<Range>();
ws.Setup(x => x.get_Range(It.IsAny<object>(), It.IsAny<object>())).Returns(range.Object);
range.Setup(x => x.Merge(It.IsAny<object>()));
// act
var process = new RenderExcel();
process.CreateExcelWorkSheet("fileName");
process.MergeCellsTogether((Worksheet)ws.Object, cellsToMerge);
// assert
range.VerifyAll();

XML-Documentation of multiple exceptions for C#

I'm actually searching for a guidline, how to document multiple exceptions in a public method inside a C#-DLL.
example:
/// <summary>
/// This method does something
/// </summary>
/// <param name="p_Parameter1">First parameter</param>
/// <param name="p_Parameter2">Second parameter</param>
/// <param name="p_Number">A number</param>
/// <exception cref="ArgumentNullException">
/// Thrown if p_Parameter1 is null</exception>
/// <exception cref="ArgumentNullException">
/// Thrown if p_Parameter2 is null</exception>
/// <exception cref="ArgumentNullException">
/// Thrown if any element of p_Parameter2 is null</exception>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if p_Number is below or equal 0</exception>
/// <returns>A object</returns>
public static object DoSomething(
object p_Parameter1, IList<object> p_Parameter2,
object p_Parameter3, int p_Number)
{
if(p_Parameter1 == null)
throw new ArgumentNullException(
paramName:"p_Parameter1",
message:"Parameter is needed");
if (p_Parameter2 == null)
throw new ArgumentNullException(
paramName: "p_Parameter2",
message: "Parameter is needed");
for (int i = 0; i < p_Parameter2.Count; i++)
{
if(p_Parameter2[i] == null)
throw new ArgumentNullException(
paramName: String.Format("p_Parameter2[{0}]", i),
message: "All elements have to be initialized");
}
if(p_Number < 0)
throw new ArgumentOutOfRangeException(
paramName: "p_Number",
message: "Parameter should be bigger then zero");
var returnValue = new object();
// do something where p_Parameter3 == null is allowed
return returnValue;
}
Is it the right way to document those exceptions? Should I add one exception-tag for each case, or should I add only one for all Parameters for which null-values ar not allowed?
/// <exception cref="ArgumentNullException">
/// Thrown if p_Parameter1, p_Parameter2
/// or any element of p_Parameter2 are null</exception>
I would definitely group the exceptions by type, ie Thrown if p_Parameter1, p_Parameter2
or any element of p_Parameter2 are null.
As a reference, look at the documentation at MSDN. An example:
ArgumentNullException | Either path, contents, or encoding is null.
MSDN is a good source to emulate in this case, and taking a survey of a few functions there it looks like they tend to use one exception block and enumerate the different parameters inside of it.
Doing it this way makes it easier for consumers of your code to know what exceptions to possibly catch because seeing a list of distinct exceptions is easier to grok than a list that contains duplicates.

Retry the request if the first one failed

I am using a xml web service on my web app and sometimes remote server fails to respond in time. I came up with the idea of re-request if first attempt fails. To prevent loop I want to limit concurrent request at 2. I want to get an opinion if what I have done below is ok and would work as I expect it.
public class ScEngine
{
private int _attemptcount = 0;
public int attemptcount
{
get
{
return _attemptcount;
}
set
{
_attemptcount = value;
}
}
public DataSet GetStat(string q, string job)
{
try
{
//snip....
attemptcount += attemptcount;
return ds;
}
catch
{
if (attemptcount>=2)
{
return null;
}
else
{
return GetStat(q, job);
}
}
}
}
public class ScEngine
{
public DataSet GetStat(string q, string job)
{
int attemptCount;
while(attemptCount < 2)
{
try
{
attemptCount++;
var ds = ...//web service call
return ds;
}
catch {}
}
//log the error
return null;
}
}
You forgot to increment the attemptcount. Plus, if there's any error on the second run, it will not be caught (thus, becomes an unhandled exception).
I wouldn't recurse in order to retry. Also, I wouldn't catch and ignore all exceptions. I'd learn which exceptions indicate an error that should be retried, and would catch those. You will be ignoring serious errors, as your code stands.
You don't want to solve it this way. You will just put more load on the servers and cause more timeouts.
You can increase the web service timeout via httpRuntime. Web services typically return a lot of data in one call, so I find myself doing this pretty frequently. Don't forget to increase how long the client is willing to wait on the client side.
Here's a version that doesn't use recursion but achieves the same result. It also includes a delay so you can give the server time to recover if it hiccups.
/// <summary>
/// The maximum amount of attempts to use before giving up on an update, delete or create
/// </summary>
private const int MAX_ATTEMPTS = 2;
/// <summary>
/// Attempts to execute the specified delegate with the specified arguments.
/// </summary>
/// <param name="operation">The operation to attempt.</param>
/// <param name="arguments">The arguments to provide to the operation.</param>
/// <returns>The result of the operation if there are any.</returns>
public static object attemptOperation(Delegate operation, params object[] arguments)
{
//attempt the operation using the default max attempts
return attemptOperation(MAX_ATTEMPTS, operation, arguments);
}
/// <summary>
/// Use for creating a random delay between retry attempts.
/// </summary>
private static Random random = new Random();
/// <summary>
/// Attempts to execute the specified delegate with the specified arguments.
/// </summary>
/// <param name="operation">The operation to attempt.</param>
/// <param name="arguments">The arguments to provide to the operation.</param>
/// <param name="maxAttempts">The number of times to attempt the operation before giving up.</param>
/// <returns>The result of the operation if there are any.</returns>
public static object attemptOperation(int maxAttempts, Delegate operation, params object [] arguments)
{
//set our initial attempt count
int attemptCount = 1;
//set the default result
object result = null;
//we've not succeeded yet
bool success = false;
//keep trying until we get a result
while (success == false)
{
try
{
//attempt the operation and get the result
result = operation.DynamicInvoke(arguments);
//we succeeded if there wasn't an exception
success = true;
}
catch
{
//if we've got to the max attempts and still have an error, give up an rethrow it
if (attemptCount++ == maxAttempts)
{
//propogate the exception
throw;
}
else
{
//create a random delay in milliseconds
int randomDelayMilliseconds = random.Next(1000, 5000);
//sleep for the specified amount of milliseconds
System.Threading.Thread.Sleep(randomDelayMilliseconds);
}
}
}
//return the result
return result;
}

Categories