Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/aspnetwebstack.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorraghuramn <ranadimi@microsoft.com>2012-10-06 04:08:34 +0400
committerraghuramn <ranadimi@microsoft.com>2012-10-10 04:12:48 +0400
commit41b15c411ddab94876d270868e0bc3d9faa4f59a (patch)
tree322aba1286f6fe00b897dd2c9af0feb8bc35a58a
parent1b5b1c247f12889f4bd9238723d80ad02ac457a1 (diff)
Issue 484: Self link generation might fail if the model has non-standard
edm primitives we are not converting non-standard primitives to their standard representation before passing on to the ODataUriParser for generating uri representation.
-rw-r--r--src/System.Web.Http.OData/OData/Builder/Conventions/ConventionsHelpers.cs27
-rw-r--r--src/System.Web.Http.OData/Properties/SRResources.Designer.cs9
-rw-r--r--src/System.Web.Http.OData/Properties/SRResources.resx3
-rw-r--r--test/System.Web.Http.OData.Test/OData/Builder/Conventions/ConventionsHelpersTests.cs87
4 files changed, 122 insertions, 4 deletions
diff --git a/src/System.Web.Http.OData/OData/Builder/Conventions/ConventionsHelpers.cs b/src/System.Web.Http.OData/OData/Builder/Conventions/ConventionsHelpers.cs
index 5c29406e..b1661907 100644
--- a/src/System.Web.Http.OData/OData/Builder/Conventions/ConventionsHelpers.cs
+++ b/src/System.Web.Http.OData/OData/Builder/Conventions/ConventionsHelpers.cs
@@ -6,6 +6,7 @@ using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Web.Http.OData.Formatter;
+using System.Web.Http.OData.Formatter.Serialization;
using System.Web.Http.OData.Properties;
using Microsoft.Data.OData.Query;
@@ -48,7 +49,7 @@ namespace System.Web.Http.OData.Builder.Conventions
// TODO: BUG 453795: reflection cleanup
if (entityTypeConfiguration.Keys.Count() == 1)
{
- return GetUriRepresentationForKeyValue(entityTypeConfiguration.Keys.First().PropertyInfo, entityContext.EntityInstance);
+ return GetUriRepresentationForKeyValue(entityTypeConfiguration.Keys.First().PropertyInfo, entityContext.EntityInstance, entityTypeConfiguration);
}
else
{
@@ -57,7 +58,7 @@ namespace System.Web.Http.OData.Builder.Conventions
entityTypeConfiguration
.Keys
.Select(
- key => String.Format(CultureInfo.InvariantCulture, "{0}={1}", key.Name, GetUriRepresentationForKeyValue(key.PropertyInfo, entityContext.EntityInstance))));
+ key => String.Format(CultureInfo.InvariantCulture, "{0}={1}", key.Name, GetUriRepresentationForKeyValue(key.PropertyInfo, entityContext.EntityInstance, entityTypeConfiguration))));
}
}
@@ -159,12 +160,30 @@ namespace System.Web.Http.OData.Builder.Conventions
return false;
}
- private static string GetUriRepresentationForKeyValue(PropertyInfo key, object entityInstance)
+ // gets the primitive odata uri representation.
+ public static string GetUriRepresentationForValue(object value)
+ {
+ Contract.Assert(value != null);
+ Contract.Assert(EdmLibHelpers.GetEdmPrimitiveTypeOrNull(value.GetType()) != null);
+
+ value = ODataPrimitiveSerializer.ConvertUnsupportedPrimitives(value);
+ return ODataUriBuilder.GetUriRepresentation(value);
+ }
+
+ private static string GetUriRepresentationForKeyValue(PropertyInfo key, object entityInstance, IEntityTypeConfiguration entityType)
{
Contract.Assert(key != null);
Contract.Assert(entityInstance != null);
+ Contract.Assert(entityType != null);
+
+ object value = key.GetValue(entityInstance, null);
+
+ if (value == null)
+ {
+ throw Error.InvalidOperation(SRResources.KeyValueCannotBeNull, key.Name, entityType.FullName);
+ }
- return ODataUriBuilder.GetUriRepresentation(key.GetValue(entityInstance, null));
+ return GetUriRepresentationForValue(value);
}
private class PropertyEqualityComparer : IEqualityComparer<PropertyInfo>
diff --git a/src/System.Web.Http.OData/Properties/SRResources.Designer.cs b/src/System.Web.Http.OData/Properties/SRResources.Designer.cs
index d4e79465..7537b7e3 100644
--- a/src/System.Web.Http.OData/Properties/SRResources.Designer.cs
+++ b/src/System.Web.Http.OData/Properties/SRResources.Designer.cs
@@ -502,6 +502,15 @@ namespace System.Web.Http.OData.Properties {
}
/// <summary>
+ /// Looks up a localized string similar to Key property &apos;{0}&apos; of type &apos;{1}&apos; is null. Key properties cannot have null values..
+ /// </summary>
+ internal static string KeyValueCannotBeNull {
+ get {
+ return ResourceManager.GetString("KeyValueCannotBeNull", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The LambdaExpression must have exactly one parameter..
/// </summary>
internal static string LambdaExpressionMustHaveExactlyOneParameter {
diff --git a/src/System.Web.Http.OData/Properties/SRResources.resx b/src/System.Web.Http.OData/Properties/SRResources.resx
index 98d1bfbd..b5c15cb0 100644
--- a/src/System.Web.Http.OData/Properties/SRResources.resx
+++ b/src/System.Web.Http.OData/Properties/SRResources.resx
@@ -438,4 +438,7 @@
<data name="TargetEntityTypeMissing" xml:space="preserve">
<value>Could not find the target entity type for the navigation property '{0}' on entity type '{1}'.</value>
</data>
+ <data name="KeyValueCannotBeNull" xml:space="preserve">
+ <value>Key property '{0}' of type '{1}' is null. Key properties cannot have null values.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/test/System.Web.Http.OData.Test/OData/Builder/Conventions/ConventionsHelpersTests.cs b/test/System.Web.Http.OData.Test/OData/Builder/Conventions/ConventionsHelpersTests.cs
index 5cfead43..992c1f06 100644
--- a/test/System.Web.Http.OData.Test/OData/Builder/Conventions/ConventionsHelpersTests.cs
+++ b/test/System.Web.Http.OData.Test/OData/Builder/Conventions/ConventionsHelpersTests.cs
@@ -4,6 +4,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.TestCommon;
+using Microsoft.TestCommon.Types;
using Moq;
namespace System.Web.Http.OData.Builder.Conventions
@@ -27,6 +28,42 @@ namespace System.Web.Http.OData.Builder.Conventions
}
}
+ public static TheoryDataSet<object, string> GetUriRepresentationForValue_DataSet
+ {
+ get
+ {
+ return new TheoryDataSet<object, string>()
+ {
+ { (bool)true, "true" },
+ { (char)'1', "'1'" },
+ { (char?)'1', "'1'" },
+ { (string)"123", "'123'" },
+ { (char[])new char[] { '1', '2', '3' }, "'123'" },
+ { (int)123, "123" },
+ { (short)123, "123" },
+ { (long)123, "123L" },
+ { (ushort)123, "123" },
+ { (uint)123, "123L" },
+ { (ulong)123, "123L" },
+ { (int?)123, "123" },
+ { (short?)123, "123" },
+ { (long?)123, "123L" },
+ { (ushort?)123, "123" },
+ { (uint?)123, "123L" },
+ { (ulong?)123, "123L" },
+ { (float)123.123, "123.12f" },
+ { (double)123.123, "123.123" },
+ { (decimal)123.123, "123.123M" },
+ { Guid.Empty, "guid'00000000-0000-0000-0000-000000000000'" },
+ { DateTime.FromBinary(0), "datetime'0001-01-01T00:00:00'" },
+ { TimeSpan.FromSeconds(86456), "time'P1DT56S'" },
+ { DateTimeOffset.FromFileTime(0), "datetimeoffset'1600-12-31T16:00:00-08:00'" },
+ { SimpleEnum.First, "'First'" },
+ { FlagsEnum.One | FlagsEnum.Two, "'One%2C%20Two'" },
+ };
+ }
+ }
+
[Theory]
[InlineData(typeof(ICollection<string>), typeof(string))]
[InlineData(typeof(IList<string>), typeof(string))]
@@ -162,6 +199,56 @@ namespace System.Web.Http.OData.Builder.Conventions
Assert.Equal("Key1='key1',Key2=2,Key3=true", keyValue);
}
+ [Fact]
+ public void GetEntityKeyValue_ThrowsForNullKeys()
+ {
+ // Arrange
+ IStructuralTypeConfiguration structuralType = new Mock<IStructuralTypeConfiguration>().Object;
+ var entityInstance = new { Key = (string)null };
+ PrimitivePropertyConfiguration[] keys = { new PrimitivePropertyConfiguration(entityInstance.GetType().GetProperty("Key"), structuralType) };
+
+ Mock<IEntityTypeConfiguration> entityType = new Mock<IEntityTypeConfiguration>();
+ entityType.Setup(e => e.Keys).Returns(keys);
+ entityType.Setup(e => e.FullName).Returns("FullName");
+
+ // Act & Assert
+ Assert.Throws<InvalidOperationException>(
+ () => ConventionsHelpers.GetEntityKeyValue(new EntityInstanceContext { EntityInstance = entityInstance }, entityType.Object),
+ "Key property 'Key' of type 'FullName' is null. Key properties cannot have null values.");
+ }
+
+ [Fact]
+ public void GetEntityKeyValue_ThrowsForNullKeys_WithMultipleKeys()
+ {
+ // Arrange
+ IStructuralTypeConfiguration structuralType = new Mock<IStructuralTypeConfiguration>().Object;
+ var entityInstance = new { Key1 = "abc", Key2 = "def", Key3 = (string)null };
+ PrimitivePropertyConfiguration[] keys =
+ {
+ new PrimitivePropertyConfiguration(entityInstance.GetType().GetProperty("Key1"), structuralType),
+ new PrimitivePropertyConfiguration(entityInstance.GetType().GetProperty("Key2"), structuralType),
+ new PrimitivePropertyConfiguration(entityInstance.GetType().GetProperty("Key3"), structuralType),
+ };
+
+ Mock<IEntityTypeConfiguration> entityType = new Mock<IEntityTypeConfiguration>();
+ entityType.Setup(e => e.Keys).Returns(keys);
+ entityType.Setup(e => e.FullName).Returns("EntityType");
+
+ // Act & Assert
+ Assert.Throws<InvalidOperationException>(
+ () => ConventionsHelpers.GetEntityKeyValue(new EntityInstanceContext { EntityInstance = entityInstance }, entityType.Object),
+ "Key property 'Key3' of type 'EntityType' is null. Key properties cannot have null values.");
+ }
+
+ [Theory]
+ [PropertyData("GetUriRepresentationForValue_DataSet")]
+ public void GetUriRepresentationForValue_Works(object value, string result)
+ {
+ Assert.Equal(
+ result,
+ ConventionsHelpers.GetUriRepresentationForValue(value));
+ }
+
private sealed class IsCollection_with_Collections_TestClass : List<bool>
{
}