ODL library allows you to write enum values onto properties of other primitive types
Assemblies affected
Microsoft.OData.Core 7.x
Microsoft.OData.Core 8.x
Reproduce steps
Given the following data models:
public class Order
{
public int Id { get; set; }
public decimal Amount { get; set; }
public DateTime OrderDate { get; set; }
}
public enum Color
{
Black,
White
}
The following code for writing an OData payload executes okay but produces an invalid output (included in the snippet as a comment):
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Order>("Orders");
modelBuilder.EnumType<Color>();
var model = modelBuilder.GetEdmModel();
var orderEntityType = model.SchemaElements.First(d => d.Name == "Order") as IEdmEntityType;
var ordersEntitySet = model.EntityContainer.FindEntitySet("Orders");
var messageWriterSettings = new ODataMessageWriterSettings
{
EnableMessageStreamDisposal = false,
Version = ODataVersion.V4,
ODataUri = new ODataUri { ServiceRoot = new Uri("http://tempuri.org") }
};
var tempStream = new MemoryStream();
IODataResponseMessage asyncResponseMessage = new InMemoryMessage { Stream = tempStream };
await using (var messageWriter = new ODataMessageWriter(asyncResponseMessage, messageWriterSettings, model))
{
var orderResource = new ODataResource
{
TypeName = typeof(Order).FullName,
Id = new Uri("http://tempuri.org/Orders(1)"),
Properties = new List<ODataProperty>
{
new ODataProperty { Name = "Id", Value = 1 },
new ODataProperty { Name = "Amount", Value = Color.Black },
new ODataProperty { Name = "OrderDate", Value = Color.White }
}
};
var resourceWriter = await messageWriter.CreateODataResourceWriterAsync(ordersEntitySet, orderEntityType);
await resourceWriter.WriteStartAsync(orderResource);
await resourceWriter.WriteEndAsync();
tempStream.Position = 0;
var result = await new StreamReader(tempStream).ReadToEndAsync();
// result:
// {
// "@odata.context":"http://tempuri.org/$metadata#Orders/$entity",
// "@odata.id":"http://tempuri.org/Orders(1)",
// "Id":1,
// "Amount":"Black",
// "OrderDate":"White"
// }
}
Expected result
The library should flag that the value being written onto the primitive property is invalid
Actual result
The library does not flag that the value being written onto the primitive property is invalid
Additional detail
Here's the definition of the InMemoryMessage type:
internal class InMemoryMessage : IODataResponseMessage, IODataResponseMessageAsync, IODataRequestMessage, IODataRequestMessageAsync
{
private readonly Dictionary<string, string> headers;
public InMemoryMessage()
{
headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
public IEnumerable<KeyValuePair<string, string>> Headers
{
get { return this.headers; }
}
public int StatusCode { get; set; }
public Uri Url { get; set; }
public string Method { get; set; }
public Stream Stream { get; set; }
public string GetHeader(string headerName)
{
return this.headers.TryGetValue(headerName, out string headerValue) ? headerValue : null;
}
public void SetHeader(string headerName, string headerValue)
{
headers[headerName] = headerValue;
}
public Stream GetStream()
{
return this.Stream;
}
public Task<Stream> GetStreamAsync()
{
TaskCompletionSource<Stream> taskCompletionSource = new TaskCompletionSource<Stream>();
taskCompletionSource.SetResult(this.Stream);
return taskCompletionSource.Task;
}
}
ODL library allows you to write enum values onto properties of other primitive types
Assemblies affected
Reproduce steps
Given the following data models:
The following code for writing an OData payload executes okay but produces an invalid output (included in the snippet as a comment):
Expected result
The library should flag that the value being written onto the primitive property is invalid
Actual result
The library does not flag that the value being written onto the primitive property is invalid
Additional detail
Here's the definition of the
InMemoryMessage
type: