public void CtorMessageAndInner()
		{
			Exception inner = new Exception ("inner");
			var ex = new DataServiceException ("message", inner);

			Assert.AreEqual ("message", ex.Message);
			Assert.AreEqual (inner, ex.InnerException);
		}
		public void CtorStatusAndErrorMessageLanguageException()
		{
			Exception inner = new Exception ("inner");
			var ex = new DataServiceException (404, "error", "message", "language", inner);
			Assert.AreEqual ("message", ex.Message);
			Assert.AreEqual (404, ex.StatusCode);
			Assert.AreEqual ("language", ex.MessageLanguage);
			Assert.AreEqual (inner, ex.InnerException);
		}
Exemplo n.º 3
0
        /// <summary>
        /// Converts the given value to the expected type as per XML serializer rules.
        /// Make sure these rules are in sync with PlainXmlSerializer.
        /// </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>
        /// <returns>object which is in sync with the properties type</returns>
        internal static object ConvertValuesForXml(object value, string propertyName, Type typeToBeConverted)
        {
            Debug.Assert(WebUtil.IsPrimitiveType(typeToBeConverted), "WebUtil.IsPrimitiveType(typeToBeConverted)");
            Debug.Assert(value == null || value is string, "This method should be used only for converting string to a primitve value.");

            string stringValue = value as string;

            if (stringValue != null)
            {
                try
                {
                    value = WebConvert.StringToPrimitive(stringValue, typeToBeConverted);
                }
                catch (FormatException e)
                {
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequest_ErrorInConvertingPropertyValue(propertyName, typeToBeConverted), e);
                }
            }

            return(value);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Override the HandleException method to throw 400 Bad Request
        /// exception to the client side.
        /// </summary>
        /// <param name="args">The HandleException argument</param>
        protected override void HandleException(HandleExceptionArgs args)
        {
            // Check if the InnerException is null
            if (args.Exception.InnerException != null)
            {
                // Convert the InnerException to DataServiceException
                DataServiceException ex = args.Exception.InnerException as
                                          DataServiceException;

                // Check if the InnerException is in type of
                // DataServiceException and the StatusCode is
                // 400(Bad Request)
                if (ex != null && ex.StatusCode == 400)
                {
                    // Return the DataServiceException to the client
                    args.Exception = ex;
                }
            }

            base.HandleException(args);
        }
        protected void setModelStateErrors(DataServiceException ex)
        {
            if (ex.DataServiceExceptionData != null && !String.IsNullOrWhiteSpace(ex.DataServiceExceptionData.GeneralMessage))
            {
                ModelState.AddModelError("ErrorGeneralMessage", ex.DataServiceExceptionData.GeneralMessage);
                errorGeneralMessage = ex.DataServiceExceptionData.GeneralMessage;
            }


            if (ex.DataServiceExceptionData != null && ex.DataServiceExceptionData.Messages != null)
            {
                foreach (string name in ex.DataServiceExceptionData.Messages.Keys)
                {
                    IList <string> list = ex.DataServiceExceptionData.Messages[name];
                    foreach (string msg in list)
                    {
                        ModelState.AddModelError(name, msg);
                    }
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Sets a resource reference to resource referenced by a URL.
        /// </summary>
        /// <param name="entityResource">The entity resource to set the resource reference on.</param>
        /// <param name="navigationProperty">The navigation property for which to set the reference to null.</param>
        /// <param name="url">The URL which points to the resource to set as the value of the navigation property.</param>
        private void SetResourceReferenceToUrl(object entityResource, ResourceProperty navigationProperty, string url)
        {
            Debug.Assert(entityResource != null, "entityResource != null");
            Debug.Assert(navigationProperty != null, "navigationProperty != null");

            // Update the object count when you are performing a bind operation.
            this.CheckAndIncrementObjectCount();

            // Get the referenced resource.
            Uri referencedUri = RequestUriProcessor.GetAbsoluteUriFromReference(url, this.Service.OperationContext);
            RequestDescription requestDescription = RequestUriProcessor.ProcessRequestUri(referencedUri, this.Service, true /*internalQuery*/);

            // ATOM deserializer checks that the url doesn't point to a collection. If it does it will ignore the link.
            if (this.IsAtomRequest && !requestDescription.IsSingleResult)
            {
                if (navigationProperty != null &&
                    navigationProperty.Kind == ResourcePropertyKind.ResourceReference)
                {
                    throw DataServiceException.CreateBadRequestError(Microsoft.OData.Service.Strings.BadRequest_LinkHrefMustReferToSingleResource(navigationProperty.Name));
                }

                return;
            }

            // Get the resource
            object referencedResource = this.Service.GetResource(requestDescription, requestDescription.SegmentInfos.Count - 1, null);

            if (navigationProperty.Kind == ResourcePropertyKind.ResourceReference)
            {
                this.Updatable.SetReference(entityResource, navigationProperty.Name, referencedResource);
            }
            else
            {
                Debug.Assert(navigationProperty.Kind == ResourcePropertyKind.ResourceSetReference, "Only navigation properties are allowed in this method.");

                // If we are to set the resource to a collection property it must not be null (so check for nulls), otherwise do allow nulls for backward compatibility.
                WebUtil.CheckResourceExists(referencedResource != null, requestDescription.LastSegmentInfo.Identifier);
                this.Updatable.AddReferenceToCollection(entityResource, navigationProperty.Name, referencedResource);
            }
        }
Exemplo n.º 7
0
        /// <summary>Applies a property from the reader to the specified resource.</summary>
        /// <param name='reader'>XmlReader to read from.</param>
        /// <param name='propertyName'>Name of property to set on the specified resource.</param>
        /// <param name='resourceType'>Type of resource.</param>
        /// <param name='resource'>Resource to set value on.</param>
        private void ApplyProperty(XmlReader reader, string propertyName, ResourceType resourceType, object resource)
        {
            Debug.Assert(reader != null, "reader != null");
            Debug.Assert(propertyName != null, "propertyName != null");
            Debug.Assert(resourceType != null, "resourceType != null");
            Debug.Assert(resource != null, "resource != null");

            ResourceProperty property    = resourceType.TryResolvePropertyName(propertyName);
            bool             ignoreValue = false;

            if (property == null)
            {
                if (resourceType.IsOpenType == false)
                {
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidPropertyNameSpecified(propertyName, resourceType.FullName));
                }
            }
            else
            {
                if (this.Update && property.IsOfKind(ResourcePropertyKind.Key))
                {
                    ignoreValue = true;
                }
            }

            object propertyValue = this.ReadPropertyWithType(reader, propertyName, property);

            if (!ignoreValue)
            {
                if (property == null)
                {
                    Deserializer.SetOpenPropertyValue(resource, propertyName, propertyValue, this.Service);
                }
                else
                {
                    Deserializer.SetPropertyValue(property, resource, propertyValue, this.ContentFormat, this.Service);
                }
            }
        }
Exemplo n.º 8
0
        internal void SetValue(object instance, object propertyValue, ResourceProperty resourceProperty)
        {
            MethodInfo setMethod = this.GetPropertyInfo(resourceProperty).GetSetMethod();

            if (setMethod == null)
            {
                throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.BadRequest_PropertyValueCannotBeSet(resourceProperty.Name));
            }
            try
            {
                setMethod.Invoke(instance, new object[] { propertyValue });
            }
            catch (TargetInvocationException exception)
            {
                ErrorHandler.HandleTargetInvocationException(exception);
                throw;
            }
            catch (ArgumentException exception2)
            {
                throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.BadRequest_ErrorInSettingPropertyValue(resourceProperty.Name), exception2);
            }
        }
