Error serializing MS Graph object between SPA client and web API project.

Cindy 1 Reputation point
2021-08-19T01:29:29.897+00:00

I started with this sample project: https://github.com/Azure-Samples/ms-identity-javascript-angular-tutorial/tree/main/7-AdvancedScenarios/1-call-api-obo
It works as expected. I added GETs for TodoTasks and Events and those work fine.

I wanted to add an update to an Event and a Task as a proof of concept. I thought I could use the @microsoft/microsoft-graph-types on my client and it would serialize with the Microsoft.Graph object models in the API. However, I'm getting an error between my client PUT call and the Web API HttpPut handler where it won't serialize the Event parameter of the PUT handler.

Client event.service.ts:

  import * as MicrosoftGraph from "@microsoft/microsoft-graph-types";
    ...

  updateEvent(ev: MicrosoftGraph.Event) {
    let u = this.url + 'Events/' + ev.id;

    return this.http.put<MicrosoftGraph.Event>(u, ev);
  }

Web API Handler (never gets called due to error)

// PUT: api/Events/{id}
[HttpPut("{id}")]
public async Task<IActionResult> PutEvent(string id, Microsoft.Graph.Event myEvent)
{ ... }

Error Response
System.NotSupportedException: The collection type 'Microsoft.Graph.IEventAttachmentsCollectionPage' on 'Microsoft.Graph.Event.Attachments' is not supported.
at System.Text.Json.JsonClassInfo.GetElementType(Type propertyType, Type parentType, MemberInfo memberInfo, JsonSerializerOptions options)
at System.Text.Json.JsonClassInfo.CreateProperty(Type declaredPropertyType, Type runtimePropertyType, Type implementedPropertyType, PropertyInfo propertyInfo, Type parentClassType, JsonConverter converter, JsonSerializerOptions options)
at System.Text.Json.JsonClassInfo.AddProperty(Type propertyType, PropertyInfo propertyInfo, Type classType, JsonSerializerOptions options)
at System.Text.Json.JsonClassInfo..ctor(Type type, JsonSerializerOptions options)
at System.Text.Json.JsonSerializerOptions.GetOrAddClass(Type classType)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS

Accept: application/json, text/plain, /
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Authorization: Bearer eyJ....
Connection: close
Content-Length: 3373
Content-Type: application/json
Host: localhost:44351
Referer: http://localhost:4200/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"
sec-ch-ua-mobile: ?0
origin: http://localhost:4200
sec-fetch-site: cross-site
sec-fetch-mode: cors
sec-fetch-dest: empty

Note that my Event object that I am trying to pass to PUT with was just retrieved from a GET and only the subject was changed.

{allowNewTimeProposals: true, attendees: [],…}
@odata.context: "https://graph.microsoft.com/v1.0/$metadata#users('hidden')/events/$entity"
@odata.etag: "W/\"hidden""
@odata.type: "microsoft.graph.event"
allowNewTimeProposals: true
attendees: []
body: {content: "", contentType: "html", @odata.type: "microsoft.graph.itemBody"}
bodyPreview: ""
calendar@odata.associationLink: "https://graph.microsoft.com/v1.0/users('hidden')/calendars('hidden')/$ref"
calendar@odata.navigationLink: "https://graph.microsoft.com/v1.0/users('hidden')/calendars('hidden')"
categories: []
changeKey: "hidden"
createdDateTime: "2021-08-09T18:14:20.7777236+00:00"
end: {dateTime: "2021-08-20T12:30:00.0000000", timeZone: "UTC",…}
hasAttachments: false
hideAttendees: false
iCalUId: "04000...."
id: "AAMkA..."
importance: "normal"
isAllDay: false
isCancelled: false
isDraft: false
isOnlineMeeting: false
isOrganizer: true
isReminderOn: true
lastModifiedDateTime: "2021-08-09T18:16:21.8851461+00:00"
location: {address: {@odata.type: "microsoft.graph.physicalAddress"},…}
locations: []
occurrenceId: null
onlineMeetingProvider: "unknown"
organizer: {,…}
originalEndTimeZone: "Eastern Standard Time"
originalStartTimeZone: "Eastern Standard Time"
reminderMinutesBeforeStart: 15
responseHeaders: {Date: ["Wed, 18 Aug 2021 18:06:55 GMT"], Cache-Control: ["private"], Transfer-Encoding: ["chunked"],…}
responseRequested: true
responseStatus: {response: "organizer", time: "0001-01-01T00:00:00+00:00",…}
sensitivity: "normal"
showAs: "busy"
start: {dateTime: "2021-08-20T12:00:00.0000000", timeZone: "UTC",…}
statusCode: "OK"
subject: "Test Event4"
transactionId: "cb1d239b-bf70-83b0-8f8e-1ea99a98c3e8"
type: "singleInstance"
webLink: "https://outlook.office365.com/owa/?itemid=AAMk...

I have a similar situation if I try to PUT a TodoTask. I guess my question is if this should work using the Microsoft Graph objects in the client and server? If not, what is the best practice to do this? Do I have to have my own object model and then translate it on each side?

Thanks!

Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
10,647 questions
{count} votes