0

Partially resolved, scroll down for the update...

I am trying to make simple call with Graph API; at the first try to just get channels in my team without the need of login manually by the user. So, looks like I need to use Ms Client ID and Client secret and some token. With my understanding I need to get the token from HTTP request (which is implemented in GraphAuthenticator.

The code that throws an exception (in func OnMessageActivityAsync):

var clientId = "<client id from app registration>";
var clientSecret = "<client secret value from app registration>";
GraphAuthenticator auth = new GraphAuthenticator(clientId, clientSecret);
var accessToken = auth.getAuthenticationToken();

var graphClient = new GraphClientService().GetAuthenticatedGraphClient(accessToken);
var team = graphClient.Teams["<my team id>"];
var channels = team.Channels;
var req = channels.Request();
^var reqTask = await req.GetAsync();
var resultList = new List<string>(reqTask.Count);

Second part has been divided to find exact null-reference (System.NullReferenceException thrown in the line with the declaration of reqTask), but looks like req is NOT a null, because I can read its members during debugging, like RequestUrl. GraphAuthenticator class simply make a HTTP request to obtain a token

var DATA = Encoding.ASCII.GetBytes($"grant_type=client_credentials&client_id={ MS_APP_ID_ENC }&client_secret={ MS_APP_PASS_ENC }&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default");
//HTTP request with successfully acquiring token...

GraphClientService comes from examples in GitHub provided by Ms (IGraphClientService has this one method only).

    public class GraphClientService : IGraphClientService {
    public GraphServiceClient GetAuthenticatedGraphClient(string accessToken) {
        return new GraphServiceClient(new DelegateAuthenticationProvider(
            async (request) => {
                request.Headers.Authorization =
                    new AuthenticationHeaderValue("Bearer", accessToken);
                await Task.CompletedTask;
            }
        ));
    }
}

I was trying to obtain maybe some data of user, even trying SimpleGraphClient - exactly as it is in the samples.

var user = await graphClient.Me.Request().Select(u => new {
                                                            u.DisplayName,
                                                            u.Mail,
                                                            u.UserPrincipalName
                                                        }).GetAsync();

But result was the same. Null reference exception. Am I missing something? I am sure about credentials, as Graph send me the token. Details of the exception:

Callstack:

This exception was originally thrown at this call stack:
Microsoft.Graph.HttpProvider.SendAsync(System.Net.Http.HttpRequestMessage, System.Net.Http.HttpCompletionOption, System.Threading.CancellationToken)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)
System.Runtime.CompilerServices.ConfiguredTaskAwaitable<TResult>.ConfiguredTaskAwaiter.GetResult()
Microsoft.Graph.BaseRequest.SendRequestAsync(object, System.Threading.CancellationToken, System.Net.Http.HttpCompletionOption)

Source: Microsoft.Graph.Core

StackTrace:

at Microsoft.Graph.HttpProvider.<SendAsync>d__18.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Graph.BaseRequest.<SendRequestAsync>d__35.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Graph.BaseRequest.<SendAsync>d__31`1.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Graph.TeamChannelsCollectionRequest.<GetAsync>d__4.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.BotBuilderSamples.BatchBot`1.<OnMessageActivityAsync>d__6.MoveNext() in G:\...cs:line 90

TargetSite: void MoveNext()

Looking into req variable I saw there is no header (count = 0). Shouldn't be there a authorization header visible?

============================ @EDIT I decided to continue this question, even though we know the root problem of the exception.

But when I am reading docs and other forums looks like problematic Graph request should throw an ServiceException. In my code it is other exception somewhere deep in Graph code, I could not get there, looks like NuGet package doesn't have symbols.

Is it possible to read error message sent by Graph and avoid this exception being thrown? Surrounding my code with try doesn't make any difference (it's an async method).

6
  • Which line in the code throws the exception? Did you debug the code and check which variable is null? Commented Feb 12, 2022 at 3:41
  • 3
    Try to debug your code. Could you share exception's details? Commented Feb 12, 2022 at 9:49
  • I have trouble on understanding your issue. Could you please tell us which flow you wanna use for authentication and which api you wanna call? Or if you need users to sign in first then call graph api? If you wanna to use graph client to call the api or you wanna send http request with a token to call the api? Commented Feb 14, 2022 at 5:48
  • What will you need? Inner exception in null, message is :"Object reference not set to an instance of an object." I already mentioned that exception is in line with reqTask. req is NOT null. I'm updating the question with call stack. Commented Feb 14, 2022 at 14:40
  • "req is NOT null" Why do you believe so? The error message is very explicitly telling you that it is, assuming that it's on the line var reqTask = await req.GetAsync(); as you describe. Please show a complete error message, not just that call stack. Show the complete text of the error message, including any line number, repeat of the code in question, ^ symbol possibly pointing at part of the line, etc. etc. Also please read ericlippert.com/2014/03/05/how-to-debug-small-programs Commented Feb 14, 2022 at 14:46

2 Answers 2

1

Thank you for all your help again.

Actual problem was with calling the Graph API. The permissions were not set correctly (missing permissions for reading channels), but the request was sent successfully; the received response contained an error message, not channels data, that's why the exception was thrown inside the Graph code.

Problem described in the question is resolved as above; the unknown for me remains how could I write this code more safely. I don't wanna blame MS for incorrect implementation, but it was hard to find what's wrong.

Sign up to request clarification or add additional context in comments.

3 Comments

So...what did you do to fix it?
As I said I'm not sure. Either 1) updating credentials or 2) adding permissions of type "Application" in AAD (instead of "Delegated" only previously) helped
"I don't wanna blame MS for incorrect implementation" Why not? It's absolutely, shamelessly awful. It's a null reference in error handling code. The call stack literally contains "HandleNonSuccess". You found this in early 2022 and this bug still exists today, in late 2024.
0

Trying to read or write using graph api without your application having the appropriate permissions will generate this exception I agree with the OP that this is poorly implementation. If you see this error, log into azure and go to your api permissions and compare to what the graph api documentation lists as being required.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.