Exemplo n.º 9
0
        /// <summary>Reads the number from the reader.</summary>
        /// <returns>reads the clr number object</returns>
        private object ReadNumber()
        {
            char ch = this.ReadNextCharacter();

            StringBuilder sb = new StringBuilder();

            sb.Append(ch);
            while (true)
            {
                ch = this.PeekNextSignificantCharacter();

                if (Char.IsDigit(ch) || (ch == '.') || (ch == 'E') || (ch == 'e') || (ch == '-') || (ch == '+'))
                {
                    this.ReadNextCharacter();
                    sb.Append(ch);
                }
                else
                {
                    break;
                }
            }

            string s = sb.ToString();
            Double doubleValue;
            int    intValue;

            // We will first try and convert this int32. If this succeeds, great. Otherwise, we will try
            // and convert this into a double.
            if (Int32.TryParse(s, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out intValue))
            {
                return(intValue);
            }
            else if (Double.TryParse(s, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out doubleValue))
            {
                return(doubleValue);
            }

            throw DataServiceException.CreateBadRequestError(Strings.BadRequestStream_InvalidContent);
        }
        protected sealed override object Deserialize(System.Data.Services.SegmentInfo segmentInfo)
        {
            object obj2;

            try
            {
                obj2 = this.Read(segmentInfo);
            }
            catch (XmlException exception)
            {
                throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.DataServiceException_GeneralError, exception);
            }
            catch (ODataContentTypeException exception2)
            {
                throw new DataServiceException(0x19f, null, System.Data.Services.Strings.DataServiceException_UnsupportedMediaType, null, exception2);
            }
            catch (ODataException exception3)
            {
                throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.DataServiceException_GeneralError, exception3);
            }
            return(obj2);
        }
        public void When_DataServiceException_is_serialized_all_public_instance_data_is_saved()
        {
            // Arrange
            const int    expectedStatusCode  = 705;
            const string expectedErrorCode   = "A47";
            const string expectedMessage     = "Server error.";
            const string expectedMessageLang = "en";

            var sut = new DataServiceException(
                expectedStatusCode, expectedErrorCode, expectedMessage, expectedMessageLang, innerException: null);

            // Act
            var ds = SerializeAndDeserializeDataServiceException(sut);

            // Assert
            Assert.AreNotSame(sut, ds);
            Assert.AreEqual(sut.GetType(), ds.GetType());
            Assert.AreEqual(expectedMessage, ds.Message);
            Assert.AreEqual(expectedStatusCode, ds.StatusCode);
            Assert.AreEqual(expectedErrorCode, ds.ErrorCode);
            Assert.AreEqual(expectedMessageLang, ds.MessageLanguage);
        }
Exemplo n.º 12
0
        private void ExecutionCompletionEventHandler(IAsyncResult ar)
        {
            Exception dataServiceException;

            lock (this.syncObject)
            {
                this.timer.Stop();
                this.isExecutionCompleted = true;
                if (!this.isExceedsMaxExecutionTime)
                {
                    dataServiceException = PSCommand.CheckPowershellForException(this.cmdletInfo.CmdletName, this.commandType, this.powerShell);
                }
                else
                {
                    object[] cmdletName = new object[1];
                    cmdletName[0]        = this.cmdletInfo.CmdletName;
                    dataServiceException = new DataServiceException(0x193, ExceptionHelpers.GetDataServiceExceptionMessage(HttpStatusCode.Forbidden, Resources.CmdletExecutionQuotaExceeded, cmdletName));
                    TraceHelper.Current.CommandExecutionTimeExceeded(this.cmdletInfo.CmdletName, this.runspace.Borrower.Name, DataServiceController.Current.Configuration.PowerShell.Quotas.MaxExecutionTime, 0);
                    DataServiceController.Current.PerfCounters.SystemQuotaViolationsPerSec.Increment();
                    DataServiceController.Current.QuotaSystem.SystemQuotaViolation.Increment();
                }
                if (this.output != null && dataServiceException == null)
                {
                    foreach (PSObject pSObject in this.output)
                    {
                        if (pSObject == null)
                        {
                            continue;
                        }
                        DSResource dSResource = SerializerBase.SerializeEntity(pSObject, this.entityType);
                        this.dataStore.Add(dSResource);
                    }
                }
                this.dataStore.Completed(dataServiceException);
                this.powerShell.Trace();
            }
            this.Dispose();
        }
Exemplo n.º 13
0
        internal object HandlePutRequest()
        {
            object             requestValue    = null;
            object             entityResource  = null;
            ResourceSetWrapper entityContainer = null;
            string             str;
            Encoding           encoding;

            HttpProcessUtility.ReadContentType(this.Service.OperationContext.Host.RequestContentType, out str, out encoding);
            System.Data.Services.RequestDescription requestDescription = this.RequestDescription;
            if (((requestDescription.TargetKind == RequestTargetKind.MediaResource) || (requestDescription.TargetKind == RequestTargetKind.OpenPropertyValue)) || (requestDescription.TargetKind == RequestTargetKind.PrimitiveValue))
            {
                requestValue = this.Deserialize(requestDescription.LastSegmentInfo);
            }
            else if (requestDescription.LinkUri)
            {
                Uri    referencedUri        = (Uri)this.Deserialize(null);
                object targetResourceToBind = this.GetTargetResourceToBind(referencedUri, true);
                entityResource  = HandleBindOperation(requestDescription, targetResourceToBind, this.Service, this.Tracker);
                entityContainer = requestDescription.LastSegmentInfo.TargetContainer;
            }
            else
            {
                requestValue = this.ReadEntity();
                if (((requestValue == null) && requestDescription.LastSegmentInfo.HasKeyValues) && (requestDescription.TargetSource == RequestTargetSource.EntitySet))
                {
                    throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.BadRequest_CannotSetTopLevelResourceToNull(requestDescription.ResultUri.AbsoluteUri));
                }
            }
            if (!requestDescription.LinkUri && IsQueryRequired(requestDescription, requestValue))
            {
                object resourceToBeModified = GetResourceToModify(requestDescription, this.Service, false, out entityResource, out entityContainer, true);
                this.Tracker.TrackAction(entityResource, entityContainer, UpdateOperations.Change);
                ModifyResource(requestDescription, resourceToBeModified, requestValue, this.Service);
            }
            return(entityResource ?? requestValue);
        }
Exemplo n.º 14
0
        /// <summary>
        /// Converts the given text into an arrayList
        /// </summary>
        /// <returns>returns the arraylist containing the list of objects</returns>
        private ArrayList ReadArray()
        {
            ArrayList array = new ArrayList();

            // Consume the '['
            this.ReadNextCharacter();

            while (true)
            {
                char ch = this.PeekNextSignificantCharacter();
                if (ch == '\0')
                {
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequestStream_InvalidContent);
                }

                if (ch == ']')
                {
                    this.ReadNextCharacter();
                    return(array);
                }

                if (array.Count != 0)
                {
                    if (ch != ',')
                    {
                        throw DataServiceException.CreateBadRequestError(Strings.BadRequestStream_MissingArrayMemberSeperator);
                    }
                    else
                    {
                        this.ReadNextCharacter();
                    }
                }

                object item = this.ReadValue();
                array.Add(item);
            }
        }
Exemplo n.º 15
0
        protected void setModelStateErrors(DataServiceException ex)
        {
            if (ex.DataServiceExceptionData != null && !String.IsNullOrWhiteSpace(ex.DataServiceExceptionData.GeneralMessage))
            {
                ModelState.AddModelError("ErrorGeneralMessage", ex.DataServiceExceptionData.GeneralMessage);
                errorGeneralMessage = ex.DataServiceExceptionData.GeneralMessage;
            }


            if (ex.DataServiceExceptionData != null && ex.DataServiceExceptionData.Messages != null)
            {
                foreach (string name in ex.DataServiceExceptionData.Messages.Keys)
                {
                    IList <string> list = ex.DataServiceExceptionData.Messages[name];
                    foreach (string msg in list)
                    {
                        ModelState.AddModelError(name, msg);
                    }
                }
            }

            if (ex.DataServiceExceptionData != null && ex.DataServiceExceptionData.IndexMessages != null)
            {
                foreach (int index in ex.DataServiceExceptionData.IndexMessages.Keys)
                {
                    Dictionary <string, List <string> > d = ex.DataServiceExceptionData.IndexMessages[index];
                    foreach (string name in d.Keys)
                    {
                        IList <string> list = d[name];
                        foreach (string msg in list)
                        {
                            ModelState.AddModelError(String.Format("{0}[{1}]", name, index), msg);
                        }
                    }
                }
            }
        }
