Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sdk/core/Azure.Core/Azure.Core.sln
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{13A0
samples\README.md = samples\README.md
samples\RequestContext.md = samples\RequestContext.md
samples\Response.md = samples\Response.md
samples\Serialization.md = samples\Serialization.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.Expressions.DataFactory", "..\Azure.Core.Expressions.DataFactory\src\Azure.Core.Expressions.DataFactory.csproj", "{7723BA5F-0017-45B4-B584-7D11AA069735}"
Expand Down
15 changes: 13 additions & 2 deletions sdk/core/Azure.Core/samples/Serialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,29 @@ Deserialization

## Using explicit cast

When using protocol methods for advanced handling of RequestContext it is still possible to use the strongly typed models.
There is an explicit cast operator that can be used to convert the protocol Response to the strongly typed model.
There is also an explicit cast operator that can be used to convert the strongly typed model to the protocol RequestContent.

Serialization

```C# Snippet:ExplicitCast_Serialize
//TODO
PetStoreClient client = new PetStoreClient(new Uri("http://somewhere.com"), new MockCredential());
DogListProperty dog = new DogListProperty("myPet");
Response response = client.CreatePet("myPet", (RequestContent)dog);
Comment thread
m-nash marked this conversation as resolved.
```

Deserialization

```C# Snippet:ExplicitCast_Deserialize
//TODO
PetStoreClient client = new PetStoreClient(new Uri("http://somewhere.com"), new MockCredential());
Response response = client.GetPet("myPet");
DogListProperty dog = (DogListProperty)response;
Console.WriteLine(dog.IsHungry);
```

Given that explicit cast does not allow for serialization options we might also consider a static `FromResponse` and instance `ToRequestContent` methods.
Comment thread
m-nash marked this conversation as resolved.

## Using System.Text.Json

Serialization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,26 @@ public DogListProperty()
{
}

public static explicit operator DogListProperty(Response response)
{
using JsonDocument jsonDocument = JsonDocument.Parse(response.ContentStream);
var serializationOptions = new SerializableOptions()
{
IgnoreReadOnlyProperties = true,
IgnoreAdditionalProperties = true
};
return DeserializeDogListProperty(jsonDocument.RootElement, serializationOptions);
}

public static explicit operator RequestContent(DogListProperty dog)
{
var content = new Utf8JsonRequestContent();
//content.JsonWriter.WriteObjectValue(dog);
//temp implementation due to IUtf8JsonSerializable signature mismatch since we added an options parameter
((IUtf8JsonSerializable)dog).Write(content.JsonWriter, new SerializableOptions());
return content;
}

#region Serialization
void IUtf8JsonSerializable.Write(Utf8JsonWriter writer, SerializableOptions options)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Azure.Core.TestFramework;
using NUnit.Framework;

namespace Azure.Core.Tests.ModelSerializationTests
{
public class ExplicitCastTests
{
[Test]
public void CastFromResponse()
{
string serviceResponse = "{\"latinName\":\"Animalia\",\"weight\":1.1,\"name\":\"Doggo\",\"isHungry\":false,\"foodConsumed\":[\"kibble\",\"egg\",\"peanut butter\"],\"numberOfLegs\":4}";
var stream = new MemoryStream(Encoding.UTF8.GetBytes(serviceResponse));
stream.Position = 0;
Response response = new MockResponse(200);
response.ContentStream = stream;
DogListProperty dog = (DogListProperty)response;

Assert.AreEqual("Doggo", dog.Name);
Assert.AreEqual(false, dog.IsHungry);
Assert.AreEqual(1.1, dog.Weight);
Assert.AreEqual(new List<string> { "kibble", "egg", "peanut butter" }, dog.FoodConsumed);
Assert.AreEqual("Animalia", dog.LatinName);

var additionalProperties = typeof(Animal).GetProperty("RawData", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(dog) as Dictionary<string, BinaryData>;
Assert.IsNotNull(additionalProperties);
Assert.IsFalse(additionalProperties.ContainsKey("numberOfLegs")); //default cast doesn't include additional properties
}

[Test]
public void CastToRequestContent()
{
#if NETFRAMEWORK
string requestContent = "{\"latinName\":\"Animalia\",\"name\":\"Doggo\",\"isHungry\":false,\"weight\":1.1000000000000001,\"foodConsumed\":[\"kibble\",\"egg\",\"peanut butter\"]}";
#else
string requestContent = "{\"latinName\":\"Animalia\",\"name\":\"Doggo\",\"isHungry\":false,\"weight\":1.1,\"foodConsumed\":[\"kibble\",\"egg\",\"peanut butter\"]}";
#endif
var dog = new DogListProperty
{
Name = "Doggo",
IsHungry = false,
Weight = 1.1,
FoodConsumed = new List<string> { "kibble", "egg", "peanut butter" },
};
RequestContent content = (RequestContent)dog;
var stream = new MemoryStream();
content.WriteTo(stream, default);
stream.Position = 0;
string contentString = new StreamReader(stream).ReadToEnd();
Assert.AreEqual(requestContent, contentString);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ private static void VerifyProperties(Animal x, Animal y, SerializableOptions opt
Assert.That(x.Name, Is.EqualTo(y.Name));
Assert.That(x.Weight, Is.EqualTo(y.Weight));

if (!options.IgnoreReadOnlyProperties)
if (!options.IgnoreAdditionalProperties)
Comment thread
m-nash marked this conversation as resolved.
{
var additionalPropertiesX = typeof(Animal).GetProperty("RawData", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(x) as Dictionary<string, BinaryData>;
var additionalPropertiesY = typeof(Animal).GetProperty("RawData", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(y) as Dictionary<string, BinaryData>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,48 @@ public virtual Response GetPet(string id, RequestContext context = null)
}
}

/// <summary> Get a pet by its Id. </summary>
/// <param name="id"> Id of pet to return. </param>
/// <param name="context"> The request context. </param>
#pragma warning disable AZC0002
public virtual async Task<Response> CreatePetAsync(string id, RequestContent content, RequestContext context = null)
#pragma warning restore AZC0002
{
using var scope = _clientDiagnostics.CreateScope("PetStoreClient.GetPet");
scope.Start();
try
{
using HttpMessage message = CreateGetPetRequest(id, context);
return await Pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false);
}
catch (Exception e)
{
scope.Failed(e);
throw;
}
}

/// <summary> Get a pet by its Id. </summary>
/// <param name="id"> Id of pet to return. </param>
/// <param name="context"> The request context. </param>
#pragma warning disable AZC0002
public virtual Response CreatePet(string id, RequestContent content, RequestContext context = null)
#pragma warning restore AZC0002
{
using var scope = _clientDiagnostics.CreateScope("PetStoreClient.GetPet");
scope.Start();
try
{
using HttpMessage message = CreateGetPetRequest(id, context);
return Pipeline.ProcessMessage(message, context);
}
catch (Exception e)
{
scope.Failed(e);
throw;
}
}

/// <summary> Create Request for <see cref="GetPet"/> and <see cref="GetPetAsync"/> operations. </summary>
/// <param name="id"> Id of pet to return. </param>
/// <param name="context"> The request context. </param>
Expand Down
12 changes: 10 additions & 2 deletions sdk/core/Azure.Core/tests/samples/SerializationSamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Azure.Core.Experimental.Tests;
using Azure.Core.TestFramework;
using Azure.Core.Tests.ModelSerializationTests;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using NUnit.Framework;
Expand Down Expand Up @@ -55,7 +58,9 @@ public void NonTryDeserialize()
public void ExplicitCastSerialize()
{
#region Snippet:ExplicitCast_Serialize
//TODO
PetStoreClient client = new PetStoreClient(new Uri("http://somewhere.com"), new MockCredential());
DogListProperty dog = new DogListProperty("myPet");
Response response = client.CreatePet("myPet", (RequestContent)dog);
#endregion
}

Expand All @@ -64,7 +69,10 @@ public void ExplicitCastSerialize()
public void ExplicitCastDeserialize()
{
#region Snippet:ExplicitCast_Deserialize
//TODO
PetStoreClient client = new PetStoreClient(new Uri("http://somewhere.com"), new MockCredential());
Response response = client.GetPet("myPet");
DogListProperty dog = (DogListProperty)response;
Console.WriteLine(dog.IsHungry);
#endregion
}

Expand Down