/// <summary> /// Gets the result set for the operation. /// </summary> /// <param name="provider">Provider instance to resolve the path expression.</param> /// <param name="bindingSet">Binding resource set.</param> /// <returns>Returns the result resource set for the operation.</returns> internal ResourceSetWrapper GetResultSet(DataServiceProviderWrapper provider, ResourceSetWrapper bindingSet) { #if DEBUG Debug.Assert(this.isReadOnly, "Wrapper class has not been initialized yet."); #endif if (this.resourceSet != null) { Debug.Assert(this.resourceSet.ResourceSet == this.operation.ResourceSet, "this.resourceSet.ResourceSet == this.serviceOperation.ResourceSet"); Debug.Assert(this.ResultSetPathExpression == null, "this.ResultSetPathExpression == null"); return(this.resourceSet); } if (this.ResultSetPathExpression != null) { Debug.Assert(provider != null, "provider != null"); if (bindingSet == null) { throw new InvalidOperationException(Strings.OperationWrapper_PathExpressionRequiresBindingSet(this.Name)); } ResourceSetWrapper resultSet = this.ResultSetPathExpression.GetTargetSet(provider, bindingSet); if (resultSet == null) { throw new InvalidOperationException(Strings.OperationWrapper_TargetSetFromPathExpressionNotNotVisible(this.Name, this.ResultSetPathExpression.PathExpression, bindingSet.Name)); } return(resultSet); } return(null); }
/// <summary> /// Gets the target set from the binding set and path expression. /// </summary> /// <param name="provider">Provider instance to resolve the association set.</param> /// <param name="bindingSet">Binding resource set.</param> /// <returns>Returns the target resource set for the path expression.</returns> internal ResourceSetWrapper GetTargetSet(DataServiceProviderWrapper provider, ResourceSetWrapper bindingSet) { Debug.Assert(provider != null, "provider != null"); Debug.Assert(bindingSet != null, "sourceSet != null"); Debug.Assert(this.pathSegments != null && this.pathSegments.Length > 0, "InitializePathSegments() must be called before this."); Debug.Assert(bindingSet.ResourceType.IsAssignableFrom(this.pathSegments[0].SourceType), "bindingSet.ResourceType.IsAssignableFrom(this.pathSegments[0].SourceType)"); ResourceSetWrapper resultSet = bindingSet; for (int idx = 0; resultSet != null && idx < this.pathSegments.Length; idx++) { PathSegment segment = this.pathSegments[idx]; if (segment.Property != null) { resultSet = provider.GetResourceSet(resultSet, segment.SourceType, segment.Property); } #if DEBUG else { Debug.Assert(idx == 0, "Path cannot end with type identifier."); } #endif } return(resultSet); }
internal static void UpdateMetadataVersion(DataServiceProviderWrapper provider, DataServiceOperationContext operationContext, out Version metadataVersion, out MetadataEdmSchemaVersion edmSchemaVersion) { metadataVersion = Version1Dot0; edmSchemaVersion = MetadataEdmSchemaVersion.Version1Dot0; if (!provider.IsV1Provider) { edmSchemaVersion = WebUtil.RaiseMetadataEdmSchemaVersion(edmSchemaVersion, MetadataEdmSchemaVersion.Version1Dot1); } foreach (ResourceType type in provider.GetVisibleTypes(operationContext)) { UpdateMetadataVersionForResourceType(type, ref metadataVersion, ref edmSchemaVersion); } if (provider.HasAnnotations(operationContext)) { edmSchemaVersion = WebUtil.RaiseMetadataEdmSchemaVersion(edmSchemaVersion, MetadataEdmSchemaVersion.Version3Dot0); } foreach (OperationWrapper wrapper in provider.GetVisibleOperations(operationContext)) { if (wrapper.Kind == OperationKind.Action) { edmSchemaVersion = WebUtil.RaiseMetadataEdmSchemaVersion(edmSchemaVersion, MetadataEdmSchemaVersion.Version3Dot0); metadataVersion = WebUtil.RaiseVersion(metadataVersion, Version3Dot0); break; } if (((wrapper.ResultKind == ServiceOperationResultKind.Void) || (wrapper.ResultKind == ServiceOperationResultKind.QueryWithSingleResult)) || (((wrapper.ResultKind == ServiceOperationResultKind.DirectValue) || (wrapper.ResultType.ResourceTypeKind == ResourceTypeKind.ComplexType)) || (wrapper.ResultType.ResourceTypeKind == ResourceTypeKind.Primitive))) { edmSchemaVersion = WebUtil.RaiseMetadataEdmSchemaVersion(edmSchemaVersion, MetadataEdmSchemaVersion.Version1Dot1); break; } } }
private DataServiceProviderWrapper CreateProviderWrapper(DataServiceConfiguration config, bool hasReflectionOrEFProviderQueryBehavior) { IDataServiceMetadataProvider provider; if (hasReflectionOrEFProviderQueryBehavior) { provider = new ReflectionDataServiceProvider(new object(), new object()); } else { provider = new DataServiceProviderSimulator(); } var dataService = new DataServiceSimulator(); DataServiceStaticConfiguration staticConfiguration = new DataServiceStaticConfiguration(dataService.Instance.GetType(), provider); IDataServiceProviderBehavior providerBehavior = hasReflectionOrEFProviderQueryBehavior ? new DataServiceProviderBehavior(new ProviderBehavior(ProviderQueryBehaviorKind.ReflectionProviderQueryBehavior)) : DataServiceProviderBehavior.CustomDataServiceProviderBehavior; var providerWrapper = new DataServiceProviderWrapper( new DataServiceCacheItem(config, staticConfiguration), provider, (IDataServiceQueryProvider)provider, dataService, hasReflectionOrEFProviderQueryBehavior ? true : false); dataService.ProcessingPipeline = new DataServiceProcessingPipeline(); dataService.Provider = providerWrapper; typeof(DataServiceProviderWrapper).GetField("providerBehavior", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(providerWrapper, providerBehavior); #if DEBUG dataService.ProcessingPipeline.SkipDebugAssert = true; #endif return(providerWrapper); }
public void ApplyConfiguration(DataServiceConfiguration configuration, DataServiceProviderWrapper provider) { if (this.Kind == OperationKind.ServiceOperation) { this.serviceOperationRights = configuration.GetServiceOperationRights(this.ServiceOperation); } else { this.serviceActionRights = configuration.GetServiceActionRights(this.ServiceAction); } if (((this.Kind == OperationKind.ServiceOperation) && ((this.serviceOperationRights & ~System.Data.Services.ServiceOperationRights.OverrideEntitySetRights) != System.Data.Services.ServiceOperationRights.None)) || ((this.Kind == OperationKind.Action) && (this.serviceActionRights != System.Data.Services.ServiceActionRights.None))) { if (this.operation.ResourceSet != null) { this.resourceSet = provider.TryResolveResourceSet(this.operation.ResourceSet.Name); if (this.resourceSet == null) { throw new InvalidOperationException(System.Data.Services.Strings.OperationWrapper_OperationResourceSetNotVisible(this.Name, this.operation.ResourceSet.Name)); } } else if (this.ResultSetPathExpression != null) { this.ResultSetPathExpression.InitializePathSegments(provider); } } }
/// <summary> /// Given a segment, writes the element to xml writer corresponding to it, works recursively to write child elements/attributes /// </summary> /// <param name="targetSegment">Segment being written</param> /// <param name="provider">Data Service provider used for rights verification.</param> private void WriteElement(EpmTargetPathSegment targetSegment, DataServiceProviderWrapper provider) #endif { // Content to be written in an element EpmCustomContentWriterNodeData currentContent = this.visitorContent[targetSegment]; currentContent.XmlContentWriter.WriteStartElement( targetSegment.SegmentNamespacePrefix, targetSegment.SegmentName, targetSegment.SegmentNamespaceUri); #if ASTORIA_CLIENT // Serialize the attributes and children before serializing the data itself base.Serialize(targetSegment, EpmSerializationKind.Attributes); #else // Serialize the attributes and children before serializing the data itself base.Serialize(targetSegment, EpmSerializationKind.Attributes, provider); #endif if (targetSegment.HasContent) { Debug.Assert(currentContent.Data != null, "Must always have non-null data content value"); currentContent.XmlContentWriter.WriteString(currentContent.Data); } #if ASTORIA_CLIENT // Serialize the attributes and children before serializing the data itself base.Serialize(targetSegment, EpmSerializationKind.Elements); #else // Serialize the attributes and children before serializing the data itself base.Serialize(targetSegment, EpmSerializationKind.Elements, provider); #endif currentContent.XmlContentWriter.WriteEndElement(); }
private static IEdmEntityType CreateModelAndGetEdmType(ResourceType resourceType) { var provider = new DataServiceProviderSimulator(); DataServiceSimulator dataService = new DataServiceSimulator(); DataServiceStaticConfiguration staticConfiguration = new DataServiceStaticConfiguration(dataService.Instance.GetType(), provider); IDataServiceProviderBehavior providerBehavior = DataServiceProviderBehavior.CustomDataServiceProviderBehavior; DataServiceProviderWrapper providerWrapper = new DataServiceProviderWrapper( new DataServiceCacheItem( new DataServiceConfiguration(provider), staticConfiguration), provider, provider, dataService, false); dataService.Provider = providerWrapper; var model = new MetadataProviderEdmModel(providerWrapper, new DataServiceStreamProviderWrapper(dataService), DataServiceActionProviderWrapper.Create(dataService)); dataService.ProcessingPipeline = new DataServiceProcessingPipeline(); model.MetadataProvider.ProviderBehavior = providerBehavior; var edmType = model.EnsureSchemaType(resourceType) as IEdmEntityType; return(edmType); }
/// <summary> /// Goes through all visible types in the provider and determine the metadata version. /// </summary> /// <param name="provider">Provider wrapper instance.</param> /// <param name="metadataVersion">Returns the metadata version.</param> /// <param name="edmSchemaVersion">Returns the edm schema version.</param> internal static void UpdateMetadataVersion(DataServiceProviderWrapper provider, out Version metadataVersion, out MetadataEdmSchemaVersion edmSchemaVersion) { Debug.Assert(provider != null, "provider != null"); metadataVersion = Version4Dot0; edmSchemaVersion = MetadataEdmSchemaVersion.Version4Dot0; // Metadata versioning should only be impacted by visible types. A resource type is visible only when it is reachable from // a resource set with EntitySetRights != 'None' or a service op with ServiceOperationRights != None or it is a complex type // made visible through DataServiceConfiguration.EnableAccess(). foreach (ResourceType resourceType in provider.GetVisibleTypes()) { UpdateMetadataVersionForResourceType(resourceType, ref metadataVersion, ref edmSchemaVersion); } #if DEBUG // If there are multiple versions in future, add code here to do version-specific things foreach (OperationWrapper so in provider.GetVisibleOperations()) { Debug.Assert( so.ResultKind == ServiceOperationResultKind.DirectValue || so.ResultKind == ServiceOperationResultKind.Enumeration || so.ResultKind == ServiceOperationResultKind.QueryWithMultipleResults || so.ResultKind == ServiceOperationResultKind.QueryWithSingleResult || so.ResultKind == ServiceOperationResultKind.Void, "Otherwise we have introduced a new value for ServiceOperationResultKind, we might need to update the 'if' statement below."); } #endif }
/// <summary>Constructor that creates the root of the tree</summary> /// <param name="provider">Provider wrapper instance</param> /// <param name="element">Object whose properties we will read</param> internal EpmNullValuedPropertyTree(DataServiceProviderWrapper provider, object element) { this.root = new EpmNullValuedPropertyNode { Name = null }; this.provider = provider; this.element = element; }
/// <summary> /// Initializes a new AtomServiceDocumentSerializer, ready to write /// out the Service Document for a data provider. /// </summary> /// <param name="output">Stream to which output should be sent.</param> /// <param name="baseUri">Base URI from which resources should be resolved.</param> /// <param name="provider">Data provider from which metadata should be gathered.</param> /// <param name="encoding">Text encoding for the response.</param> internal AtomServiceDocumentSerializer( Stream output, Uri baseUri, DataServiceProviderWrapper provider, Encoding encoding) : base(output, baseUri, provider, encoding) { }
/// <summary> /// Gets the visible resource properties for <paramref name="entityType"/> for this set. /// We cache the list of visible resource properties so we don't have to calculate it repeatedly when serializing feeds. /// </summary> /// <param name="provider">Data service provider instance.</param> /// <param name="entityType">Resource type in question.</param> /// <returns>List of visible resource properties for the resource type.</returns> internal IEnumerable <ResourceProperty> GetEntitySerializableProperties(DataServiceProviderWrapper provider, ResourceType entityType) { Debug.Assert(entityType != null && entityType.ResourceTypeKind == ResourceTypeKind.EntityType, "entityType != null && entityType.ResourceTypeKind == ResourceTypeKind.EntityType"); ResourcePropertyCache cachedResourceProperties = this.InitializeResourcePropertyCache(provider, entityType); return(cachedResourceProperties.Properties); }
/// <summary>Initializes a new <see cref="RequestExpressionParser"/>.</summary> /// <param name="service">Service with data and configuration.</param> /// <param name="requestDescription">RequestDescription instance containing information about the current request being parsed.</param> internal RequestExpressionParser(IDataService service, RequestDescription requestDescription) { Debug.Assert(service != null, "service != null"); Debug.Assert(requestDescription != null, "requestDescription != null"); this.provider = service.Provider; this.model = this.provider.GetMetadataProviderEdmModel(); this.odataUriParser = RequestUriProcessor.CreateUriParserWithBatchReferenceCallback(service, service.OperationContext.AbsoluteRequestUri); }
/// <summary> /// Initializes a new JsonServiceDocumentSerializer, ready to write /// out the Service Document for a data provider. /// </summary> /// <param name="output">Stream to which output should be sent.</param> /// <param name="provider">Data provider from which metadata should be gathered.</param> /// <param name="encoding">Text encoding for the response.</param> internal JsonServiceDocumentSerializer( Stream output, DataServiceProviderWrapper provider, Encoding encoding) { Debug.Assert(output != null, "output != null"); Debug.Assert(provider != null, "provider != null"); this.writer = new JsonWriter(new StreamWriter(output, encoding)); this.provider = provider; }
internal EpmCustomContentWriterNodeData(EpmCustomContentWriterNodeData parentData, EpmTargetPathSegment segment, object element, EpmContentSerializer.EpmNullValuedPropertyTree nullValuedProperties, DataServiceProviderWrapper provider) #endif { this.XmlContentStream = parentData.XmlContentStream; this.XmlContentWriter = parentData.XmlContentWriter; #if ASTORIA_CLIENT this.PopulateData(segment, element); #else this.PopulateData(segment, element, nullValuedProperties, provider); #endif }
internal static ResourceType GetNonPrimitiveResourceType(DataServiceProviderWrapper provider, object obj) { IProjectedResult result = obj as IProjectedResult; ResourceType type = (result != null) ? provider.TryResolveResourceType(result.ResourceTypeName) : provider.GetResourceType(obj); if (type == null) { throw new DataServiceException(500, System.Data.Services.Strings.BadProvider_InvalidTypeSpecified(obj.GetType().FullName)); } return(type); }
/// <summary> /// Constructor creates contained serializers /// </summary> /// <param name="resourceType">Resource type being serialized</param> /// <param name="value">Instance of <paramref name="resourceType"/></param> /// <param name="targetItem">SyndicationItem to which content will be added</param> /// <param name="provider">Data Service provider used for rights verification.</param> internal EpmContentSerializer(ResourceType resourceType, Object value, SyndicationItem targetItem, DataServiceProviderWrapper provider) { this.resourceType = resourceType; this.targetItem = targetItem; this.nullValuedProperties = new EpmNullValuedPropertyTree(provider, value); if (this.NeedEpmSerialization) { this.epmSyndicationSerializer = new EpmSyndicationContentSerializer(this.resourceType.EpmTargetTree, value, targetItem, this.nullValuedProperties); this.epmCustomSerializer = new EpmCustomContentSerializer(this.resourceType.EpmTargetTree, value, targetItem, this.nullValuedProperties, provider); } }
/// <summary>Reads a $select clause.</summary> /// <param name="value">Value to read.</param> /// <param name="dataServiceProviderWrapper">The provider wrapper for the service.</param> /// <returns>A list of paths, each of which is a list of identifiers.</returns> private static IList <IList <string> > SplitSelect(string value, DataServiceProviderWrapper dataServiceProviderWrapper) { Debug.Assert(!String.IsNullOrEmpty(value), "!String.IsNullOrEmpty(value)"); List <IList <string> > result = new List <IList <string> >(); List <string> currentPath = null; ExpressionLexer lexer = new ExpressionLexer(value); while (lexer.CurrentToken.Kind != ExpressionTokenKind.End) { string identifier; bool lastSegment = false; if (lexer.CurrentToken.Kind == ExpressionTokenKind.Star) { identifier = lexer.CurrentToken.Text; lexer.NextToken(); lastSegment = true; } else { identifier = lexer.ReadDottedIdentifier(true /*allowEndWithDotStar*/); bool nameIsContainerQualifed; if (dataServiceProviderWrapper.GetNameFromContainerQualifiedName(identifier, out nameIsContainerQualifed) == "*") { lastSegment = true; } } if (currentPath == null) { currentPath = new List <string>(); result.Add(currentPath); } currentPath.Add(identifier); // Check whether we're at the end, whether we're drilling in, // or whether we're finishing with this path. ExpressionTokenKind tokenId = lexer.CurrentToken.Kind; if (tokenId != ExpressionTokenKind.End) { if (lastSegment || tokenId != ExpressionTokenKind.Slash) { lexer.ValidateToken(ExpressionTokenKind.Comma); currentPath = null; } lexer.NextToken(); } } return(result); }
/// <summary> /// Initializes a new instance of <see cref="ODataPathToSegmentInfoConverter"/>. /// </summary> /// <param name="maxProtocolVersion">The max protocol version of the service.</param> /// <param name="providerWrapper">The provider wrapper to use for looking up types/sets, etc.</param> /// <param name="crossReferenceCallback">A callback to get cross-referenced segments (ie '$0') when inside a batch request changeset.</param> private ODataPathToSegmentInfoConverter( Version maxProtocolVersion, DataServiceProviderWrapper providerWrapper, Func<string, SegmentInfo> crossReferenceCallback) { Debug.Assert(providerWrapper != null, "providerWrapper != null"); Debug.Assert(crossReferenceCallback != null, "crossReferenceCallback != null"); Debug.Assert(maxProtocolVersion != null, "maxProtocolVersion != null"); this.providerWrapper = providerWrapper; this.crossReferenceCallback = crossReferenceCallback; this.maxProtocolVersion = maxProtocolVersion; }
/// <summary> /// Initializes a new instance of <see cref="ODataPathToSegmentInfoConverter"/>. /// </summary> /// <param name="maxProtocolVersion">The max protocol version of the service.</param> /// <param name="providerWrapper">The provider wrapper to use for looking up types/sets, etc.</param> /// <param name="crossReferenceCallback">A callback to get cross-referenced segments (ie '$0') when inside a batch request changeset.</param> private ODataPathToSegmentInfoConverter( Version maxProtocolVersion, DataServiceProviderWrapper providerWrapper, Func <string, SegmentInfo> crossReferenceCallback) { Debug.Assert(providerWrapper != null, "providerWrapper != null"); Debug.Assert(crossReferenceCallback != null, "crossReferenceCallback != null"); Debug.Assert(maxProtocolVersion != null, "maxProtocolVersion != null"); this.providerWrapper = providerWrapper; this.crossReferenceCallback = crossReferenceCallback; this.maxProtocolVersion = maxProtocolVersion; }
internal ResourceSetWrapper GetTargetSet(DataServiceProviderWrapper provider, ResourceSetWrapper bindingSet) { ResourceSetWrapper sourceContainer = bindingSet; for (int i = 0; (sourceContainer != null) && (i < this.pathSegments.Length); i++) { PathSegment segment = this.pathSegments[i]; if (segment.Property != null) { sourceContainer = provider.GetContainer(sourceContainer, segment.SourceType, segment.Property); } } return sourceContainer; }
public void Initialize() { this.host = new DataServiceHost2Simulator(); var context = new DataServiceOperationContext(this.host); this.dataServiceSimulator = new DataServiceSimulator { OperationContext = context }; var providerSimulator = new DataServiceProviderSimulator(); DataServiceStaticConfiguration staticConfiguration = new DataServiceStaticConfiguration(this.dataServiceSimulator.Instance.GetType(), providerSimulator); IDataServiceProviderBehavior providerBehavior = DataServiceProviderBehavior.CustomDataServiceProviderBehavior; var resourceType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "SelectTestNamespace", "Fake", false) { CanReflectOnInstanceType = false, IsOpenType = true }; resourceType.AddProperty(new ResourceProperty("Id", ResourcePropertyKind.Key | ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int))) { CanReflectOnInstanceTypeProperty = false }); var resourceSet = new ResourceSet("FakeSet", resourceType); resourceSet.SetReadOnly(); providerSimulator.AddResourceSet(resourceSet); var configuration = new DataServiceConfiguration(providerSimulator); configuration.SetEntitySetAccessRule("*", EntitySetRights.All); var provider = new DataServiceProviderWrapper( new DataServiceCacheItem( configuration, staticConfiguration), providerSimulator, providerSimulator, this.dataServiceSimulator, false); this.dataServiceSimulator.ProcessingPipeline = new DataServiceProcessingPipeline(); this.dataServiceSimulator.Provider = provider; provider.ProviderBehavior = providerBehavior; this.dataServiceSimulator.Configuration = new DataServiceConfiguration(providerSimulator); this.dataServiceSimulator.Configuration.DataServiceBehavior.MaxProtocolVersion = ODataProtocolVersion.V4; this.responseMessageSimulator = new ODataResponseMessageSimulator(); }
internal EpmCustomContentWriterNodeData(EpmTargetPathSegment segment, object element, EpmContentSerializer.EpmNullValuedPropertyTree nullValuedProperties, DataServiceProviderWrapper provider) #endif { this.XmlContentStream = new MemoryStream(); XmlWriterSettings customContentWriterSettings = new XmlWriterSettings(); customContentWriterSettings.OmitXmlDeclaration = true; customContentWriterSettings.ConformanceLevel = ConformanceLevel.Fragment; this.XmlContentWriter = XmlWriter.Create(this.XmlContentStream, customContentWriterSettings); #if ASTORIA_CLIENT this.PopulateData(segment, element); #else this.PopulateData(segment, element, nullValuedProperties, provider); #endif }
internal void Serialize(DataServiceProviderWrapper provider) #endif { foreach (EpmTargetPathSegment targetSegment in this.Root.SubSegments) { #if ASTORIA_CLIENT this.Serialize(targetSegment, EpmSerializationKind.All); #else this.Serialize(targetSegment, EpmSerializationKind.All, provider); #endif } this.Success = true; }
/// <summary>Public interface used by the EpmContentSerializer class</summary> /// <param name="provider">Data Service provider used for rights verification.</param> internal void Serialize(DataServiceProviderWrapper provider) #endif { foreach (EpmTargetPathSegment targetSegment in this.Root.SubSegments) { #if ASTORIA_CLIENT this.Serialize(targetSegment, EpmSerializationKind.All); #else this.Serialize(targetSegment, EpmSerializationKind.All, provider); #endif } this.Success = true; }
protected override void Serialize(EpmTargetPathSegment targetSegment, EpmSerializationKind kind, DataServiceProviderWrapper provider) #endif { if (targetSegment.IsAttribute) { this.WriteAttribute(targetSegment); } else { #if ASTORIA_CLIENT this.WriteElement(targetSegment); #else this.WriteElement(targetSegment, provider); #endif } }
/// <summary> /// Prepares the service's model for serialization during a $metadata request by adding versioning annotations and running validation. /// </summary> /// <param name="provider">The service's provider</param> /// <param name="configuration">The service's configuration</param> /// <returns>Returns the prepared model.</returns> internal static IEdmModel PrepareModelForSerialization(DataServiceProviderWrapper provider, DataServiceConfiguration configuration) { Debug.Assert(provider != null, "provider != null"); Debug.Assert(configuration != null, "configuration != null"); MetadataProviderEdmModel model = provider.GetMetadataProviderEdmModel(); model.AssertCacheEmpty(); // For computing the metadata version, we need to walk through all the types and operations. // This causes the model to be also completely populated and hence the metadata is loaded // based on the MPV on the server. // But there are some changes we made in 5.0 OOB release that we will display the right // value of Nullable attribute in $metadata for V3 and above. Since the metadata version // is not known, this is not correctly populated. Hence we need to compute the metadata // version first, and then clear the model so that it can be populated again based on the // the computed metadata version. Version minMetadataEdmSchemaVersion = model.MinMetadataEdmSchemaVersion; // NOTE: The below annotations on the model are only relevant for $metadata serialization. // We set them every time the metadata document is written. Version metadataEdmSchemaVersion = provider.SchemaVersion.ToVersion(); if (minMetadataEdmSchemaVersion > metadataEdmSchemaVersion) { metadataEdmSchemaVersion = minMetadataEdmSchemaVersion; } model.SetEdmVersion(metadataEdmSchemaVersion); // For Astoria, set the EDMX version of the model always to "1.0" model.SetEdmxVersion(edmxVersion); // now load the entire model. model.EnsureFullMetadataLoaded(); // even though there may not be user annotations there may be an annotation for Azure key url, this must always be called model.AnnotationsCache.PopulateFromConfiguration(configuration); // If model validation is enabled, validate the model before writing. if (!configuration.DisableValidationOnMetadataWrite) { ValidateModel(model, metadataEdmSchemaVersion); } return(model); }
internal static ResourceType ResolveTypeIdentifier(DataServiceProviderWrapper provider, string identifier, ResourceType previousSegmentResourceType, bool previousSegmentIsTypeSegment) { ResourceType subType = provider.TryResolveResourceType(identifier); if (subType != null) { if (previousSegmentIsTypeSegment) { throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.RequestUriProcessor_TypeIdentifierCannotBeSpecifiedAfterTypeIdentifier(identifier, previousSegmentResourceType.FullName)); } if (!previousSegmentResourceType.IsAssignableFrom(subType)) { throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.RequestUriProcessor_InvalidTypeIdentifier_MustBeASubType(identifier, previousSegmentResourceType.FullName)); } } return(subType); }
/// <summary>Delegates to each of custom and syndication serializers for serializing content</summary> /// <param name="content">Content in which to write null valued properties</param> /// <param name="provider">Data Service provider used for rights verification.</param> internal void Serialize(DictionaryContent content, DataServiceProviderWrapper provider) { if (this.NeedEpmSerialization) { Debug.Assert(this.epmSyndicationSerializer != null, "ResourceType with mapping implies a valid syndication content serializer"); this.epmSyndicationSerializer.Serialize(provider); Debug.Assert(this.epmCustomSerializer != null, "ResourceType with mapping implies a valid custom content serializer"); this.epmCustomSerializer.Serialize(provider); this.nullValuedProperties.AddNullValuesToContent(content); } else { Debug.Assert(this.targetItem != null, "Must always have target content item"); this.targetItem.Authors.Add(new SyndicationPerson(null, String.Empty, null)); } }
/// <summary> /// Initializes a new XmlDocumentSerializer, ready to write /// out an XML document /// </summary> /// <param name="output">Stream to which output should be sent.</param> /// <param name="baseUri">Base URI from which resources should be resolved.</param> /// <param name="provider">Data provider from which metadata should be gathered.</param> /// <param name="encoding">Text encoding for the response.</param> internal XmlDocumentSerializer( Stream output, Uri baseUri, DataServiceProviderWrapper provider, Encoding encoding) { Debug.Assert(output != null, "output != null"); Debug.Assert(provider != null, "provider != null"); Debug.Assert(baseUri != null, "baseUri != null"); Debug.Assert(encoding != null, "encoding != null"); Debug.Assert(baseUri.IsAbsoluteUri, "baseUri.IsAbsoluteUri(" + baseUri + ")"); Debug.Assert(baseUri.AbsoluteUri[baseUri.AbsoluteUri.Length - 1] == '/', "baseUri(" + baseUri.AbsoluteUri + ") ends with '/'"); this.writer = XmlUtil.CreateXmlWriterAndWriteProcessingInstruction(output, encoding); this.provider = provider; this.baseUri = baseUri; }
/// <summary>Writes the Service Document to the output stream.</summary> /// <param name="provider">DataServiceProviderWrapper instance.</param> internal void WriteServiceDocument(DataServiceProviderWrapper provider) { ODataServiceDocument serviceDocument = new ODataServiceDocument(); serviceDocument.EntitySets = provider.GetResourceSets().Select(rs => { ODataEntitySetInfo entitySetInfo = new ODataEntitySetInfo() { Url = new Uri(rs.Name, UriKind.RelativeOrAbsolute), Name = rs.Name }; return(entitySetInfo); }); this.writer.WriteServiceDocument(serviceDocument); }
private static DataServiceProviderWrapper CreateProviderWrapper(TestActionProvider actionProvider = null, Action <DataServiceProviderSimulator> addMetadata = null) { var provider = new DataServiceProviderSimulator(); if (addMetadata != null) { addMetadata(provider); } var dataService = new DataServiceSimulatorWithGetService(); dataService.Configuration = new DataServiceConfiguration(provider); dataService.ProcessingPipeline = new DataServiceProcessingPipeline(); dataService.Configuration.SetServiceActionAccessRule("*", ServiceActionRights.Invoke); dataService.Configuration.SetEntitySetAccessRule("*", EntitySetRights.All); dataService.Configuration.SetServiceOperationAccessRule("*", ServiceOperationRights.All); dataService.Configuration.DataServiceBehavior.MaxProtocolVersion = ODataProtocolVersion.V4; dataService.OperationContext = new DataServiceOperationContext(false, new DataServiceHost2Simulator { AbsoluteRequestUri = new Uri("http://fake.org/$metadata") }); dataService.OperationContext.InitializeAndCacheHeaders(dataService); DataServiceStaticConfiguration staticConfiguration = new DataServiceStaticConfiguration(dataService.Instance.GetType(), provider); IDataServiceProviderBehavior providerBehavior = DataServiceProviderBehavior.CustomDataServiceProviderBehavior; var providerWrapper = new DataServiceProviderWrapper( new DataServiceCacheItem( dataService.Configuration, staticConfiguration), provider, provider, dataService, false); dataService.Provider = providerWrapper; providerWrapper.ProviderBehavior = providerBehavior; dataService.ActionProvider = DataServiceActionProviderWrapper.Create(dataService); if (actionProvider != null) { dataService.Providers.Add(typeof(IDataServiceActionProvider), actionProvider); } return(providerWrapper); }
/// <summary>Whether the types contained in the set have named streams or not</summary> /// <param name="provider">Data service provider instance.</param> private void CheckHierarchy(DataServiceProviderWrapper provider) { #if DEBUG Debug.Assert(provider != null, "provider != null"); Debug.Assert(this.resourceSet != null, "this.resourceSet != null"); Debug.Assert(this.isReadOnly, "this.isReadOnly - entity set settings not initialized."); #endif // Go through all types contained in the set. // Find the maximum of minimum DSPVs required for resource types. // If any one type has collection properties, the whole set has them. // If any one type has named streams, the whole set has them. ResourceType baseType = this.resourceSet.ResourceType; bool hasNavigationPropertyOrNamedStreamOnDerivedType = false; bool hasNavigationProperty = this.GetEntitySerializableProperties(provider, baseType).Any(p => p.TypeKind == ResourceTypeKind.EntityType); bool hasOpenType = baseType.IsOpenType; this.hasDerivedTypes = provider.HasDerivedTypes(baseType); Version resourceSetVersion = baseType.MetadataVersion; // If we have all the V3 features or no derived types then we do not need to look any further if (this.hasDerivedTypes) { foreach (ResourceType derivedType in provider.GetDerivedTypes(baseType)) { bool hasNavigationPropertyOnDerivedType = this.GetEntitySerializablePropertiesDeclaredOnTheResourceType(provider, derivedType).Any(p => p.TypeKind == ResourceTypeKind.EntityType); hasNavigationProperty |= hasNavigationPropertyOnDerivedType; hasNavigationPropertyOrNamedStreamOnDerivedType |= derivedType.HasNamedStreamsDeclaredOnThisType | hasNavigationPropertyOnDerivedType; resourceSetVersion = VersionUtil.RaiseVersion(resourceSetVersion, derivedType.MetadataVersion); hasOpenType |= derivedType.IsOpenType; // If we have all the V3(latest) features we do not need to look any further if (resourceSetVersion == VersionUtil.Version4Dot0 && hasNavigationPropertyOrNamedStreamOnDerivedType && hasOpenType) { break; } } } this.hasAccessibleNavigationProperty = hasNavigationProperty; this.hasOpenTypes = hasOpenType; this.metadataVersion = resourceSetVersion; }
internal void WriteServiceDocument(DataServiceProviderWrapper provider) { ODataWorkspace defaultWorkspace = new ODataWorkspace { Collections = provider.GetResourceSets().Select<ResourceSetWrapper, ODataResourceCollectionInfo>(delegate (ResourceSetWrapper rs) { ODataResourceCollectionInfo info = new ODataResourceCollectionInfo { Url = new Uri(rs.Name, UriKind.RelativeOrAbsolute) }; AtomResourceCollectionMetadata annotation = new AtomResourceCollectionMetadata(); AtomTextConstruct construct = new AtomTextConstruct { Text = rs.Name }; annotation.Title = construct; info.SetAnnotation<AtomResourceCollectionMetadata>(annotation); return info; }) }; this.writer.WriteServiceDocument(defaultWorkspace); }
internal static object GetPropertyValue(DataServiceProviderWrapper provider, object resource, ResourceType resourceType, ResourceProperty resourceProperty, string propertyName) { IProjectedResult result = resource as IProjectedResult; if (result != null) { object projectedPropertyValue = result.GetProjectedPropertyValue(propertyName ?? resourceProperty.Name); if (IsNullValue(projectedPropertyValue)) { projectedPropertyValue = null; } return(projectedPropertyValue); } if (resourceProperty != null) { return(provider.GetPropertyValue(resource, resourceProperty, resourceType)); } return(provider.GetOpenPropertyValue(resource, propertyName)); }
internal void WriteServiceDocument(DataServiceProviderWrapper provider) { ODataWorkspace defaultWorkspace = new ODataWorkspace { Collections = provider.GetResourceSets().Select <ResourceSetWrapper, ODataResourceCollectionInfo>(delegate(ResourceSetWrapper rs) { ODataResourceCollectionInfo info = new ODataResourceCollectionInfo { Url = new Uri(rs.Name, UriKind.RelativeOrAbsolute) }; AtomResourceCollectionMetadata annotation = new AtomResourceCollectionMetadata(); AtomTextConstruct construct = new AtomTextConstruct { Text = rs.Name }; annotation.Title = construct; info.SetAnnotation <AtomResourceCollectionMetadata>(annotation); return(info); }) }; this.writer.WriteServiceDocument(defaultWorkspace); }
/// <summary> /// Given a source property path in the segmented form reads the property value from the resource type instance. /// </summary> /// <param name="element">Resource type instance.</param> /// <param name="provider">Underlying data provider.</param> /// <param name="resourceType">Resource type whose property is to be read.</param> /// <param name="srcPathSegments">Segmented source property path.</param> /// <param name="currentSegment">Index of current property name in <paramref name="srcPathSegments"/></param> /// <returns>Property value read from the resource type instance. Possibly null.</returns> private static object ReadPropertyValue(object element, DataServiceProviderWrapper provider, ResourceType resourceType, string[] srcPathSegments, int currentSegment) { if (element == null || currentSegment == srcPathSegments.Length) { return(element); } else { String propertyName = srcPathSegments[currentSegment]; ResourceProperty resourceProperty = resourceType != null?resourceType.TryResolvePropertyName(propertyName) : null; if (resourceProperty != null) { // If this is the last part of the path, then it has to be a primitive type otherwise should be a complex type if (!resourceProperty.IsOfKind(currentSegment == srcPathSegments.Length - 1 ? ResourcePropertyKind.Primitive : ResourcePropertyKind.ComplexType)) { throw new InvalidOperationException(Strings.EpmSourceTree_EndsWithNonPrimitiveType(propertyName)); } } else { if (!(resourceType == null || resourceType.IsOpenType)) { throw new InvalidOperationException(Strings.EpmSourceTree_InaccessiblePropertyOnType(propertyName, resourceType.Name)); } // this is an open type resolve resourceType and try resolving resourceProperty resourceType = WebUtil.GetNonPrimitiveResourceType(provider, element); resourceProperty = resourceType.TryResolvePropertyName(propertyName); } Debug.Assert(resourceType != null, "resourceType != null"); object propertyValue = WebUtil.GetPropertyValue(provider, element, resourceType, resourceProperty, resourceProperty == null ? propertyName : null); return(ReadPropertyValue( propertyValue, provider, resourceProperty != null ? resourceProperty.ResourceType : null, srcPathSegments, currentSegment + 1)); } }
internal ResourceSetWrapper GetResultSet(DataServiceProviderWrapper provider, ResourceSetWrapper bindingSet) { if (this.resourceSet != null) { return this.resourceSet; } if (this.ResultSetPathExpression == null) { return null; } if (bindingSet == null) { throw new InvalidOperationException(System.Data.Services.Strings.OperationWrapper_PathExpressionRequiresBindingSet(this.Name)); } ResourceSetWrapper targetSet = this.ResultSetPathExpression.GetTargetSet(provider, bindingSet); if (targetSet == null) { throw new InvalidOperationException(System.Data.Services.Strings.OperationWrapper_TargetSetFromPathExpressionNotNotVisible(this.Name, this.ResultSetPathExpression.PathExpression, bindingSet.Name)); } return targetSet; }
/// <summary>Writes the Service Document to the output stream.</summary> /// <param name="provider">DataServiceProviderWrapper instance.</param> internal void WriteServiceDocument(DataServiceProviderWrapper provider) { ODataServiceDocument serviceDocument = new ODataServiceDocument(); serviceDocument.EntitySets = provider.GetResourceSets().Select(rs => { ODataEntitySetInfo entitySetInfo = new ODataEntitySetInfo() { Url = new Uri(rs.Name, UriKind.RelativeOrAbsolute), Name = rs.Name }; entitySetInfo.SetAnnotation<AtomResourceCollectionMetadata>(new AtomResourceCollectionMetadata() { Title = new AtomTextConstruct { Text = rs.Name } }); return entitySetInfo; }); this.writer.WriteServiceDocument(serviceDocument); }
/// <summary> /// Checks if the cache is populated, otherwise populates it. /// </summary> /// <param name="provider">Data service provider instance.</param> /// <param name="type">Resource type in question.</param> /// <returns>An instance of ResourcePropertyCache, with all information about the properties cached.</returns> private ResourcePropertyCache InitializeResourcePropertyCache(DataServiceProviderWrapper provider, ResourceType type) { Debug.Assert(provider != null, "provider != null"); Debug.Assert(type != null, "resourceType != null"); Debug.Assert(this.ResourceType.IsAssignableFrom(type), "this.ResourceType.IsAssignableFrom(resourceType)"); ResourcePropertyCache propertyCache; if (!this.resourcePropertyCache.TryGetValue(type, out propertyCache)) { propertyCache = new ResourcePropertyCache(); propertyCache.Properties = new List <ResourceProperty>(); foreach (ResourceProperty property in type.Properties) { if (property.TypeKind == ResourceTypeKind.EntityType && provider.GetResourceSet(this, type, property) == null) { // non-visible nav properties continue; } propertyCache.Properties.Add(property); } propertyCache.PropertiesDeclaredOnTheType = new List <ResourceProperty>(); foreach (ResourceProperty property in type.PropertiesDeclaredOnThisType) { if (property.TypeKind == ResourceTypeKind.EntityType && provider.GetResourceSet(this, type, property) == null) { // non-visible nav properties continue; } propertyCache.PropertiesDeclaredOnTheType.Add(property); } this.resourcePropertyCache.Add(type, propertyCache); } return(propertyCache); }
private void CheckHierarchy(DataServiceProviderWrapper provider) { if (!this.epmMinDSPV.HasValue) { System.Data.Services.Providers.ResourceType resourceType = this.resourceSet.ResourceType; bool hasEntityPropertyMappings = resourceType.HasEntityPropertyMappings; DataServiceProtocolVersion epmMinimumDataServiceProtocolVersion = resourceType.EpmMinimumDataServiceProtocolVersion; bool flag2 = false; bool flag3 = this.GetEntitySerializableProperties(provider, resourceType).Any<ResourceProperty>(p => p.TypeKind == ResourceTypeKind.EntityType); bool isOpenType = resourceType.IsOpenType; Version metadataVersion = resourceType.MetadataVersion; if (provider.HasDerivedTypes(resourceType)) { foreach (System.Data.Services.Providers.ResourceType type2 in provider.GetDerivedTypes(resourceType)) { if (type2.EpmMinimumDataServiceProtocolVersion > epmMinimumDataServiceProtocolVersion) { epmMinimumDataServiceProtocolVersion = type2.EpmMinimumDataServiceProtocolVersion; } hasEntityPropertyMappings |= type2.HasEntityPropertyMappings; bool flag5 = this.GetEntitySerializablePropertiesDeclaredOnTheResourceType(provider, type2).Any<ResourceProperty>(p => p.TypeKind == ResourceTypeKind.EntityType); flag3 |= flag5; flag2 |= type2.HasNamedStreamsDeclaredOnThisType | flag5; metadataVersion = WebUtil.RaiseVersion(metadataVersion, type2.MetadataVersion); isOpenType |= type2.IsOpenType; if (((epmMinimumDataServiceProtocolVersion == DataServiceProtocolVersion.V3) && (metadataVersion == RequestDescription.Version3Dot0)) && (flag2 && isOpenType)) { break; } } } this.hasEntityPropertyMappings = hasEntityPropertyMappings; this.epmMinDSPV = new DataServiceProtocolVersion?(epmMinimumDataServiceProtocolVersion); this.hasNavigationPropertyOrNamedStreamOnDerivedTypes = flag2; this.hasAccessibleNavigationProperty = flag3; this.hasOpenTypes = isOpenType; this.metadataVersion = metadataVersion; } }
/// <summary> /// Creates a new instance of <see cref="EntityToSerialize"/>. /// </summary> /// <param name="entity">The entity itself.</param> /// <param name="resourceType">The type of the entity.</param> /// <param name="resourceSetWrapper">The resource set the entity belongs to.</param> /// <param name="provider">The wrapper for the current service provider.</param> /// <param name="absoluteServiceUri">The absolute service URI.</param> /// <returns>The new instance of <see cref="EntityToSerialize"/></returns> internal static EntityToSerialize Create(object entity, ResourceType resourceType, ResourceSetWrapper resourceSetWrapper, DataServiceProviderWrapper provider, Uri absoluteServiceUri) { Debug.Assert(provider != null, "provider != null"); Debug.Assert(provider.DataService != null, "provider.DataService != null"); Debug.Assert(provider.DataService.Configuration != null, "provider.DataService.Configuration != null"); KeySerializer keySerializer = KeySerializer.Create(UrlConvention.Create(provider.DataService)); Func<ResourceProperty, object> getPropertyValue = p => { object keyValue = WebUtil.GetPropertyValue(provider, entity, resourceType, p, null); if (keyValue == null) { throw new InvalidOperationException(Service.Strings.Serializer_NullKeysAreNotSupported(p.Name)); } return keyValue; }; bool includeTypeSegment = resourceSetWrapper.ResourceType != resourceType; return Create(entity, resourceType, resourceSetWrapper.Name, includeTypeSegment, getPropertyValue, keySerializer, absoluteServiceUri); }
private static MetadataProviderEdmModel CreateMetadataProviderEdmModel(DataServiceProviderSimulator metadataProvider, IDataServiceActionProvider actionProvider = null) { var dataServiceSimulator = new DataServiceSimulatorWithGetService { OperationContext = new DataServiceOperationContext(false, new DataServiceHost2Simulator()), ProcessingPipeline = new DataServiceProcessingPipeline() }; dataServiceSimulator.OperationContext.InitializeAndCacheHeaders(dataServiceSimulator); var dataServiceConfiguration = new DataServiceConfiguration(metadataProvider); dataServiceConfiguration.SetEntitySetAccessRule("*", EntitySetRights.AllRead); dataServiceConfiguration.SetServiceActionAccessRule("*", ServiceActionRights.Invoke); dataServiceConfiguration.DataServiceBehavior.MaxProtocolVersion = ODataProtocolVersion.V4; if (actionProvider != null) { dataServiceSimulator.Providers.Add(typeof(IDataServiceActionProvider), actionProvider); } DataServiceStaticConfiguration staticConfiguration = new DataServiceStaticConfiguration(dataServiceSimulator.Instance.GetType(), metadataProvider); IDataServiceProviderBehavior providerBehavior = DataServiceProviderBehavior.CustomDataServiceProviderBehavior; DataServiceProviderWrapper providerWrapper = new DataServiceProviderWrapper( new DataServiceCacheItem( dataServiceConfiguration, staticConfiguration), metadataProvider, metadataProvider, dataServiceSimulator, false); dataServiceSimulator.Provider = providerWrapper; var model = new MetadataProviderEdmModel(providerWrapper, new DataServiceStreamProviderWrapper(dataServiceSimulator), DataServiceActionProviderWrapper.Create(dataServiceSimulator)); model.MetadataProvider.ProviderBehavior = providerBehavior; return(model); }
/// <summary> /// Apply the given configuration to the resource set. /// </summary> /// <param name="configuration">data service configuration instance.</param> /// <param name="provider">data service provider wrapper instance for accessibility validation.</param> public void ApplyConfiguration(DataServiceConfiguration configuration, DataServiceProviderWrapper provider) { #if DEBUG Debug.Assert(!this.isReadOnly, "Can only apply the configuration once."); #endif if (this.Kind == OperationKind.ServiceOperation) { this.serviceOperationRights = configuration.GetServiceOperationRights(this.ServiceOperation); } else { Debug.Assert(this.Kind == OperationKind.Action, "this.Kind == OperationKind.Action"); this.serviceActionRights = configuration.GetServiceActionRights(this.ServiceAction); } if ((this.Kind == OperationKind.ServiceOperation && (this.serviceOperationRights & ~ServiceOperationRights.OverrideEntitySetRights) != ServiceOperationRights.None) || (this.Kind == OperationKind.Action && this.serviceActionRights != Service.ServiceActionRights.None)) { if (this.operation.ResourceSet != null) { // If the result type is an entity type, we need to make sure its entity set is visible. // If the entity set is hidden, we need to make sure that we throw an exception. this.resourceSet = provider.TryResolveResourceSet(this.operation.ResourceSet.Name); if (this.resourceSet == null) { throw new InvalidOperationException(Strings.OperationWrapper_OperationResourceSetNotVisible(this.Name, this.operation.ResourceSet.Name)); } } else if (this.ResultSetPathExpression != null) { this.ResultSetPathExpression.InitializePathSegments(provider); } } #if DEBUG this.isReadOnly = true; #endif }
internal MetadataProviderEdmModel(DataServiceProviderWrapper provider, DataServiceOperationContext operationContext, DataServiceStreamProviderWrapper streamProviderWrapper) { this.metadataProvider = provider; this.operationContext = operationContext; this.streamProviderWrapper = streamProviderWrapper; this.schemaTypeCache = new Dictionary<string, IEdmSchemaType>(StringComparer.Ordinal); this.resourceTypesPerNamespaceCache = new Dictionary<string, HashSet<ResourceType>>(StringComparer.Ordinal); this.entityContainerCache = new Dictionary<string, MetadataProviderEdmEntityContainer>(StringComparer.Ordinal); this.primitiveOrComplexCollectionTypeCache = new Dictionary<ResourceType, IEdmCollectionType>(EqualityComparer<ResourceType>.Default); this.entityPrimitiveOrComplexCollectionTypeCache = new Dictionary<ResourceType, IEdmCollectionType>(EqualityComparer<ResourceType>.Default); this.derivedTypeMappings = new Dictionary<IEdmStructuredType, List<IEdmStructuredType>>(EqualityComparer<IEdmStructuredType>.Default); this.associationSetByKeyCache = new Dictionary<string, string>(StringComparer.Ordinal); Version version = this.metadataProvider.Configuration.DataServiceBehavior.MaxProtocolVersion.ToVersion(); this.SetDataServiceVersion(version); Version version2 = null; if (!MetadataProviderUtils.DataServiceEdmVersionMap.TryGetValue(version, out version2)) { this.SetEdmVersion(Microsoft.Data.Edm.Library.EdmConstants.EdmVersionLatest); } else { this.SetEdmVersion(version2); } }
private static ODataMessageWriterSettings CreateMessageWriterSettings(Uri serviceUri, DataServiceProviderWrapper provider, Version responseVersion, bool disableDisposeStream, ODataFormat format) { ODataMessageWriterSettings settings = new ODataMessageWriterSettings { BaseUri = serviceUri, Version = new ODataVersion?(CommonUtil.ConvertToODataVersion(responseVersion)), Indent = false, CheckCharacters = false, DisableMessageStreamDisposal = disableDisposeStream }; settings.EnableWcfDataServicesServerBehavior(provider.IsV1Provider); settings.SetContentType(format); return settings; }
/// <summary> /// Updates the current payload kind from the given query results if needed. This is to account for open-property values /// being either 'value' or 'binaryvalue' depending on the instance type. /// </summary> /// <param name="queryResults">The query results.</param> /// <param name="provider">The provider.</param> internal void UpdatePayloadKindFromValueIfNeeded(QueryResultInfo queryResults, DataServiceProviderWrapper provider) { // now determine the payload kind if (this.TargetKind == RequestTargetKind.OpenPropertyValue) { object element = queryResults.Current; ResourceType resourceType = WebUtil.GetResourceType(provider, element); Debug.Assert(resourceType != null, "resourceType != null, WebUtil.GetResourceType() should throw if it fails to resolve the resource type."); if (WebUtil.IsBinaryResourceType(resourceType)) { this.responsePayloadKind = ODataPayloadKind.BinaryValue; } else { this.responsePayloadKind = ODataPayloadKind.Value; } } }
/// <summary>Constructs a <see cref="MetadataProviderEdmModel"/> which wraps the given <see cref="DataServiceProviderWrapper"/> instance.</summary> /// <param name="provider"><see cref="DataServiceProviderWrapper"/> instance.</param> /// <param name="streamProviderWrapper">The stream provider wrapper instance.</param> /// <param name="actionProviderWrapper">The action provider wrapper instance.</param> internal MetadataProviderEdmModel(DataServiceProviderWrapper provider, DataServiceStreamProviderWrapper streamProviderWrapper, DataServiceActionProviderWrapper actionProviderWrapper) { Debug.Assert(provider != null, "provider != null"); this.metadataProvider = provider; this.streamProviderWrapper = streamProviderWrapper; this.actionProviderWrapper = actionProviderWrapper; this.schemaTypeCache = new Dictionary<string, IEdmSchemaType>(StringComparer.Ordinal); this.resourceTypesPerNamespaceCache = new Dictionary<string, HashSet<ResourceType>>(StringComparer.Ordinal); this.entityContainerCache = new Dictionary<string, MetadataProviderEdmEntityContainer>(StringComparer.Ordinal); this.primitiveOrComplexCollectionTypeCache = new Dictionary<ResourceType, IEdmCollectionType>(EqualityComparer<ResourceType>.Default); this.entityPrimitiveOrComplexCollectionTypeCache = new Dictionary<ResourceType, IEdmCollectionType>(EqualityComparer<ResourceType>.Default); this.derivedTypeMappings = new Dictionary<IEdmStructuredType, List<IEdmStructuredType>>(EqualityComparer<IEdmStructuredType>.Default); this.associationSetByKeyCache = new Dictionary<string, string>(StringComparer.Ordinal); this.operationsQualifiedNameCache = new Dictionary<string, List<MetadataProviderEdmOperation>>(StringComparer.Ordinal); this.operationWrapperOperationLookUp = new Dictionary<OperationWrapper, IEdmOperation>(EqualityComparer<OperationWrapper>.Default); // In the model, set the data service version and the edm version based on the MPV (this is the best estimate we have at this time). // This helps to set the nullability facet correctly when resolving type references. Note that, when the model is serialized for $metadata requests // in MetadataSerializer.WriteMetadataDocument, the DSV and the edm version on the model will be overwritten with the value computed by walking the // resource model. Version odataVersion = this.metadataProvider.Configuration.DataServiceBehavior.MaxProtocolVersion.ToVersion(); Version edmVersion = null; if (!MetadataProviderUtils.DataServiceEdmVersionMap.TryGetValue(odataVersion, out edmVersion)) { this.SetEdmVersion(Microsoft.OData.Edm.Library.EdmConstants.EdmVersionLatest); } else { this.SetEdmVersion(edmVersion); } // Initialize the minimum Edm Metadata Version to 4.0. this.MinMetadataEdmSchemaVersion = Microsoft.OData.Edm.Library.EdmConstants.EdmVersion4; this.AnnotationsCache = new VocabularyAnnotationCache(this); }
private static DataServiceProviderWrapper CreateProvider(out DataServiceConfiguration config, out DataServiceOperationContext operationContext) { var baseUri = new Uri("http://localhost"); var host = new DataServiceHostSimulator() { AbsoluteServiceUri = baseUri, AbsoluteRequestUri = new Uri(baseUri.AbsoluteUri + "/$metadata", UriKind.Absolute), RequestHttpMethod = "GET", RequestAccept = "application/xml+atom", RequestVersion = "4.0", RequestMaxVersion = "4.0", }; operationContext = new DataServiceOperationContext(host); var dataService = new DataServiceSimulator() { OperationContext = operationContext }; operationContext.InitializeAndCacheHeaders(dataService); DataServiceProviderSimulator providerSimulator = new DataServiceProviderSimulator(); providerSimulator.ContainerNamespace = "MyModel"; providerSimulator.ContainerName = "CustomersContainer"; ResourceType customerEntityType = new ResourceType( typeof(object), ResourceTypeKind.EntityType, null, "MyModel", "Customer", false) { CanReflectOnInstanceType = false }; ResourcePropertyKind idPropertyKind = ResourcePropertyKind.Primitive | ResourcePropertyKind.Key; ResourceProperty idProperty = new ResourceProperty( "Id", idPropertyKind, ResourceType.GetPrimitiveResourceType(typeof(int))) { CanReflectOnInstanceTypeProperty = false }; customerEntityType.AddProperty(idProperty); ResourcePropertyKind firstNamePropertyKind = ResourcePropertyKind.Primitive | ResourcePropertyKind.Key; ResourceProperty firstNameProperty = new ResourceProperty( "FirstName", firstNamePropertyKind, ResourceType.GetPrimitiveResourceType(typeof(string))) { CanReflectOnInstanceTypeProperty = false }; customerEntityType.AddProperty(firstNameProperty); customerEntityType.SetReadOnly(); providerSimulator.AddResourceType(customerEntityType); ResourceSet customerSet = new ResourceSet("Customers", customerEntityType); customerSet.SetReadOnly(); providerSimulator.AddResourceSet(customerSet); config = new DataServiceConfiguration(providerSimulator); config.SetEntitySetAccessRule("*", EntitySetRights.All); config.DataServiceBehavior.MaxProtocolVersion = ODataProtocolVersion.V4; IDataServiceProviderBehavior providerBehavior = DataServiceProviderBehavior.CustomDataServiceProviderBehavior; DataServiceStaticConfiguration staticConfig = new DataServiceStaticConfiguration(dataService.Instance.GetType(), providerSimulator); DataServiceProviderWrapper provider = new DataServiceProviderWrapper( new DataServiceCacheItem(config, staticConfig), providerSimulator, providerSimulator, dataService, false); dataService.ProcessingPipeline = new DataServiceProcessingPipeline(); dataService.Provider = provider; provider.ProviderBehavior = providerBehavior; dataService.ActionProvider = DataServiceActionProviderWrapper.Create(dataService); #if DEBUG dataService.ProcessingPipeline.SkipDebugAssert = true; #endif operationContext.RequestMessage.InitializeRequestVersionHeaders(VersionUtil.ToVersion(config.DataServiceBehavior.MaxProtocolVersion)); return provider; }
/// <summary> /// Converts the given value to the expected type as per json reader rules /// Make sure these rules are in [....] with jsonwriter. /// </summary> /// <param name="value">value to the converted</param> /// <param name="propertyName">name of the property whose value is getting converted</param> /// <param name="typeToBeConverted">clr type to which the value needs to be converted to</param> /// <param name="provider">underlying data service provider.</param> /// <returns>object which is in [....] with the properties type</returns> internal static object ConvertValues(object value, string propertyName, Type typeToBeConverted, DataServiceProviderWrapper provider) { if (value == null) { return null; } Type propertyType = Nullable.GetUnderlyingType(typeToBeConverted) ?? typeToBeConverted; try { string stringValue = value as string; if (stringValue != null) { if (propertyType == typeof(byte[])) { return Convert.FromBase64String(stringValue); } else if (propertyType == typeof(System.Data.Linq.Binary)) { return new System.Data.Linq.Binary(Convert.FromBase64String(stringValue)); } else if (propertyType == typeof(System.Xml.Linq.XElement)) { return System.Xml.Linq.XElement.Parse(stringValue, System.Xml.Linq.LoadOptions.PreserveWhitespace); } else if (propertyType == typeof(Guid)) { return new Guid(stringValue); } else { // For string types, we support conversion to all possible primitive types return Convert.ChangeType(value, propertyType, CultureInfo.InvariantCulture); } } else if (value is Int32) { int intValue = (int)value; if (propertyType == typeof(Int16)) { return Convert.ToInt16(intValue); } else if (propertyType == typeof(Byte)) { return Convert.ToByte(intValue); } else if (propertyType == typeof(SByte)) { return Convert.ToSByte(intValue); } else if (propertyType == typeof(Single)) { return Convert.ToSingle(intValue); } else if (propertyType == typeof(Double)) { return Convert.ToDouble(intValue); } else if (propertyType == typeof(Decimal) || propertyType == typeof(Int64)) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_ErrorInConvertingNumericValues(propertyName)); } else if (propertyType != typeof(Int32) && !provider.IsV1Provider) { // In V1, whenever we encountered a conversion which was unsafe, we would just return and most likely, it // would fail when the provider tried and set the value to the property since the type won't match. // Ideally, we should have thrown here, instead of allowing it to pass to the provider. // Now in V2, with provider becoming public, and another configuration option available (EnableTypeConversion), // it seems wrong to pass the value to the provider without doing the conversion when the EnableTypeConversion is set to true // But since we can't break the behaviour for V1 providers, we will be doing this only for custom V2 providers. throw DataServiceException.CreateBadRequestError(Strings.BadRequest_ErrorInConvertingNumericValues(propertyName)); } } else if (value is Double) { Double doubleValue = (Double)value; if (propertyType == typeof(Single)) { return Convert.ToSingle(doubleValue); } else if (propertyType != typeof(Double) && !provider.IsV1Provider) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_ErrorInConvertingNumericValues(propertyName)); } } } catch (Exception e) { if (WebUtil.IsCatchableExceptionType(e)) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_ErrorInConvertingPropertyValue(propertyName, propertyType.Name), e); } } // otherwise just return the value without doing any conversion return value; }
/// <summary>Initializes content for the serializer visitor</summary> /// <param name="nullValuedProperties">Null valued properties found during serialization</param> /// <param name="provider">Data Service provider used for rights verification.</param> private void InitializeVisitorContent(EpmContentSerializer.EpmNullValuedPropertyTree nullValuedProperties, DataServiceProviderWrapper provider) { this.visitorContent = new Dictionary<EpmTargetPathSegment, EpmCustomContentWriterNodeData>(ReferenceEqualityComparer<EpmTargetPathSegment>.Instance); // Initialize all the root's children's xml writers foreach (EpmTargetPathSegment subSegmentOfRoot in this.Root.SubSegments) { this.visitorContent.Add(subSegmentOfRoot, new EpmCustomContentWriterNodeData(subSegmentOfRoot, this.Element, nullValuedProperties, provider)); this.InitializeSubSegmentVisitorContent(subSegmentOfRoot, nullValuedProperties, provider); } }
/// <summary> /// Gets the result set for the operation. /// </summary> /// <param name="provider">Provider instance to resolve the path expression.</param> /// <param name="bindingSet">Binding resource set.</param> /// <returns>Returns the result resource set for the operation.</returns> internal ResourceSetWrapper GetResultSet(DataServiceProviderWrapper provider, ResourceSetWrapper bindingSet) { #if DEBUG Debug.Assert(this.isReadOnly, "Wrapper class has not been initialized yet."); #endif if (this.resourceSet != null) { Debug.Assert(this.resourceSet.ResourceSet == this.operation.ResourceSet, "this.resourceSet.ResourceSet == this.serviceOperation.ResourceSet"); Debug.Assert(this.ResultSetPathExpression == null, "this.ResultSetPathExpression == null"); return this.resourceSet; } if (this.ResultSetPathExpression != null) { Debug.Assert(provider != null, "provider != null"); if (bindingSet == null) { throw new InvalidOperationException(Strings.OperationWrapper_PathExpressionRequiresBindingSet(this.Name)); } ResourceSetWrapper resultSet = this.ResultSetPathExpression.GetTargetSet(provider, bindingSet); if (resultSet == null) { throw new InvalidOperationException(Strings.OperationWrapper_TargetSetFromPathExpressionNotNotVisible(this.Name, this.ResultSetPathExpression.PathExpression, bindingSet.Name)); } return resultSet; } return null; }
/// <summary>Initialize the visitor content for all of root's grandchildren and beyond</summary> /// <param name="subSegment">One of root's children</param> /// <param name="nullValuedProperties">Null valued properties found during serialization</param> /// <param name="provider">Data Service provider used for rights verification.</param> private void InitializeSubSegmentVisitorContent(EpmTargetPathSegment subSegment, EpmContentSerializer.EpmNullValuedPropertyTree nullValuedProperties, DataServiceProviderWrapper provider) { foreach (EpmTargetPathSegment segment in subSegment.SubSegments) { this.visitorContent.Add(segment, new EpmCustomContentWriterNodeData(this.visitorContent[subSegment], segment, this.Element, nullValuedProperties, provider)); this.InitializeSubSegmentVisitorContent(segment, nullValuedProperties, provider); } }
/// <summary> /// Constructor initializes the base class be identifying itself as a custom content serializer /// </summary> /// <param name="targetTree">Target tree containing mapping information</param> /// <param name="element">Object to be serialized</param> /// <param name="target">SyndicationItem to which content will be added</param> /// <param name="nullValuedProperties">Null valued properties found during serialization</param> /// <param name="provider">Data Service provider used for rights verification.</param> internal EpmCustomContentSerializer(EpmTargetTree targetTree, object element, SyndicationItem target, EpmContentSerializer.EpmNullValuedPropertyTree nullValuedProperties, DataServiceProviderWrapper provider) : base(targetTree, false, element, target) { this.InitializeVisitorContent(nullValuedProperties, provider); }