Exemplo n.º 16
0
        public void ProcessException(HandleExceptionArgs args)
        {
            this.plainException = args.Exception;

            DataServiceException dse = args.Exception as DataServiceException;

            if (dse != null)
            {
                if (dse.StatusCode == (int)HttpStatusCode.NotModified)
                {
                    // 304 is not a failure, we let the server handle it.
                    return;
                }
            }

            if (AllowServerToSerializeException.Value)
            {
                this.ResponseStatusCode  = args.ResponseStatusCode;
                this.ResponseContentType = args.ResponseContentType;
            }
            else
            {
                // set the right status code and content type
                this.ResponseStatusCode  = args.ResponseStatusCode;
                this.ResponseContentType = "text/plain";

                // write the error message in the payload
                StreamWriter writer = new StreamWriter(this.responseStream);
                writer.WriteLine("TestServiceHost.ProcessException special pre-writing handling:");
                writer.Write(args.Exception.Message);
                writer.Flush();

                // Re-throw the exception. This makes things consistent for tests,
                // which except an exception from HttpWebRequest.StatusCode <> 200 as well.
                throw new WebException("WebException from TestServiceHost.ProcessException", args.Exception);
            }
        }
Exemplo n.º 17
0
 /// <summary>
 /// Reads the given payload and return the top level object.
 /// </summary>
 /// <param name="segmentInfo">Info about the object being created.</param>
 /// <returns>Instance of the object created.</returns>
 protected override sealed object Deserialize(SegmentInfo segmentInfo)
 {
     try
     {
         return(this.Read(segmentInfo));
     }
     catch (System.Xml.XmlException exception)
     {
         throw DataServiceException.CreateBadRequestError(Microsoft.OData.Service.Strings.DataServiceException_GeneralError, exception);
     }
     catch (ODataContentTypeException exception)
     {
         throw new DataServiceException(
                   415,
                   null,
                   Microsoft.OData.Service.Strings.DataServiceException_UnsupportedMediaType,
                   null,
                   exception);
     }
     catch (ODataException exception)
     {
         throw DataServiceException.CreateBadRequestError(Microsoft.OData.Service.Strings.DataServiceException_GeneralError, exception);
     }
 }
Exemplo n.º 18
0
        /// <summary>
        /// Applies an entry which is the content of a navigation property to the specified entity resource.
        /// </summary>
        /// <param name="navigationProperty">The navigation property for which the feed was specified.</param>
        /// <param name="targetResourceSet">The resource set of the target of the navigation property.</param>
        /// <param name="entityResource">The entity resource to apply the value to.</param>
        /// <param name="entry">The entry to apply. This can be null if the null value should be applied.</param>
        /// <remarks>Note that the targetResourceSet will be filled for non-ATOM formats, but it will be null for ATOM.</remarks>
        private void ApplyEntryInNavigationProperty(
            ResourceProperty navigationProperty,
            ResourceSetWrapper targetResourceSet,
            object entityResource,
            ODataEntry entry)
        {
            Debug.Assert(
                navigationProperty != null && navigationProperty.TypeKind == ResourceTypeKind.EntityType,
                "navigationProperty != null && navigationProperty.TypeKind == ResourceTypeKind.EntityType");
            Debug.Assert(
                navigationProperty.Kind == ResourcePropertyKind.ResourceReference,
                "ODataLib reader should never report an entry for a collection navigation property.");
            Debug.Assert(targetResourceSet != null, "targetResourceSet != null");
            Debug.Assert(entityResource != null, "entityResource != null");

            // Deep insert is not allowed in updates, unless it's JSON and the deep insert is a null value.
            if ((this.IsAtomRequest || entry != null) && this.Update)
            {
                throw DataServiceException.CreateBadRequestError(Microsoft.OData.Service.Strings.BadRequest_DeepUpdateNotSupported);
            }

            if (entry == null)
            {
                this.SetResourceReferenceToNull(entityResource, navigationProperty);
            }
            else
            {
                Debug.Assert(targetResourceSet != null, "targetResourceSet != null");
                SegmentInfo propertySegmentInfo = CreateSegment(navigationProperty, navigationProperty.Name, targetResourceSet, true /* singleResult */);
                Debug.Assert(propertySegmentInfo.TargetKind != RequestTargetKind.OpenProperty, "Open navigation properties are not supported on OpenTypes.");

                object childEntityResource = this.CreateNestedEntityAndApplyProperties(propertySegmentInfo, entry);

                this.Updatable.SetReference(entityResource, navigationProperty.Name, childEntityResource);
            }
        }
Exemplo n.º 19
0
        private void CreateEntityResource(System.Data.Services.SegmentInfo segmentInfo, ODataEntry entry, ODataEntryAnnotation entryAnnotation, bool topLevel)
        {
            object obj2;

            base.CheckAndIncrementObjectCount();
            ResourceType entryResourceType = this.GetEntryResourceType(entry, segmentInfo.TargetResourceType);

            base.UpdateAndCheckRequestResponseDSV(entryResourceType, topLevel);
            if (segmentInfo.TargetKind == RequestTargetKind.OpenProperty)
            {
                throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.OpenNavigationPropertiesNotSupportedOnOpenTypes(segmentInfo.Identifier));
            }
            if (base.Update)
            {
                obj2 = base.GetObjectFromSegmentInfo(entryResourceType, segmentInfo, true, true, base.Service.OperationContext.Host.HttpVerb == HttpVerbs.PUT);
            }
            else
            {
                DataServiceConfiguration.CheckResourceRights(segmentInfo.TargetContainer, EntitySetRights.WriteAppend);
                obj2 = base.Updatable.CreateResource(segmentInfo.TargetContainer.Name, entryResourceType.FullName);
            }
            entryAnnotation.EntityResource     = obj2;
            entryAnnotation.EntityResourceType = entryResourceType;
        }
Exemplo n.º 20
0
        /// <summary>
        /// Read the link media type and validate for non open property types
        /// </summary>
        /// <param name="mediaType">media type as specified on the link element.</param>
        /// <param name="property">property which the link represents.</param>
        /// <returns>returns the type parameters specified in the media link.</returns>
        private static string ValidateTypeParameterForNonOpenTypeProperties(string mediaType, ResourceProperty property)
        {
            string typeParameterValue = null;

            if (!String.IsNullOrEmpty(mediaType))
            {
                string   mime;
                Encoding encoding;
                KeyValuePair <string, string>[] contentTypeParameters = HttpProcessUtility.ReadContentType(mediaType, out mime, out encoding);
                if (mime != XmlConstants.MimeApplicationAtom)
                {
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequest_MimeTypeMustBeApplicationAtom(mime, XmlConstants.MimeApplicationAtom));
                }

                // If the type parameter is specified, make sure its correct. We do the validation for known properties here
                // and for open-properties, the validation is done if the link is expanded. Otherwise, there is no good way of
                // doing the validation.
                typeParameterValue = HttpProcessUtility.GetParameterValue(contentTypeParameters, XmlConstants.AtomTypeAttributeName);
                if (!String.IsNullOrEmpty(typeParameterValue) && property != null)
                {
                    if (property.Kind == ResourcePropertyKind.ResourceReference)
                    {
                        if (typeParameterValue != XmlConstants.AtomEntryElementName)
                        {
                            throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidTypeParameterSpecifiedInMimeType(typeParameterValue, XmlConstants.AtomEntryElementName));
                        }
                    }
                    else if (typeParameterValue != XmlConstants.AtomFeedElementName)
                    {
                        throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidTypeParameterSpecifiedInMimeType(typeParameterValue, XmlConstants.AtomFeedElementName));
                    }
                }
            }

            return(typeParameterValue);
        }
Exemplo n.º 21
0
        /// <summary>
        /// Returns collection item type name or null if the provided type name is not a collection.
        /// </summary>
        /// <param name="typeName">Collection type name read from payload.</param>
        /// <param name="isNested">Whether it is a nested (recursive) call.</param>
        /// <returns>Collection element type name or null if not a collection.</returns>
        /// <remarks>
        /// The following rules are used for collection type names:
        /// - it has to start with "Collection(" and end with ")" - trailing and leading whitespaces make the type not to be recognized as collection.
        /// - there is to be no characters (including whitespaces) between "Collection" and "(" - otherwise it won't be recognized as collection
        /// - collection item type name has to be a non-empty string - i.e. "Collection()" won't be recognized as collection
        /// - nested collection - e.g. "Collection(Collection(Edm.Int32))" - are not supported - we will throw
        /// Note the following are examples of valid type names which are not collection:
        /// - "Collection()"
        /// - " Collection(Edm.Int32)"
        /// - "Collection (Edm.Int32)"
        /// - "Collection("
        /// If the type name is not recognized as a collection it will be eventually passed to type resolver if it is not a known primitive type.
        /// </remarks>
        internal static string GetCollectionItemTypeName(string typeName, bool isNested)
        {
            // to be recognized as a collection wireTypeName must not be null, has to start with "Collection(" and end with ")" and must not be "Collection()"
            if (typeName != null && typeName.StartsWith(XmlConstants.CollectionTypeQualifier + "(", StringComparison.Ordinal) && typeName[typeName.Length - 1] == ')' && typeName.Length != (XmlConstants.CollectionTypeQualifier + "()").Length)
            {
                if (isNested)
                {
#if ODATA_CLIENT
                    throw Error.InvalidOperation(Strings.ClientType_CollectionOfCollectionNotSupported);
#else
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequest_CollectionOfCollectionNotSupported);
#endif
                }

                string innerTypeName = typeName.Substring((XmlConstants.CollectionTypeQualifier + "(").Length, typeName.Length - (XmlConstants.CollectionTypeQualifier + "()").Length);

                // Check if it is not a nested collection and throw if it is
                GetCollectionItemTypeName(innerTypeName, true);

                return(innerTypeName);
            }

            return(null);
        }
        /// <summary>
        /// Reads the input request payload and returns the WCF DS value representation of it.
        /// </summary>
        /// <param name="segmentInfo">Info about the request to read. For entity reference requests this is null.</param>
        /// <returns>The WCF DS representation of the value read. For entity reference link this is the Uri of the link.</returns>
        protected override object Read(SegmentInfo segmentInfo)
        {
            Debug.Assert(segmentInfo == null, "segmentInfo == null");
            Debug.Assert(this.RequestDescription.LinkUri, "The EntityReferenceLinkDeserializer only supports $ref payloads.");

            ODataEntityReferenceLink entityReferenceLink = this.MessageReader.ReadEntityReferenceLink();

            Debug.Assert(entityReferenceLink != null, "ReadEntityReferenceLink should never return null.");
            Uri entityReferenceUri = entityReferenceLink.Url;

            Debug.Assert(entityReferenceUri != null, "The Url of the entity reference link should never be null.");
            AssertReaderFormatIsExpected(this.MessageReader, ODataFormat.Json);

            // We must fail on empty URI
            string entityReferenceUriAsString = UriUtil.UriToString(entityReferenceUri);

            if (string.IsNullOrEmpty(entityReferenceUriAsString))
            {
                throw DataServiceException.CreateBadRequestError(Microsoft.OData.Service.Strings.BadRequest_MissingUriForLinkOperation);
            }

            // Resolve the URI against the service
            return(RequestUriProcessor.GetAbsoluteUriFromReference(entityReferenceUri, this.Service.OperationContext.AbsoluteServiceUri));
        }
Exemplo n.º 23
0
        /// <summary>
        /// Converts the given value to the expected type as per json reader rules
        /// Make sure these rules are in sync 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 sync 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);
        }
Exemplo n.º 24
0
		public PagedMessage GetPage(DataMessage dataMessage) {
			int sequenceId = (int)dataMessage.headers[DataMessage.SequenceIdHeader];
			Sequence sequence = GetSequence(sequenceId);
			if (sequence != null)
				return GetPagedMessage(dataMessage, sequence);
			else {
				DataServiceException dse = new DataServiceException(string.Format("Sequence {0} in destination {1} was not found", sequenceId, dataMessage.destination));
				throw dse;
			}
		}
Exemplo n.º 25
0
        /// <summary>
        /// Converts the given value into the right type
        /// </summary>
        /// <returns>returns the clr object instance which </returns>
        public object ReadValue()
        {
            this.RecurseEnter();

            object value     = null;
            bool   allowNull = false;

            char ch = this.PeekNextSignificantCharacter();

            if (ch == '[')
            {
                value = this.ReadArray();
            }
            else if (ch == '{')
            {
                value = this.ReadObject();
            }
            else if ((ch == '\'') || (ch == '"'))
            {
                bool   hasLeadingSlash;
                string s = this.ReadString(out hasLeadingSlash);
                value = s; // may be overwritten with a DateTime if ends up being a date/time

                // Atlas format for date/time
                if (hasLeadingSlash)
                {
                    Match match = DateTimeFormat.Match(s);
                    if (match.Success)
                    {
                        string ticksStr = match.Groups["ticks"].Value;

                        long ticks;
                        if (long.TryParse(ticksStr, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out ticks))
                        {
                            // The javascript ticks start from 1/1/1970 but FX DateTime ticks start from 1/1/0001
                            DateTime dateTime = new DateTime(ticks * 10000 + JsonWriter.DatetimeMinTimeTicks, DateTimeKind.Utc);
                            value = dateTime;
                        }
                    }
                }
            }
            else if (Char.IsDigit(ch) || (ch == '-') || (ch == '.'))
            {
                value = this.ReadNumber();
            }
            else if ((ch == 't') || (ch == 'f'))
            {
                value = this.ReadBoolean();
            }
            else if (ch == 'n')
            {
                this.ReadNull();
                allowNull = true;
            }

            if ((value == null) && (allowNull == false))
            {
                throw DataServiceException.CreateBadRequestError(Strings.BadRequestStream_InvalidContent);
            }

            this.RecurseLeave();

            // if there is junk data at the end of the stream ex. {...}junk
            // then an exception will be thrown.
            if (this.recursionDepth == 0)
            {
                // at the end of the stream
                if (this.PeekNextSignificantCharacter() != '\0')
                {
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequestStream_InvalidContent);
                }
            }

            return(value);
        }
Exemplo n.º 26
0
        /// <summary>
        /// Read the string value from the reader
        /// </summary>
        /// <param name="hasLeadingSlash">out parameter indicating whether the string has a leading slash or not</param>
        /// <returns>returns the string value read from the reader</returns>
        private string ReadString(out bool hasLeadingSlash)
        {
            char endQuoteCharacter = this.ReadNextCharacter();
            char ch = this.ReadNextCharacter();

            hasLeadingSlash = (ch == '\\') ? true : false;
            StringBuilder sb = new StringBuilder();

            while (true)
            {
                if (ch == '\\')
                {
                    ch = this.ReadNextCharacter();

                    // From 4627, section 2.5: Strings, here's the list of characters that we should be escaping
                    if (ch == 'u')
                    {
                        string unicodeSequence = this.GetCharacters(4);
                        Debug.Assert(unicodeSequence != null, "unicodeSequence != null");
                        ch = (char)Int32.Parse(unicodeSequence, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
                        sb.Append(ch);
                    }
                    else if (ch == 'b')
                    {
                        sb.Append('\b');
                    }
                    else if (ch == 'f')
                    {
                        sb.Append('\f');
                    }
                    else if (ch == 'n')
                    {
                        sb.Append('\n');
                    }
                    else if (ch == 'r')
                    {
                        sb.Append('\r');
                    }
                    else if (ch == 't')
                    {
                        sb.Append('\t');
                    }
                    else if (ch == '\\' || ch == '\"' || ch == '/' || ch == '\'')
                    {
                        sb.Append(ch);
                    }
                    else
                    {
                        throw DataServiceException.CreateBadRequestError(Strings.BadRequestStream_InvalidJsonUnrecognizedEscapeSequence);
                    }
                }
                else
                if (ch == endQuoteCharacter)
                {
                    return(sb.ToString());
                }
                else
                {
                    sb.Append(ch);
                }

                ch = this.ReadNextCharacter();
            }
        }
Exemplo n.º 27
0
        /// <summary>
        /// Create the object given the list of the properties. One of the properties will be __metadata property
        /// which will contain type information
        /// </summary>
        /// <param name="jsonObject">list of the properties and values specified in the payload</param>
        /// <param name="segmentInfo">info about the object being created</param>
        /// <param name="topLevel">true if the current object is a top level one, otherwise false</param>
        /// <param name="existingRelationship">does this resource already binded to its parent</param>
        /// <returns>instance of the object created</returns>
        private object CreateObject(object jsonObject, SegmentInfo segmentInfo, bool topLevel, out bool existingRelationship)
        {
            this.RecurseEnter();

            existingRelationship = true;
            bool         existingResource = true;
            object       resource         = null;
            ResourceType resourceType;

            JsonReader.JsonObjectRecords jsonObjectRecord;

            if (topLevel)
            {
                // Every top level json content must be JsonObjectRecords - primitive, complex or entity
                jsonObjectRecord = jsonObject as JsonReader.JsonObjectRecords;
                if (jsonObjectRecord == null)
                {
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequestStream_InvalidResourceEntity);
                }

                object nonEntityResource;
                if (HandleTopLevelNonEntityProperty(jsonObjectRecord, segmentInfo, out nonEntityResource))
                {
                    // if the segment refers to primitive type, then return the value
                    if (segmentInfo.TargetKind == RequestTargetKind.Primitive ||
                        nonEntityResource == null ||
                        (segmentInfo.TargetKind == RequestTargetKind.OpenProperty && WebUtil.IsPrimitiveType(nonEntityResource.GetType())))
                    {
                        return(nonEntityResource);
                    }

                    jsonObject = nonEntityResource;
                }
            }
            else if (
                jsonObject == null ||
                (segmentInfo.TargetKind == RequestTargetKind.OpenProperty && WebUtil.IsPrimitiveType(jsonObject.GetType())) ||
                segmentInfo.TargetKind == RequestTargetKind.Primitive)
            {
                // For reference properties, we do not know if there was already some relationship setup
                // By setting it to null, we are unbinding the old relationship and hence existing relationship
                // is false
                // For open properties, if its null, there is no way we will be able to deduce the type
                existingRelationship = false;
                return(jsonObject);
            }

            // Otherwise top level json content must be JsonObjectRecords, since we don't allow multiple inserts
            // at the top level
            jsonObjectRecord = jsonObject as JsonReader.JsonObjectRecords;
            if (jsonObjectRecord == null)
            {
                throw DataServiceException.CreateBadRequestError(Strings.BadRequestStream_InvalidResourceEntity);
            }

            ResourceType targetResourceType = null;

            if (segmentInfo.TargetKind != RequestTargetKind.OpenProperty)
            {
                targetResourceType = segmentInfo.TargetResourceType;
                Debug.Assert(targetResourceType != null, "Should be able to resolve type for well known segments");
                Debug.Assert(
                    targetResourceType.ResourceTypeKind == ResourceTypeKind.ComplexType || targetResourceType.ResourceTypeKind == ResourceTypeKind.EntityType,
                    "targetType must be entity type or complex type");
            }

            // Get the type and uri from the metadata element, if specified
            string uri;
            bool   metadataElementSpecified;

            resourceType = this.GetTypeAndUriFromMetadata(
                jsonObjectRecord.Entries,
                targetResourceType,
                topLevel,
                out uri,
                out metadataElementSpecified);

            Debug.Assert((resourceType != null && resourceType.ResourceTypeKind != ResourceTypeKind.Primitive) || uri != null, "Either uri or resource type must be specified");

            if ((uri != null || resourceType.ResourceTypeKind == ResourceTypeKind.EntityType) && segmentInfo.TargetKind == RequestTargetKind.OpenProperty)
            {
                // Open navigation properties are not supported on OpenTypes.
                throw DataServiceException.CreateBadRequestError(Strings.OpenNavigationPropertiesNotSupportedOnOpenTypes(segmentInfo.Identifier));
            }

            this.CheckAndIncrementObjectCount();
            if ((resourceType != null && resourceType.ResourceTypeKind != ResourceTypeKind.ComplexType) ||
                uri != null)
            {
                // For inserts/updates, its okay not to specify anything in the payload.
                // Someone might just want to create a entity with default values or
                // merge nothing or replace everything with default values.
                if (this.Update)
                {
                    if (!topLevel)
                    {
                        if (metadataElementSpecified && jsonObjectRecord.Count > 1 ||
                            !metadataElementSpecified)
                        {
                            throw DataServiceException.CreateBadRequestError(Strings.BadRequest_DeepUpdateNotSupported);
                        }
                        else if (uri == null)
                        {
                            throw DataServiceException.CreateBadRequestError(Strings.BadRequest_UriMissingForUpdateForDeepUpdates);
                        }
                    }

                    if (topLevel)
                    {
                        // Checking for merge vs replace semantics
                        // Only checking for top level resource entity
                        // since we don't support update of deep resources
                        resource = GetObjectFromSegmentInfo(
                            resourceType,
                            segmentInfo,
                            true /*checkETag*/,
                            true /*checkForNull*/,
                            this.Service.OperationContext.Host.AstoriaHttpVerb == AstoriaVerbs.PUT /*replaceResource*/);
                    }
                    else
                    {
                        // case of binding at the first level.
                        existingRelationship = false;
                        return(this.GetTargetResourceToBind(uri, false /*checkNull*/));
                    }
                }
                else
                {
                    // For insert, its a new resource that is getting created or an existing resource
                    // getting binded. Either case, its a new relationship.
                    existingRelationship = false;

                    // For POST operations, the following rules holds true:
                    // 1> If the uri is specified for navigation properties and no other property is specified, then its a bind operation.
                    // Otherwise, ignore the uri and insert the new resource.
                    if (uri != null)
                    {
                        if (segmentInfo.TargetSource == RequestTargetSource.Property && jsonObjectRecord.Count == 1)
                        {
                            this.RecurseLeave();
                            return(this.GetTargetResourceToBind(uri, false /*checkNull*/));
                        }
                    }
                }
            }

            Debug.Assert(resourceType != null, "resourceType != null");
            if (resourceType.ResourceTypeKind == ResourceTypeKind.ComplexType)
            {
                Debug.Assert(resource == null, "resource == null");
                resource         = this.Updatable.CreateResource(null, resourceType.FullName);
                existingResource = false;
            }
            else if (!this.Update)
            {
                Debug.Assert(resource == null, "resource == null");
                if (segmentInfo.TargetKind == RequestTargetKind.Resource)
                {
                    // check for append rights whenever we need to create a resource
                    DataServiceConfiguration.CheckResourceRights(segmentInfo.TargetContainer, EntitySetRights.WriteAppend);

                    resource = this.Updatable.CreateResource(segmentInfo.TargetContainer.Name, resourceType.FullName);

                    // If resourceType is FF mapped with KeepInContent=false and the response format is Atom, we need to raise the response DSV version
                    // Note that we only need to do this for POST since PUT responds with 204 and DSV=1.0
                    //
                    // Errr, mismatching request and response formats don't meet the bar at this point, commenting out the fix...
                    //
                    //// this.UpdateAndCheckEpmRequestResponseDSV(resourceType, topLevel);

                    this.Tracker.TrackAction(resource, segmentInfo.TargetContainer, UpdateOperations.Add);
                }
                else
                {
                    Debug.Assert(segmentInfo.TargetKind == RequestTargetKind.OpenProperty, "segmentInfo.TargetKind == RequestTargetKind.OpenProperty");

                    // Open navigation properties are not supported on OpenTypes.
                    throw DataServiceException.CreateBadRequestError(Strings.OpenNavigationPropertiesNotSupportedOnOpenTypes(segmentInfo.Identifier));
                }

                existingResource = false;
            }

            bool changed = this.PopulateProperties(jsonObjectRecord, resource, segmentInfo.TargetContainer, resourceType);

            // For put operations, you need not specify any property and that means reset all the properties.
            // hence for put operations, change is always true.
            changed = changed || this.Service.OperationContext.Host.AstoriaHttpVerb == AstoriaVerbs.PUT;
            if (changed && existingResource && segmentInfo.TargetContainer != null)
            {
                this.Tracker.TrackAction(resource, segmentInfo.TargetContainer, UpdateOperations.Change);
            }

            this.RecurseLeave();
            return(resource);
        }
Exemplo n.º 28
0
        /// <summary>
        /// Populate the properties of the given resource
        /// </summary>
        /// <param name="jsonObject">JsonObjectRecords containing property name and values</param>
        /// <param name="resource">instance of the resource whose properties needs to be populated</param>
        /// <param name="parentResourceSet">resource set where <paramref name="resource"/> belongs to</param>
        /// <param name="parentResourceType">resource type whose properties needs to be populated</param>
        /// <returns>true if any properties were set; false otherwise.</returns>
        private bool PopulateProperties(JsonReader.JsonObjectRecords jsonObject, object resource, ResourceSetWrapper parentResourceSet, ResourceType parentResourceType)
        {
            // Update all the properties specified in the payload.
            // Don't touch the properties which are not specified. Its upto the provider to interpret
            // the meaning of things which are not specified
            bool changed = false;
            List <ResourceProperty> navProperties     = new List <ResourceProperty>();
            List <object>           navPropertyValues = new List <object>();

            #region Handle Non-Nav Properties
            foreach (string propertyName in jsonObject.OrderedKeys)
            {
                // Ignore the metadata property
                if (propertyName == XmlConstants.JsonMetadataString)
                {
                    continue;
                }

                // Check if the property exists and try and set the value
                ResourceProperty resourceProperty = parentResourceType.TryResolvePropertyName(propertyName);
                if (resourceProperty == null && parentResourceType.IsOpenType == false)
                {
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidPropertyNameSpecified(propertyName, parentResourceType.FullName));
                }

                // Get the property value, set it appropriately, and mark the object as changed.
                object propertyValue = jsonObject.Entries[propertyName];
                bool   existingRelationship;

                // If its a open property
                if (resourceProperty == null)
                {
                    this.HandleOpenTypeProperties(resource, propertyName, propertyValue);
                    changed = true;
                }
                else if (resourceProperty.TypeKind == ResourceTypeKind.ComplexType)
                {
                    SegmentInfo segmentInfo = CreateSegment(resourceProperty, resourceProperty.Name, null, true /* singleResult */);
                    segmentInfo.TargetKind = RequestTargetKind.ComplexObject;
                    propertyValue          = this.CreateObject(propertyValue, segmentInfo, false /*topLevel*/, out existingRelationship);
                    SetPropertyValue(resourceProperty, resource, propertyValue, ContentFormat.Json, this.Service);
                    changed = true;
                }
                else if (resourceProperty.TypeKind == ResourceTypeKind.Primitive)
                {
                    // Ignoring the value of key properties in PUT payload
                    if (!this.Update || !resourceProperty.IsOfKind(ResourcePropertyKind.Key))
                    {
                        SetPropertyValue(resourceProperty, resource, propertyValue, ContentFormat.Json, this.Service);
                    }

                    changed = true;
                }
                else
                {
                    Debug.Assert(ResourceTypeKind.EntityType == resourceProperty.TypeKind, "only expecting nav properties");

                    if (IsDeferredElement(propertyValue))
                    {
                        // Skip the deferred element
                        continue;
                    }
                    else
                    {
                        navProperties.Add(resourceProperty);
                        navPropertyValues.Add(propertyValue);
                    }
                }
            }

            #endregion Non-Navigation Properties

            #region Handle Navigation Properties

            Debug.Assert(navProperties.Count == navPropertyValues.Count, "nav properties and nav property values count must be the same");

            // The reason why we need to do this is so that we can gaurantee that the nav properties are getting set at the end.
            // This is nice, since we already do this in the atom deserializer. Hence its consistent. Second, we wanted to
            // give a gaurantee that when FK and nav properties are specified in the payload, nav properties always win.
            for (int i = 0; i < navProperties.Count; i++)
            {
                this.HandleNavigationProperty(parentResourceSet, parentResourceType, resource, navProperties[i], navPropertyValues[i]);
                changed = true;
            }

            #endregion Handle Navigation Properties

            return(changed);
        }
Exemplo n.º 29
0
        /// <summary>
        /// Gets the type and uri specified in the metadata object in the given json object.
        /// </summary>
        /// <param name="jsonObjectTable">jsonObject which contains the metadata information</param>
        /// <param name="expectedType">expected type that this segment of the uri is targeted to</param>
        /// <param name="topLevel">whether the segment represents the top level object.</param>
        /// <param name="uri">uri as specified in the metadata object. If its not specified, this is set to null</param>
        /// <param name="metadataElementSpecified">returns true if the metadata element was specified</param>
        /// <returns>typename and uri as specified in the metadata object</returns>
        private ResourceType GetTypeAndUriFromMetadata(
            Dictionary <String, Object> jsonObjectTable,
            ResourceType expectedType,
            bool topLevel,
            out string uri,
            out bool metadataElementSpecified)
        {
            metadataElementSpecified = false;

            // Get the metadata object
            object       metadataObject;
            ResourceType targetType        = expectedType;
            bool         typeNameSpecified = false;

            uri = null;

            if (jsonObjectTable.TryGetValue(XmlConstants.JsonMetadataString, out metadataObject))
            {
                metadataElementSpecified = true;
                JsonReader.JsonObjectRecords metadata = metadataObject as JsonReader.JsonObjectRecords;
                if (metadata == null)
                {
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequestStream_InvalidMetadataContent);
                }

                // Get the type information from the metadata object. if the type name is not specified,
                // then return the expectedType as the target type
                object objectTypeName;
                if (metadata.Entries.TryGetValue(XmlConstants.JsonTypeString, out objectTypeName))
                {
                    string typeName = objectTypeName as string;
                    if (string.IsNullOrEmpty(typeName))
                    {
                        throw DataServiceException.CreateBadRequestError(Strings.BadRequestStream_InvalidTypeMetadata);
                    }

                    // Resolve resource type name
                    targetType = this.Service.Provider.TryResolveResourceType(typeName);
                    if (targetType == null || targetType.ResourceTypeKind == ResourceTypeKind.Primitive)
                    {
                        throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidTypeName(typeName));
                    }

                    if (expectedType != null && !expectedType.IsAssignableFrom(targetType))
                    {
                        throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidTypeSpecified(typeName, expectedType.FullName));
                    }

                    typeNameSpecified = true;
                }

                uri = JsonDeserializer.ReadUri(metadata.Entries);
            }

            // Type information is optional for bind operations.
            // Top level operations cannot be bind operations, since uri need to have $links
            // for top level bind operations and that's a different code path.
            // For bind operations, uri must be specified and nothing else should be specified.
            bool bindOperation = !topLevel && uri != null && jsonObjectTable.Count == 1;

            // type name must be specified for POST or PUT/MERGE operations.
            if (!typeNameSpecified)
            {
                if (!bindOperation)
                {
                    if (expectedType == null)
                    {
                        // For open properties, you must specify the type information
                        throw DataServiceException.CreateBadRequestError(Strings.BadRequestStream_MissingTypeInformationForOpenTypeProperties);
                    }
                    else if (this.Service.Provider.HasDerivedTypes(expectedType))
                    {
                        // For types that take part in inheritance, type information must be specified.
                        throw DataServiceException.CreateBadRequestError(Strings.BadRequest_TypeInformationMustBeSpecifiedForInhertiance);
                    }
                }
                else
                {
                    // If the type name is not specified, we should set the type name to null, since in case of inheritance,
                    // we don't want to guess the type information.
                    targetType = null;
                }
            }

            return(targetType);
        }
Exemplo n.º 30
0
 /// <summary>Creates an exception for a parse error.</summary>
 /// <param name="message">Message text.</param>
 /// <returns>A new Exception.</returns>
 private static Exception ParseError(string message)
 {
     return(DataServiceException.CreateSyntaxError(message));
 }
Exemplo n.º 31
0
		public SequencedMessage GetPageItems(DataMessage dataMessage) {
			int sequenceId = (int)dataMessage.headers[DataMessage.SequenceIdHeader];
			Sequence sequence = GetSequence(sequenceId);
			if (sequence != null) {
				IList DSids = dataMessage.headers["DSids"] as IList;
				//ArrayList items = new ArrayList(DSids.Count);
				SequencedMessage sequencedMessage = new SequencedMessage();
				object[] items = new object[DSids.Count];
				lock (_objLock) {
					for (int i = 0; i < DSids.Count; i++) {
						Identity identity = new Identity(DSids[i] as IDictionary);
						ItemWrapper itemWrapper = GetItem(identity);
						//items.Add(item);
						items[i] = itemWrapper.Instance;
					}

					sequencedMessage.destination = dataMessage.destination;
					sequencedMessage.sequenceId = sequence.Id;
					sequencedMessage.sequenceSize = sequence.Size;
					sequencedMessage.sequenceProxies = null;

					sequencedMessage.body = items;
				}
				return sequencedMessage;
			} else {
				DataServiceException dse = new DataServiceException(string.Format("Sequence {0} in destination {1} was not found", sequenceId, dataMessage.destination));
				throw dse;
			}
		}
Exemplo n.º 32
0
        /// <summary>
        /// Generates a comparison expression which can handle NULL values for any type.
        /// NULL is always treated as the smallest possible value.
        /// So for example for strings NULL is smaller than any non-NULL string.
        /// For now only GreaterThan and LessThan operators are supported by this method.
        /// </summary>
        /// <param name="left">Left hand side expression</param>
        /// <param name="right">Right hand side expression</param>
        /// <param name="operatorKind">gt or lt operator token</param>
        /// <returns>Resulting comparison expression (has a Boolean value)</returns>
        private Expression GenerateNullAwareComparison(Expression left, Expression right, BinaryOperatorKind operatorKind)
        {
            Debug.Assert(
                operatorKind == BinaryOperatorKind.GreaterThan || operatorKind == BinaryOperatorKind.LessThan,
                "Only GreaterThan or LessThan operators are supported by the GenerateNullAwateComparison method for now.");

            if (WebUtil.TypeAllowsNull(left.Type))
            {
                if (!WebUtil.TypeAllowsNull(right.Type))
                {
                    right = Expression.Convert(right, typeof(Nullable <>).MakeGenericType(right.Type));
                }
            }
            else if (WebUtil.TypeAllowsNull(right.Type))
            {
                left = Expression.Convert(left, typeof(Nullable <>).MakeGenericType(left.Type));
            }
            else
            {
                // Can't perform NULL aware comparison on this type. Just let the normal
                // comparison deal with it. Since the type doesn't allow NULL one should
                // never appear, so normal comparison is just fine.
                return(this.GenerateComparisonExpression(left, right, operatorKind));
            }

            switch (operatorKind)
            {
            case BinaryOperatorKind.GreaterThan:
                // (left != null) && ((right == null) || Compare(left, right) > 0)
                if (left == ExpressionUtils.NullLiteral)
                {
                    return(Expression.Constant(false, typeof(bool)));
                }
                else if (right == ExpressionUtils.NullLiteral)
                {
                    return(ExpressionGenerator.GenerateNotEqual(left, Expression.Constant(null, left.Type)));
                }
                else
                {
                    return(ExpressionGenerator.GenerateLogicalAnd(
                               ExpressionGenerator.GenerateNotEqual(left, Expression.Constant(null, left.Type)),
                               ExpressionGenerator.GenerateLogicalOr(
                                   ExpressionGenerator.GenerateEqual(right, Expression.Constant(null, right.Type)),
                                   this.GenerateComparisonExpression(left, right, operatorKind))));
                }

            case BinaryOperatorKind.LessThan:
                // (right != null) && ((left == null) || Compare(left, right) < 0)
                if (right == ExpressionUtils.NullLiteral)
                {
                    return(Expression.Constant(false, typeof(bool)));
                }
                else if (left == ExpressionUtils.NullLiteral)
                {
                    return(ExpressionGenerator.GenerateNotEqual(right, Expression.Constant(null, right.Type)));
                }
                else
                {
                    return(ExpressionGenerator.GenerateLogicalAnd(
                               ExpressionGenerator.GenerateNotEqual(right, Expression.Constant(null, left.Type)),
                               ExpressionGenerator.GenerateLogicalOr(
                                   ExpressionGenerator.GenerateEqual(left, Expression.Constant(null, right.Type)),
                                   this.GenerateComparisonExpression(left, right, operatorKind))));
                }

            default:
                // For now only < and > are supported as we use this only from $skiptoken
                string message = ServiceStrings.RequestQueryParser_NullOperatorUnsupported(operatorKind);
                throw DataServiceException.CreateSyntaxError(message);
            }
        }
		public void CtorStatusAndMessage()
		{
			var ex = new DataServiceException (404, "message");
			Assert.AreEqual (404, ex.StatusCode);
			Assert.AreEqual ("message", ex.Message);
		}
Exemplo n.º 34
0
        public void UpdateProviderPropertyTest()
        {
            IDataService service = this.serviceFactory.CreateService <CustomUpdateProvider2Service>();

            ODataProtocolVersion[] versions   = new[] { ODataProtocolVersion.V4 };
            bool[]        boolValues          = new[] { true, false };
            List <string> failureCombinations = new List <string>();

            foreach (var version in versions)
            {
                foreach (var hasReflectionOrEFProviderQueryBehavior in boolValues)
                {
                    foreach (var implementsIUpdatable in boolValues)
                    {
                        foreach (var implementsIDSUP in boolValues)
                        {
                            foreach (var implementsIDSUP2 in boolValues)
                            {
                                service.Configuration.DataServiceBehavior.MaxProtocolVersion = version;
                                CustomUpdateProvider2Service.ImplementsIUpdatable            = implementsIUpdatable;
                                CustomUpdateProvider2Service.ImplementsIDSUP    = implementsIDSUP;
                                CustomUpdateProvider2Service.ImplementsIDSUP2   = implementsIDSUP2;
                                CustomUpdateProvider2Service.IUpdatableGetCount = 0;
                                CustomUpdateProvider2Service.IDataServiceUpdateProviderGetCount  = 0;
                                CustomUpdateProvider2Service.IDataServiceUpdateProvider2GetCount = 0;

                                ((DataServiceSimulator)service).Provider = CreateProviderWrapper(service.Configuration, hasReflectionOrEFProviderQueryBehavior);
                                UpdatableWrapper updatable = new UpdatableWrapper(service);
                                try
                                {
                                    var instance = updatable.GetType().GetProperty("UpdateProvider", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(updatable, null);
                                    Assert.IsNotNull(instance, "UpdatableWrapper should throw if UpdateProvider fails to get the interface.");
                                    Assert.AreEqual(1, CustomUpdateProvider2Service.IDataServiceUpdateProvider2GetCount);

                                    // None of this code is actually hit, we need to investigate this.
                                    if (!CustomUpdateProvider2Service.ImplementsIDSUP2)
                                    {
                                        if (hasReflectionOrEFProviderQueryBehavior)
                                        {
                                            Assert.AreEqual(1, CustomUpdateProvider2Service.IUpdatableGetCount);
                                        }
                                        else
                                        {
                                            Assert.AreEqual(0, CustomUpdateProvider2Service.IUpdatableGetCount);
                                        }

                                        if (!CustomUpdateProvider2Service.ImplementsIUpdatable)
                                        {
                                            Assert.AreEqual(1, CustomUpdateProvider2Service.IDataServiceUpdateProviderGetCount);
                                        }
                                        else
                                        {
                                            if (hasReflectionOrEFProviderQueryBehavior)
                                            {
                                                Assert.AreEqual(0, CustomUpdateProvider2Service.IDataServiceUpdateProviderGetCount);
                                            }
                                            else
                                            {
                                                Assert.AreEqual(1, CustomUpdateProvider2Service.IDataServiceUpdateProviderGetCount);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        Assert.AreEqual(0, CustomUpdateProvider2Service.IUpdatableGetCount);
                                        Assert.AreEqual(0, CustomUpdateProvider2Service.IDataServiceUpdateProviderGetCount);
                                    }
                                }
                                catch (TargetInvocationException tie)
                                {
                                    string errorCaseVariation = string.Format("Version:{0}, hasReflectionOrEFProviderQueryBehavior:{1}, implementsIUpdatable:{2}, implementsIDSUP:{3}, implementsIDSUP2:{4}", version, hasReflectionOrEFProviderQueryBehavior, implementsIUpdatable, implementsIDSUP, implementsIDSUP2);
                                    failureCombinations.Add(errorCaseVariation);
                                    DataServiceException e = (DataServiceException)tie.InnerException;
                                    Assert.AreEqual(501, e.StatusCode);
                                    if (hasReflectionOrEFProviderQueryBehavior)
                                    {
                                        Assert.AreEqual("The data source must implement IUpdatable, IDataServiceUpdateProvider or IDataServiceUpdateProvider2 to support updates.", e.Message);
                                    }
                                    else
                                    {
                                        Assert.AreEqual("The data source must implement IDataServiceUpdateProvider or IDataServiceUpdateProvider2 to support updates.", e.Message);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
		public void CtorMessage()
		{
			var ex = new DataServiceException ("message");
			Assert.AreEqual ("message", ex.Message);
			Assert.IsNull (ex.InnerException);
		}
Exemplo n.º 36
0
        /// <summary>
        /// Reads the input request payload and returns the WCF DS value representation of it.
        /// </summary>
        /// <param name="segmentInfo">Info about the request to read.</param>
        /// <returns>The WCF DS representation of the value read.</returns>
        protected override object Read(SegmentInfo segmentInfo)
        {
            Debug.Assert(segmentInfo != null, "segmentInfo != null");
            Debug.Assert(
                segmentInfo.TargetKind == RequestTargetKind.Primitive ||
                segmentInfo.TargetKind == RequestTargetKind.ComplexObject ||
                segmentInfo.TargetKind == RequestTargetKind.Collection ||
                segmentInfo.TargetKind == RequestTargetKind.OpenProperty,
                "The PropertyDeserializer only supports Primitive, ComplexObject, Collection or OpenProperty target kinds.");

            ResourceProperty  resourceProperty;
            ResourceType      propertyResourceType;
            IEdmTypeReference propertyTypeReference;

            if (segmentInfo.TargetKind == RequestTargetKind.OpenProperty)
            {
                resourceProperty      = null;
                propertyResourceType  = null;
                propertyTypeReference = null;
            }
            else
            {
                resourceProperty      = segmentInfo.ProjectedProperty;
                propertyResourceType  = resourceProperty.ResourceType;
                propertyTypeReference = this.GetTypeReference(propertyResourceType, resourceProperty.CustomAnnotations.ToList());

                // WCF DS server allows null values for primitive properties. For non top-level properties, custom annotations are added
                // to ensure ODataLib does not perform any validation. The provider can choose to throw in which case, the response code will be 500. The
                // same applies to top-level primitive properties. So, we ensure the type reference carries the correct value for the nullability facet.
                if (resourceProperty.Kind == ResourcePropertyKind.Primitive &&
                    MetadataProviderUtils.ShouldDisablePrimitivePropertyNullValidation(resourceProperty, (IEdmPrimitiveTypeReference)propertyTypeReference))
                {
                    propertyTypeReference = this.GetSchemaType(propertyResourceType).ToTypeReference(true);
                }

                // WCF DS server allows null values for complex properties.  For non top-level properties, custom annotations are added
                // to ensure ODataLib does not perform any validation. The provider can choose to throw in which case, the response code will be 500. The
                // same applies to top-level complex properties. So, we ensure the type reference carries the correct value for the nullability facet.
                if (resourceProperty.Kind == ResourcePropertyKind.ComplexType && this.Service.Provider.HasReflectionOrEFProviderQueryBehavior && !propertyTypeReference.IsNullable)
                {
                    propertyTypeReference = this.GetSchemaType(propertyResourceType).ToTypeReference(true);
                }
            }

            ODataProperty property = this.MessageReader.ReadProperty(propertyTypeReference);

            Debug.Assert(property != null, "property != null");
#pragma warning disable 618
            AssertReaderFormatIsExpected(this.MessageReader, ODataFormat.Atom, ODataFormat.Json);
#pragma warning restore 618
            // On V4, it seems this checking logic is useless. Will remove it after fully understanding.
            // PlainXmlDeserializer - PUT to a property with m:null='true' doesn't verify the name of the property matches
            //
            // PUT to open property with XML payload ignores the name of the property in the payload.
            //  For backward compat reasons we must not fail if the property name doesn't match and the value is null or it's an open property (in XML case).
            //
            // V2 Server reads JSON complex values without property wrapper, ODataLib will report these as ODataProperty with empty name, so for those
            //  we need to not compare the property name.
            //
            // For Json light, we do not validate the property name since in requests we do not parse the metadata URI and thus
            //   will always report 'value'.
            if (!this.IsAtomRequest && !this.IsJsonLightRequest &&
                string.CompareOrdinal(segmentInfo.Identifier, property.Name) != 0)
            {
                throw DataServiceException.CreateBadRequestError(
                          Microsoft.OData.Service.Strings.PlainXml_IncorrectElementName(segmentInfo.Identifier, property.Name));
            }

            object propertyValue = property.Value;

            object convertedValue = this.ConvertValue(propertyValue, ref propertyResourceType);

            if (segmentInfo.TargetKind == RequestTargetKind.OpenProperty)
            {
                // Set the target resource type for open properties so we can reason over the property type later.
                // The target resource type of an open property segment is determined when converting the payload value above.
                Debug.Assert(segmentInfo.TargetResourceType == null, "segmentInfo.TargetResourceType == null");
                segmentInfo.TargetResourceType = propertyResourceType;
            }
            else
            {
                Debug.Assert(segmentInfo.TargetResourceType.FullName == propertyResourceType.FullName, "segmentInfo.TargetResourceType == propertyResourceType");
            }

            return(convertedValue);
        }