/// <summary>Initializes a new NonEntitySerializer instance.</summary> /// <param name="requestDescription">Description of request.</param> /// <param name="absoluteServiceUri">Base URI from which resources should be resolved.</param> /// <param name="service">Service with configuration and provider from which metadata should be gathered.</param> /// <param name="messageWriter">ODataMessageWriter instance which needs to be used to write the response.</param> internal NonEntitySerializer(RequestDescription requestDescription, Uri absoluteServiceUri, IDataService service, ODataMessageWriter messageWriter) : base(requestDescription, absoluteServiceUri, service, null) { Debug.Assert(messageWriter != null, "messageWriter != null"); this.writer = messageWriter; }
/// <summary> /// Initializes a new instance of <see cref="Deserializer"/>. /// </summary> /// <param name="update">true if we're reading an update operation; false if not.</param> /// <param name="dataService">Data service for which the deserializer will act.</param> /// <param name="tracker">Tracker to use for modifications.</param> /// <param name="requestDescription">The request description to use.</param> internal Deserializer(bool update, IDataService dataService, UpdateTracker tracker, RequestDescription requestDescription) { Debug.Assert(dataService != null, "dataService != null"); this.service = dataService; this.tracker = tracker; this.update = update; this.description = requestDescription; }
/// <summary>Initializes a new <see cref="Deserializer"/> based on a different one.</summary> /// <param name="parent">Parent deserializer for the new instance.</param> internal Deserializer(Deserializer parent) { Debug.Assert(parent != null, "parent != null"); this.recursionDepth = parent.recursionDepth; this.service = parent.service; this.tracker = parent.tracker; this.update = parent.update; this.description = parent.description; }
/// <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 EntitySerializer instance.</summary> /// <param name="requestDescription">Request description.</param> /// <param name="absoluteServiceUri">Absolute URI to the service entry point.</param> /// <param name="service">Service with configuration and provider from which metadata should be gathered.</param> /// <param name="httpETagHeaderValue">HTTP ETag header value.</param> /// <param name="messageWriter">ODataMessageWriter instance which needs to be used to write the response.</param> /// <param name="contentFormat">The content format.</param> internal EntitySerializer( RequestDescription requestDescription, Uri absoluteServiceUri, IDataService service, string httpETagHeaderValue, ODataMessageWriter messageWriter, ODataFormat contentFormat) : base(requestDescription, absoluteServiceUri, service, httpETagHeaderValue) { Debug.Assert(service != null, "service != null"); this.messageWriter = messageWriter; this.contentFormat = contentFormat; }
/// <summary>Initializes a new SyndicationSerializer instance.</summary> /// <param name="requestDescription">Description of request.</param> /// <param name="absoluteServiceUri">Base URI from which resources should be resolved.</param> /// <param name="service">Service with configuration and provider from which metadata should be gathered.</param> /// <param name="output">Output stream.</param> /// <param name="encoding">Encoding for output.</param> internal PlainXmlSerializer( RequestDescription requestDescription, Uri absoluteServiceUri, IDataService service, Stream output, Encoding encoding) : base(requestDescription, absoluteServiceUri, service, null) { Debug.Assert(output != null, "output != null"); Debug.Assert(encoding != null, "encoding != null"); this.writer = XmlUtil.CreateXmlWriterAndWriteProcessingInstruction(output, encoding); }
/// <summary> /// Initializes a new <see cref="JsonSerializer"/>, ready to write out a description. /// </summary> /// <param name="requestDescription">Description for the requested results.</param> /// <param name="output">Stream to which output should be sent.</param> /// <param name="absoluteServiceUri">Absolute URI to the service entry point.</param> /// <param name="service">Service with configuration and provider from which metadata should be gathered.</param> /// <param name="encoding">Text encoding for the response.</param> /// <param name="httpETagHeaderValue">HTTP ETag header value.</param> internal JsonSerializer( RequestDescription requestDescription, Stream output, Uri absoluteServiceUri, IDataService service, Encoding encoding, string httpETagHeaderValue) : base(requestDescription, absoluteServiceUri, service, httpETagHeaderValue) { Debug.Assert(output != null, "output != null"); Debug.Assert(encoding != null, "encoding != null"); this.writer = new JsonWriter(new StreamWriter(output, encoding)); }
/// <summary> /// Initializes a new instance of <see cref="ODataMessageReaderDeserializer"/>. /// </summary> /// <param name="update">true if we're reading an update operation; false if not.</param> /// <param name="dataService">Data service for which the deserializer will act.</param> /// <param name="tracker">Tracker to use for modifications.</param> /// <param name="requestDescription">The request description to use.</param> /// <param name="enableODataServerBehavior">If true, the message reader settings will use the ODataServer behavior; /// if false, the message reader settings will use the default behavior.</param> internal ODataMessageReaderDeserializer(bool update, IDataService dataService, UpdateTracker tracker, RequestDescription requestDescription, bool enableODataServerBehavior) : base(update, dataService, tracker, requestDescription) { AstoriaRequestMessage requestMessage = dataService.OperationContext.RequestMessage; // WCF DS needs to treat content type */* as ATOM payload, so check for it here and override the content type header if (ContentTypeUtil.CompareMimeType(requestMessage.ContentType, XmlConstants.MimeAny)) { requestMessage.ContentType = XmlConstants.MimeApplicationAtom; } this.messageReader = new ODataMessageReader( requestMessage, WebUtil.CreateMessageReaderSettings(dataService, enableODataServerBehavior), dataService.Provider.GetMetadataProviderEdmModel()); }
/// <summary>Initializes a new SyndicationSerializer instance.</summary> /// <param name="requestDescription">Request description.</param> /// <param name="absoluteServiceUri">Absolute URI to the service entry point.</param> /// <param name="service">Service with configuration and provider from which metadata should be gathered.</param> /// <param name="output">Stream to write to.</param> /// <param name="encoding">Encoding for text in output stream.</param> /// <param name="etag">HTTP ETag header value.</param> /// <param name="factory">Factory for formatter objects.</param> internal SyndicationSerializer( RequestDescription requestDescription, Uri absoluteServiceUri, IDataService service, Stream output, Encoding encoding, string etag, SyndicationFormatterFactory factory) : base(requestDescription, absoluteServiceUri, service, etag) { Debug.Assert(service != null, "service != null"); Debug.Assert(output != null, "output != null"); Debug.Assert(encoding != null, "encoding != null"); Debug.Assert(factory != null, "factory != null"); this.factory = factory; this.writer = factory.CreateWriter(output, encoding); }
public AddToCacheResult AddRequestToInfiniteCache(RequestDescription request, double cachingScore) { if (Cache.VideoCache.ContainsKey(request.VideoID)) { Cache.VideoCache[request.VideoID].CacheScore += cachingScore; } else { Cache.VideoCache.Add(request.VideoID, new CachedVideoRequest { Video = request.Video, VideoID = request.VideoID, CacheScore = cachingScore, OriginalRequest = request }); request.IsCached = true; } return(AddToCacheResult.Added); }
/// <summary>Sets the response status code and the default caching and versioning headers.</summary> /// <param name="description">The request description for the current request.</param> /// <param name="statusCode">The status code for the response.</param> internal void SetResponseHeaders(RequestDescription description, int statusCode) { // Set the caching policy appropriately - for the time being, we disable caching. this.SetHeader(XmlConstants.HttpResponseCacheControl, XmlConstants.HttpCacheControlNoCache); // If a preference was applied, add corresponding response header. ClientPreference preference = description.Preference; this.PreferenceAppliedHeader().ReturnContent = preference.ShouldIncludeResponseBody ? true : (preference.ShouldNotIncludeResponseBody ? (bool?)false : null); // Only set the annotation filter to the Preference-Applied if we are writing a response body // since instance annotations only appear in the response body. if (description.ShouldWriteResponseBody && !string.IsNullOrEmpty(preference.AnnotationFilter)) { this.PreferenceAppliedHeader().AnnotationFilter = preference.AnnotationFilter; } this.SetHeader(XmlConstants.HttpODataVersion, description.ResponseVersion.ToString() + ";"); this.StatusCode = statusCode; }
public void TokenSecretNotIncludedInAuthorizationHeaderForPostRequestWithUseAuthorizationHeaders() { var session = new OAuthSession(new OAuthConsumerContext { ConsumerKey = "consumer", UseHeaderForOAuthParameters = true }, "http://localhost/request", "http://localhost/userauth", "http://localhost/access", null); var accessToken = new TokenBase { ConsumerKey = "consumer", Token = "token", TokenSecret = "secret" }; RequestDescription description = session .Request(accessToken) .Post() .ForUrl("http://localhost/") .SignWithToken() .GetRequestDescription(); Assert.False(description.Headers["Authorization"].Contains(Parameters.OAuth_Token_Secret)); }
public void TokenSecretNotIncludedInQueryParametersForGetRequest() { var session = new OAuthSession(new OAuthConsumerContext { ConsumerKey = "consumer" }, "http://localhost/request", "http://localhost/userauth", "http://localhost/access", null); var accessToken = new TokenBase { ConsumerKey = "consumer", Token = "token", TokenSecret = "secret" }; RequestDescription description = session .Request(accessToken) .Get() .ForUrl("http://localhost/") .SignWithToken() .GetRequestDescription(); Assert.False(description.Url.ToString().Contains(Parameters.OAuth_Token_Secret)); }
/// <summary>Filters a query like a SQL WHERE clause does.</summary> /// <param name="service">Service with data and configuration.</param> /// <param name="requestDescription">RequestDescription instance containing information about the current request being parsed.</param> /// <param name="source">Original source for query expression.</param> /// <returns>The composed query expression.</returns> internal static Expression Where(IDataService service, RequestDescription requestDescription, Expression source) { Debug.Assert(service != null, "service != null"); Debug.Assert(source != null, "source != null"); Debug.Assert(requestDescription != null, "requestDescription != null"); FilterClause filterClause = new RequestExpressionParser(service, requestDescription).ParseFilter(); if (filterClause == null) { return source; } bool filterQueryApplicable = requestDescription.TargetKind == RequestTargetKind.Resource || requestDescription.TargetKind == RequestTargetKind.OpenProperty || requestDescription.TargetKind == RequestTargetKind.ComplexObject || requestDescription.CountOption == RequestQueryCountOption.CountSegment; if (!filterQueryApplicable) { throw DataServiceException.CreateBadRequestError(Strings.RequestQueryProcessor_QueryFilterOptionNotApplicable); } Type queryElementType = source.ElementType(); Debug.Assert(queryElementType != null, "queryElementType != null"); ParameterExpression parameterForIt = Expression.Parameter(queryElementType, "it"); Debug.Assert( (requestDescription.TargetResourceSet == null && (requestDescription.TargetResourceType == null || requestDescription.TargetResourceType.ResourceTypeKind != ResourceTypeKind.EntityType)) || (requestDescription.TargetResourceType != null && requestDescription.TargetResourceType.ResourceTypeKind == ResourceTypeKind.EntityType), "setForIt cannot be null if typeForIt is an entity type."); Debug.Assert( requestDescription.TargetResourceType == null && parameterForIt.Type == typeof(object) || requestDescription.TargetResourceType != null && requestDescription.TargetResourceType.InstanceType == parameterForIt.Type, "non-open type expressions should have a typeForIt"); var translator = NodeToExpressionTranslator.Create(service, requestDescription, parameterForIt); LambdaExpression lambda = translator.TranslateFilterClause(filterClause); return source.QueryableWhere(lambda); }
/// <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); } }
/// <summary> /// Binds the expand paths from the requests $expand query option to the sets/types/properties from the metadata provider of the service. /// </summary> /// <param name="requestDescription">The request description.</param> /// <param name="dataService">The data service.</param> /// <param name="expandQueryOption">The value of the $expand query option.</param> /// <returns>The bound expand segments.</returns> internal static IList <IList <ExpandItem> > BindExpandSegments(RequestDescription requestDescription, IDataService dataService, string expandQueryOption) { Debug.Assert(requestDescription != null, "requestDescription != null"); Debug.Assert(dataService != null, "dataService != null"); if (string.IsNullOrWhiteSpace(expandQueryOption)) { return(new List <IList <ExpandItem> >()); } ResourceType targetResourceType = requestDescription.TargetResourceType; ResourceSetWrapper targetResourceSet = requestDescription.TargetResourceSet; if (targetResourceType == null || targetResourceType.ResourceTypeKind != ResourceTypeKind.EntityType || targetResourceSet == null) { throw DataServiceException.CreateBadRequestError(Strings.RequestQueryProcessor_QueryExpandOptionNotApplicable); } MetadataProviderEdmModel model = dataService.Provider.GetMetadataProviderEdmModel(); IEdmEntityType targetType = (IEdmEntityType)model.EnsureSchemaType(targetResourceType); IEdmEntitySet targetSet = model.EnsureEntitySet(targetResourceSet); SelectExpandClause clause; try { model.Mode = MetadataProviderEdmModelMode.SelectAndExpandParsing; clause = ODataUriParser.ParseSelectAndExpand(/*select*/ null, expandQueryOption, model, targetType, targetSet); } catch (ODataException ex) { throw new DataServiceException(400, null, ex.Message, null, ex); } finally { model.Mode = MetadataProviderEdmModelMode.Serialization; } return(new ExpandAndSelectPathExtractor(clause).ExpandPaths); }
public void generate_request_with_raw_body_includes_body_hash() { var session = new OAuthSession(new OAuthConsumerContext {ConsumerKey = "consumer", UseHeaderForOAuthParameters = true}, "http://localhost/request", "http://localhost/userauth", "http://localhost/access"); var accessToken = new TokenBase {ConsumerKey = "consumer", Token = "token", TokenSecret = "secret"}; byte[] rawContents = Encoding.UTF8.GetBytes("Hello World!"); IConsumerRequest content = session .EnableOAuthRequestBodyHashes() .Request(accessToken) .Post() .ForUrl("http://localhost/resource") .WithRawContent(rawContents); RequestDescription description = content.GetRequestDescription(); Assert.Equal(rawContents, description.RawBody); Assert.Contains("oauth_body_hash=\"Lve95gjOVATpfV8EL5X4nxwjKHE%3D\"", description.Headers[Parameters.OAuth_Authorization_Header]); }
internal static IEnumerator GetSingleResultFromRequest(SegmentInfo segmentInfo) { IEnumerator enumerator2; IEnumerator requestEnumerator = WebUtil.GetRequestEnumerator(segmentInfo.RequestEnumerable); bool flag = true; try { WebUtil.CheckResourceExists(requestEnumerator.MoveNext(), segmentInfo.Identifier); RequestDescription.CheckNullDirectReference(requestEnumerator.Current, segmentInfo); flag = false; enumerator2 = requestEnumerator; } finally { if (flag) { WebUtil.Dispose(requestEnumerator); } } return(enumerator2); }
private MessageWriterBuilder ForNormalRequest() { var requestDescription = new RequestDescription(RequestTargetKind.Resource, RequestTargetSource.EntitySet, new Uri("http://temp.org/")); var resourceType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "Fake", "Type", 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(); requestDescription.LastSegmentInfo.TargetResourceType = resourceType; requestDescription.LastSegmentInfo.TargetResourceSet = ResourceSetWrapper.CreateForTests(resourceSet); return(this.ForNormalRequest(requestDescription)); }
public void RawValueWithMimeTypeShouldUseFormat() { this.host.AbsoluteServiceUri = new Uri("http://myservice.org/"); this.host.AbsoluteRequestUri = new Uri("http://myservice.org/FakeSet"); SegmentInfo segment = new SegmentInfo { TargetKind = RequestTargetKind.PrimitiveValue, TargetSource = RequestTargetSource.Property, ProjectedProperty = new ResourceProperty("Fake", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string))) { MimeType = "fake/things" } }; var requestDescription = new RequestDescription(new[] { segment }, new Uri("http://temp.org")); var testSubject = this.ForNormalRequest(requestDescription); testSubject.WriterSettings.UseFormat.Should().BeTrue(); testSubject.WriterSettings.Format.Should().BeSameAs(ODataFormat.RawValue); }
//Launched when user clicks Get Sheets from Home view public ActionResult Start() { try { //From DevDefined library //Makes initial GET request to Smartsheet to display the authentication screen OAuthSession session = BuildSession(); RequestDescription requestTokenRequest = session .BuildRequestTokenContext("GET") .GetRequestDescription(); ViewBag.logout = false; return(new RedirectResult(requestTokenRequest.Url.OriginalString)); } catch (WebException e) { //Stores the error message to the ViewBag so it can be displayed in the Failure view ViewBag.error = e.Message; return(View("Failure")); } }
public AddToCacheResult AddRequestToCache(RequestDescription request, double cachingScore) { if (request.Video.VideoSizeInMb > (MaxMb - ConsumedSpace)) { return(AddToCacheResult.NotEnoughFreeSpace); } if (Cache.VideoCache.ContainsKey(request.VideoID)) { Cache.VideoCache[request.VideoID].CacheScore += cachingScore; } else { Cache.VideoCache.Add(request.VideoID, new CachedVideoRequest { Video = request.Video, VideoID = request.VideoID, CacheScore = cachingScore }); } return(AddToCacheResult.Added); }
public async Task <AsyncReadResult <TValue> > ReadAsync(TKey key) { var innerData = await _api.ReadAsync(key); TValue data = default(TValue); if (innerData == null || innerData.Transaction == null || innerData.Transaction.UserTransaction == null) { return(new AsyncReadResult <TValue>(new RequestDescription(Errors.FailRead), data)); } var result = new RequestDescription(innerData.Transaction.UserTransaction); if (innerData.Data != null) { data = _dataProvider.DeserializeValue(innerData.Data); } else { result.DataNotFound(); } return(new AsyncReadResult <TValue>(result, data)); }
/// <summary> /// Returns the index of the entity that need to get modified /// </summary> /// <param name="description">description about the target request</param> /// <returns>Returns the index of the entity that needs to get modified</returns> internal static int GetIndexOfEntityResourceToModify(RequestDescription description) { Debug.Assert(description.TargetSource == RequestTargetSource.Property, "description.TargetSource == RequestTargetSource.Property"); int entityResourceIndex = -1; if (description.LinkUri) { Debug.Assert( description.SegmentInfos[description.SegmentInfos.Count - 2].TargetKind == RequestTargetKind.Link, "There should be only one segment allowed after $ref"); Debug.Assert( description.SegmentInfos[description.SegmentInfos.Count - 3].TargetKind == RequestTargetKind.Resource && description.SegmentInfos[description.SegmentInfos.Count - 3].SingleResult, "The segment previous to the $ref segment must refer to a single resource"); entityResourceIndex = description.SegmentInfos.Count - 3; } else { for (int j = description.SegmentInfos.Count - 1; j >= 0; j--) { if (description.SegmentInfos[j].TargetKind == RequestTargetKind.Resource && description.SegmentInfos[j].SingleResult) { entityResourceIndex = j; break; } } } Debug.Assert(entityResourceIndex != -1, "This method should never be called for request that doesn't have a parent resource"); return entityResourceIndex; }
internal ODataMessageReaderDeserializer(bool update, IDataService dataService, UpdateTracker tracker, RequestDescription requestDescription, bool enableWcfDataServicesServerBehavior) : base(update, dataService, tracker, requestDescription) { System.Data.Services.ODataRequestMessage requestMessage = new System.Data.Services.ODataRequestMessage(dataService.OperationContext.Host); if (WebUtil.CompareMimeType(requestMessage.ContentType, "*/*")) { requestMessage.ContentType = "application/atom+xml"; } this.messageReader = new ODataMessageReader(requestMessage, WebUtil.CreateMessageReaderSettings(dataService, enableWcfDataServicesServerBehavior), dataService.Provider.GetMetadataModel(base.Service.OperationContext)); this.contentFormat = System.Data.Services.ContentFormat.Unknown; }
public static ResourceProperty GetPropertyForPropertyOnlyOperation(this RequestDescription requestDescription) { return(requestDescription.GetAnnotation <ResourceProperty>(PropertyForPropertyOnlyOperationName)); }
public static void SetPostServiceOperation(this RequestDescription requestDescription) { requestDescription.SetAnnotation(PostServiceOperationName, true); }
/// <summary> /// Returns true if we need to query the provider before updating. /// </summary> /// <param name="requestDescription">request description</param> /// <param name="requestValue">value corresponding to the payload for this request</param> /// <param name="provider">provider against which the request was targeted</param> /// <returns>returns true if we need to issue an query to satishfy the request</returns> private static bool IsQueryRequired(RequestDescription requestDescription, object requestValue, DataServiceProviderWrapper provider) { Debug.Assert(requestDescription.IsSingleResult, "requestDescription.IsSingleResult"); if (requestDescription.TargetKind == RequestTargetKind.PrimitiveValue || requestDescription.TargetKind == RequestTargetKind.Primitive || requestDescription.TargetKind == RequestTargetKind.OpenPropertyValue || requestDescription.TargetKind == RequestTargetKind.MediaResource || requestDescription.TargetKind == RequestTargetKind.ComplexObject) { return true; } if (requestDescription.TargetKind == RequestTargetKind.OpenProperty) { Debug.Assert(!requestDescription.LastSegmentInfo.HasKeyValues, "CreateSegments must have caught this issue."); // if the value is null, then just set it, since we don't know the type if (requestValue == null || WebUtil.IsPrimitiveType(requestValue.GetType())) { return true; } // otherwise just set the complex type properties if (WebUtil.GetNonPrimitiveResourceType(provider, requestValue).ResourceTypeKind == ResourceTypeKind.ComplexType) { return true; } } return false; }
public static bool GetInvalidClientRequest(this RequestDescription requestDescription) { return(requestDescription.GetAnnotation <bool?>(InvalidClientRequestAnnotationName) == true); }
/// <summary> /// Returns the entity that need to get modified /// </summary> /// <param name="description">description about the target request</param> /// <param name="service">data service type to which the request was made</param> /// <param name="allowCrossReferencing">whether cross-referencing is allowed for the resource in question.</param> /// <param name="entityContainer">entity container of the entity which is getting modified.</param> /// <param name="entityResourceIndex">index of the segment which refers to the entity getting modified.</param> /// <returns>Returns the entity that needs to get modified</returns> private static object GetEntityResourceToModify( RequestDescription description, IDataService service, bool allowCrossReferencing, out ResourceSetWrapper entityContainer, out int entityResourceIndex) { Debug.Assert(description.SegmentInfos.Count >= 2, "description.SegmentInfos.Count >= 2"); if (!allowCrossReferencing && description.RequestExpression == null) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_ResourceCanBeCrossReferencedOnlyForBindOperation); } // Get the index of the entity resource that is getting modified entityResourceIndex = Deserializer.GetIndexOfEntityResourceToModify(description); Debug.Assert(entityResourceIndex != -1, "This method should never be called for request that doesn't have a parent resource"); entityContainer = description.SegmentInfos[entityResourceIndex].TargetResourceSet; Debug.Assert(entityContainer != null, "Entity container cannot be null for segments whose targetkind is resource"); AstoriaRequestMessage host = service.OperationContext.RequestMessage; // Since this is the entity which is going to get modified, then we need to check for rights if (host.HttpVerb == HttpVerbs.PUT) { DataServiceConfiguration.CheckResourceRights(entityContainer, EntitySetRights.WriteReplace); } else if (host.HttpVerb == HttpVerbs.PATCH) { DataServiceConfiguration.CheckResourceRights(entityContainer, EntitySetRights.WriteMerge); } else { Debug.Assert( host.HttpVerb == HttpVerbs.POST || host.HttpVerb == HttpVerbs.DELETE, "expecting POST and DELETE methods"); DataServiceConfiguration.CheckResourceRights(entityContainer, EntitySetRights.WriteMerge | EntitySetRights.WriteReplace); } object entityResource = service.GetResource(description, entityResourceIndex, null); if (entityResource == null) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_DereferencingNullPropertyValue(description.SegmentInfos[entityResourceIndex].Identifier)); } return entityResource; }
/// <summary> /// Handle bind operation /// </summary> /// <param name="description">information about the request uri.</param> /// <param name="linkResource">the child resource which needs to be linked.</param> /// <param name="service">data service instance</param> /// <param name="tracker">update tracker instance to fire change interceptor calls</param> /// <returns>returns the parent object to which an new object was linked to.</returns> internal static object HandleBindOperation(RequestDescription description, object linkResource, IDataService service, UpdateTracker tracker) { Debug.Assert(description != null, "description != null"); Debug.Assert(linkResource != null, "linkResource != null"); Debug.Assert(service != null, "service != null"); Debug.Assert(tracker != null, "tracker != null"); ResourceSetWrapper container; object entityGettingModified = Deserializer.GetEntityResourceToModify(description, service, true /*allowCrossReference*/, out container); tracker.TrackAction(entityGettingModified, container, UpdateOperations.Change); Debug.Assert(description.Property != null, "description.Property != null"); if (description.IsSingleResult) { service.Updatable.SetReference(entityGettingModified, description.Property.Name, linkResource); } else { service.Updatable.AddReferenceToCollection(entityGettingModified, description.Property.Name, linkResource); } return entityGettingModified; }
/// <summary> /// Returns the last segment info whose target request kind is resource /// </summary> /// <param name="description">description about the target request</param> /// <param name="service">data service type to which the request was made</param> /// <param name="allowCrossReferencing">whether cross-referencing is allowed for the resource in question.</param> /// <param name="entityResource">entity resource which is getting modified.</param> /// <param name="entityContainer">entity container of the entity which is getting modified.</param> /// <param name="checkETag">whether to check the etag for the entity resource that is getting modified.</param> /// <returns>Returns the object that needs to get modified</returns> internal static object GetResourceToModify( RequestDescription description, IDataService service, bool allowCrossReferencing, out object entityResource, out ResourceSetWrapper entityContainer, bool checkETag) { // Set the index of the modifying resource int modifyingResourceIndex; if ( description.TargetKind == RequestTargetKind.OpenPropertyValue || description.TargetKind == RequestTargetKind.PrimitiveValue) { modifyingResourceIndex = description.SegmentInfos.Count - 3; } else { modifyingResourceIndex = description.SegmentInfos.Count - 2; } int entityResourceIndex; entityResource = Deserializer.GetEntityResourceToModify( description, service, allowCrossReferencing, out entityContainer, out entityResourceIndex); // now walk from the entity resource to the resource to modify. // for open types, as you walk, if the intermediate resource is an entity, // update the entityResource accordingly. object resourceToModify = entityResource; for (int i = entityResourceIndex + 1; i <= modifyingResourceIndex; i++) { // If the segment is a type identifier segment, skip the segment. There is no need to issue one more query // to the provider. if (description.SegmentInfos[i].IsTypeIdentifierSegment) { continue; } #if DEBUG SegmentInfo segmentInfo = description.SegmentInfos[i]; Debug.Assert(segmentInfo.TargetKind != RequestTargetKind.Resource, "segmentInfo.TargetKind != RequestTargetKind.Resource"); #endif resourceToModify = service.Updatable.GetValue(resourceToModify, description.SegmentInfos[i].Identifier); } // If checkETag is true, then we need to check the etag for the resource // Note that MediaResource has a separate etag, we don't need to check the MLE etag if the target kind is MediaResource if (checkETag && !WebUtil.IsCrossReferencedSegment(description.SegmentInfos[modifyingResourceIndex], service) && description.TargetKind != RequestTargetKind.MediaResource) { service.Updatable.SetETagValues(entityResource, entityContainer); } return resourceToModify; }
internal static Deserializer CreateDeserializer(RequestDescription description, IDataService dataService, bool update, UpdateTracker tracker) { string mimeType; System.Text.Encoding encoding; AstoriaRequestMessage host = dataService.OperationContext.RequestMessage; ContentTypeUtil.ReadContentType(host.ContentType, out mimeType, out encoding); Debug.Assert(tracker != null, "Change tracker must always be created."); Debug.Assert( (!update /*POST*/ && dataService.OperationContext.RequestMessage.HttpVerb == HttpVerbs.POST) || (update /*PUT,PATCH*/ && (dataService.OperationContext.RequestMessage.HttpVerb == HttpVerbs.PUT || dataService.OperationContext.RequestMessage.HttpVerb == HttpVerbs.PATCH)), "For PUT and PATCH, update must be true; for POST, update must be false"); if (description.IsServiceActionRequest) { return new ParameterDeserializer(update, dataService, tracker, description); } if (description.TargetKind == RequestTargetKind.OpenPropertyValue || description.TargetKind == RequestTargetKind.PrimitiveValue) { return new RawValueDeserializer(update, dataService, tracker, description); } if (description.TargetKind == RequestTargetKind.MediaResource) { return new MediaResourceDeserializer(update, dataService, tracker, description); } if (description.TargetKind == RequestTargetKind.Primitive || description.TargetKind == RequestTargetKind.ComplexObject || description.TargetKind == RequestTargetKind.Collection || description.TargetKind == RequestTargetKind.OpenProperty) { return new PropertyDeserializer(update, dataService, tracker, description); } if (description.LinkUri) { return new EntityReferenceLinkDeserializer(update, dataService, tracker, description); } if (description.TargetKind == RequestTargetKind.Resource) { return new EntityDeserializer(update, dataService, tracker, description); } throw new DataServiceException(415, Strings.RequestUriProcessor_MethodNotAllowed); }
/// <summary> /// Returns the entity that need to get modified /// </summary> /// <param name="description">description about the target request</param> /// <param name="service">data service type to which the request was made</param> /// <param name="allowCrossReferencing">whether cross-referencing is allowed for the resource in question.</param> /// <param name="entityContainer">entity container of the entity which is getting modified.</param> /// <returns>Returns the entity that needs to get modified</returns> internal static object GetEntityResourceToModify( RequestDescription description, IDataService service, bool allowCrossReferencing, out ResourceSetWrapper entityContainer) { int entityResourceIndex; return Deserializer.GetEntityResourceToModify( description, service, allowCrossReferencing, out entityContainer, out entityResourceIndex); }
/// <summary> /// Modify the value of the given resource to the given value /// </summary> /// <param name="description">description about the request</param> /// <param name="resourceToBeModified">resource that needs to be modified</param> /// <param name="requestValue">the new value for the target resource</param> /// <param name="service">Service this request is against</param> internal static void ModifyResource(RequestDescription description, object resourceToBeModified, object requestValue, IDataService service) { if (description.TargetKind == RequestTargetKind.OpenProperty || description.TargetKind == RequestTargetKind.OpenPropertyValue) { Debug.Assert(!description.LastSegmentInfo.HasKeyValues, "CreateSegments must have caught the problem already."); SetOpenPropertyValue(resourceToBeModified, description.ContainerName, requestValue, service); } else if (description.TargetKind == RequestTargetKind.MediaResource) { SetStreamPropertyValue(resourceToBeModified, (Stream)requestValue, service, description); } else { Debug.Assert( description.TargetKind == RequestTargetKind.Primitive || description.TargetKind == RequestTargetKind.ComplexObject || description.TargetKind == RequestTargetKind.PrimitiveValue || description.TargetKind == RequestTargetKind.Collection, "unexpected target kind encountered"); // update the primitive value ResourceProperty propertyToUpdate = description.LastSegmentInfo.ProjectedProperty; SetPropertyValue(propertyToUpdate, resourceToBeModified, requestValue, service); } }
/// <summary> /// Reads the action parameters from the payload. /// </summary> /// <param name="actionSegment">Segment info for the action whose parameters are being read.</param> /// <param name="dataService">Data service instance.</param> /// <returns>A dictionary of parameter name and parameter value pairs.</returns> internal static Dictionary<string, object> ReadPayloadParameters(SegmentInfo actionSegment, IDataService dataService) { Debug.Assert(actionSegment != null, "actionSegment != null"); RequestDescription requestDescription = new RequestDescription(new SegmentInfo[] { actionSegment }, RequestUriProcessor.GetResultUri(dataService.OperationContext)); Debug.Assert(requestDescription.IsServiceActionRequest, "IsServiceActionRequest(requestDescription)"); // Verify that the DSV is 4.0 or greater for parameters payload. requestDescription.VerifyRequestVersion(VersionUtil.Version4Dot0, dataService); using (Deserializer parameterDeserializer = Deserializer.CreateDeserializer(requestDescription, dataService, false /*update*/, UpdateTracker.CreateUpdateTracker(dataService))) { return (Dictionary<string, object>)parameterDeserializer.Deserialize(actionSegment); } }
/// <summary> /// Initializes a new instance of <see cref="EntityReferenceLinkDeserializer"/>. /// </summary> /// <param name="update">true if we're reading an update operation; false if not.</param> /// <param name="dataService">Data service for which the deserializer will act.</param> /// <param name="tracker">Tracker to use for modifications.</param> /// <param name="requestDescription">The request description to use.</param> internal EntityReferenceLinkDeserializer(bool update, IDataService dataService, UpdateTracker tracker, RequestDescription requestDescription) : base(update, dataService, tracker, requestDescription, true /*enableODataServerBehavior*/) { }
/// <summary> /// Returns true if we need to query the provider before updating. /// </summary> /// <param name="requestDescription">request description</param> /// <param name="requestValue">value corresponding to the payload for this request</param> /// <returns>returns true if we need to issue an query to satishfy the request</returns> private static bool IsQueryRequired(RequestDescription requestDescription, object requestValue) { Debug.Assert(requestDescription.IsSingleResult, "requestDescription.IsSingleResult"); if (requestDescription.TargetKind == RequestTargetKind.PrimitiveValue || requestDescription.TargetKind == RequestTargetKind.Primitive || requestDescription.TargetKind == RequestTargetKind.OpenPropertyValue || requestDescription.TargetKind == RequestTargetKind.MediaResource || requestDescription.TargetKind == RequestTargetKind.ComplexObject || requestDescription.TargetKind == RequestTargetKind.Collection) { return true; } if (requestDescription.TargetKind == RequestTargetKind.OpenProperty) { Debug.Assert(!requestDescription.LastSegmentInfo.HasKeyValues, "CreateSegments must have caught this issue."); ResourceType requestResourceType = requestDescription.LastSegmentInfo.TargetResourceType; // If this open property is collection, use resourceType in requestValue. var requestCollectionValue = requestValue as CollectionPropertyValueEnumerable; if (requestResourceType == null && requestCollectionValue != null) { requestResourceType = requestCollectionValue.ResourceType; return true; } Debug.Assert(requestValue == null || requestResourceType != null, "requestResourceType != null"); // if the value is null, then just set it, since we don't know the type if (requestValue == null || requestResourceType.ResourceTypeKind == ResourceTypeKind.Primitive) { return true; } // otherwise just set the complex type properties if (requestResourceType.ResourceTypeKind == ResourceTypeKind.ComplexType) { return true; } } return false; }
/// <summary> /// Create a new instance of ODataMessageWriterSettings for normal requests. /// </summary> /// <param name="dataService">Data service instance.</param> /// <param name="requestDescription">The current request description.</param> /// <param name="responseMessage">IODataResponseMessage implementation.</param> /// <param name="model">The model to provide to the message writer.</param> /// <returns>An instance of a message writer with the appropriate settings.</returns> internal static MessageWriterBuilder ForNormalRequest(IDataService dataService, RequestDescription requestDescription, IODataResponseMessage responseMessage, IEdmModel model) { Debug.Assert(dataService != null, "dataService != null"); Debug.Assert(dataService.OperationContext != null, "dataService.OperationContext != null"); Debug.Assert(requestDescription != null, "requestDescription != null"); Debug.Assert(dataService.OperationContext.RequestMessage != null, "dataService.OperationContext.RequestMessage != null"); Debug.Assert(responseMessage != null, "responseMessage != null"); Uri serviceUri = dataService.OperationContext.AbsoluteServiceUri; Version responseVersion = requestDescription.ActualResponseVersion; MessageWriterBuilder messageWriterBuilder = new MessageWriterBuilder(serviceUri, responseVersion, dataService, responseMessage, model); // ODataLib doesn't allow custom MIME types on raw values (must be text/plain for non-binary, and application/octet for binary values). // To maintain existing V1/V2 behavior, work around this by setting the format as RawValue (we handle conneg ourself for this, so don't make ODL do its own), // and then later manually override the content type header. Conneg is done by Astoria in DataService.CreateResponseBodyWriter. if (requestDescription.ResponsePayloadKind == ODataPayloadKind.Value && !string.IsNullOrEmpty(requestDescription.MimeType)) { messageWriterBuilder.WriterSettings.SetContentType(ODataFormat.RawValue); } else { string acceptHeaderValue = dataService.OperationContext.RequestMessage.GetAcceptableContentTypes(); // In V1/V2 we defaulted to charset=utf-8 for the response when there was no specific Accept-Charset. // ODataMessageWriter uses a different default in some cases depending on the media type, so we need to override that here. string requestAcceptCharSet = dataService.OperationContext.RequestMessage.GetRequestAcceptCharsetHeader(); if (string.IsNullOrEmpty(requestAcceptCharSet) || requestAcceptCharSet == "*") { requestAcceptCharSet = XmlConstants.Utf8Encoding; } messageWriterBuilder.WriterSettings.SetContentType(acceptHeaderValue, requestAcceptCharSet); } // always set the metadata document URI. ODataLib will decide whether or not to write it. messageWriterBuilder.WriterSettings.ODataUri = new ODataUri() { ServiceRoot = serviceUri, SelectAndExpand = requestDescription.ExpandAndSelect.Clause, Path = requestDescription.Path }; messageWriterBuilder.WriterSettings.JsonPCallback = requestDescription.JsonPaddingFunctionName; return(messageWriterBuilder); }
/// <summary> /// Handles post request. /// </summary> /// <param name="requestDescription">description about the uri for the post operation.</param> /// <returns>returns the resource that is getting inserted or binded - as specified in the payload.</returns> internal object HandlePostRequest(RequestDescription requestDescription) { Debug.Assert(!this.Update, "This method must be called for POST operations only"); Debug.Assert(requestDescription != null, "requestDescription != null"); object resourceInPayload; if (requestDescription.LinkUri) { string uri = this.GetLinkUriFromPayload(); resourceInPayload = this.GetTargetResourceToBind(uri, true /*checkNull*/); Debug.Assert(resourceInPayload != null, "link resource cannot be null"); Deserializer.HandleBindOperation(requestDescription, resourceInPayload, this.Service, this.Tracker); } else { if (requestDescription.LastSegmentInfo.TargetContainer != null) { DataServiceConfiguration.CheckResourceRights(requestDescription.LastSegmentInfo.TargetContainer, EntitySetRights.WriteAppend); } resourceInPayload = this.ReadEntity(requestDescription); if (requestDescription.TargetSource == RequestTargetSource.Property) { Debug.Assert(requestDescription.Property.Kind == ResourcePropertyKind.ResourceSetReference, "Expecting POST resource set property"); Deserializer.HandleBindOperation(requestDescription, resourceInPayload, this.Service, this.Tracker); } else { Debug.Assert(requestDescription.TargetSource == RequestTargetSource.EntitySet, "Expecting POST on entity set"); this.tracker.TrackAction(resourceInPayload, requestDescription.LastSegmentInfo.TargetContainer, UpdateOperations.Add); } } return resourceInPayload; }
/// <summary> /// Creates a new <see cref="Deserializer"/> for the specified stream. /// </summary> /// <param name="description">description about the request uri.</param> /// <param name="dataService">Data service for which the deserializer will act.</param> /// <param name="update">indicates whether this is a update operation or not</param> /// <param name="tracker">Tracker to use for modifications.</param> /// <returns>A new instance of <see cref="Deserializer"/>.</returns> internal static Deserializer CreateDeserializer(RequestDescription description, IDataService dataService, bool update, UpdateTracker tracker) { string mimeType; System.Text.Encoding encoding; DataServiceHostWrapper host = dataService.OperationContext.Host; HttpProcessUtility.ReadContentType(host.RequestContentType, out mimeType, out encoding); ContentFormat requestFormat = WebUtil.SelectRequestFormat(mimeType, description); Stream requestStream = host.RequestStream; Debug.Assert(requestStream != null, "requestStream != null"); Debug.Assert(tracker != null, "Change tracker must always be created."); Deserializer deserializer = null; Debug.Assert( (!update /*POST*/ && dataService.OperationContext.Host.AstoriaHttpVerb == AstoriaVerbs.POST) || (update /*PUT,MERGE*/ && (dataService.OperationContext.Host.AstoriaHttpVerb == AstoriaVerbs.MERGE || dataService.OperationContext.Host.AstoriaHttpVerb == AstoriaVerbs.PUT)), "For PUT and MERGE, update must be true; for POST, update must be false"); switch (requestFormat) { case ContentFormat.Json: deserializer = new JsonDeserializer( requestStream, encoding, update, dataService, tracker); break; case ContentFormat.Atom: SyndicationFormatterFactory factory = new Atom10FormatterFactory(); deserializer = new SyndicationDeserializer( requestStream, // stream encoding, // encoding dataService, // dataService update, factory, tracker); // factory break; case ContentFormat.PlainXml: deserializer = new PlainXmlDeserializer( requestStream, encoding, dataService, update, tracker); break; default: throw new DataServiceException(415, Strings.BadRequest_UnsupportedRequestContentType(host.RequestContentType)); } Debug.Assert(deserializer != null, "deserializer != null"); return deserializer; }
/// <summary> /// Deserializes the given stream into clr object as specified in the payload /// </summary> /// <param name="requestDescription">description about the target request</param> /// <returns>the object instance that it created and populated from the reader</returns> internal object ReadEntity(RequestDescription requestDescription) { Debug.Assert(requestDescription != null, "requestDescription != null"); this.description = requestDescription; if (requestDescription.TargetKind == RequestTargetKind.Resource) { Debug.Assert(requestDescription.LastSegmentInfo != null, "requestDescription.LastSegmentInfo != null"); Debug.Assert(requestDescription.LastSegmentInfo.TargetContainer != null, "requestDescription.LastSegmentInfo.TargetContainer != null"); Debug.Assert(requestDescription.TargetResourceType != null, "requestDescription.TargetResourceType != null"); this.RequestDescription.UpdateAndCheckEpmFeatureVersion(this.description.LastSegmentInfo.TargetContainer, this.Service); } // If the description points to a resource, // we need to materialize the object and return back. SegmentInfo segmentInfo = requestDescription.LastSegmentInfo; if (!this.Update) { Debug.Assert(!segmentInfo.SingleResult, "POST operation is allowed only on collections"); SegmentInfo adjustedSegment = new SegmentInfo(); adjustedSegment.TargetKind = segmentInfo.TargetKind; adjustedSegment.TargetSource = segmentInfo.TargetSource; adjustedSegment.SingleResult = true; adjustedSegment.ProjectedProperty = segmentInfo.ProjectedProperty; adjustedSegment.TargetResourceType = segmentInfo.TargetResourceType; adjustedSegment.TargetContainer = segmentInfo.TargetContainer; adjustedSegment.Identifier = segmentInfo.Identifier; segmentInfo = adjustedSegment; } return this.CreateSingleObject(segmentInfo); }
public static void SetInvalidClientRequest(this RequestDescription requestDescription) { requestDescription.SetAnnotation(InvalidClientRequestAnnotationName, true); }
/// <summary> /// Handle bind operation /// </summary> /// <param name="description">information about the request uri.</param> /// <param name="linkResource">the child resource which needs to be linked.</param> /// <param name="service">data service instance</param> /// <param name="tracker">update tracker instance to fire change interceptor calls</param> /// <returns>returns the parent object to which an new object was linked to.</returns> internal static object HandleBindOperation(RequestDescription description, object linkResource, IDataService service, UpdateTracker tracker) { Debug.Assert(description != null, "description != null"); Debug.Assert(linkResource != null, "linkResource != null"); Debug.Assert(service != null, "service != null"); Debug.Assert(tracker != null, "tracker != null"); object entityGettingModified; ResourceSetWrapper container; object resourceToBeModified = Deserializer.GetResourceToModify(description, service, true /*allowCrossReference*/, out entityGettingModified, out container, false /*checkETag*/); Debug.Assert(resourceToBeModified == entityGettingModified, "Since this is a link operation, modifying resource must be the entity resource"); // If the container we are modifying contains any type with FF mapped KeepInContent=false properties, we need to raise the FeatureVersion. description.UpdateAndCheckEpmFeatureVersion(container, service); tracker.TrackAction(entityGettingModified, container, UpdateOperations.Change); Debug.Assert(description.Property != null, "description.Property != null"); if (description.IsSingleResult) { service.Updatable.SetReference(entityGettingModified, description.Property.Name, linkResource); } else { service.Updatable.AddReferenceToCollection(entityGettingModified, description.Property.Name, linkResource); } return entityGettingModified; }
public static void SetPropertyForPropertyOnlyOperation(this RequestDescription requestDescription, ResourceProperty property) { requestDescription.SetAnnotation(PropertyForPropertyOnlyOperationName, property); }
public object GetResource(RequestDescription description, int segmentIndex, string typeFullName) { throw new NotImplementedException(); }
public static List <ResourceType> GetExpandedResourceTypes(this RequestDescription requestDescription) { return(requestDescription.GetAnnotation <List <ResourceType> >(ExpandedResourceTypesName)); }
/// <summary>Initializes a new <see cref="ResponseBodyWriter"/> that can write the body of a response.</summary> /// <param name="service">Service for the request being processed.</param> /// <param name="queryResults">Enumerator for results.</param> /// <param name="requestDescription">Description of request made to the system.</param> /// <param name="actualResponseMessageWhoseHeadersMayBeOverridden">IODataResponseMessage instance for the response.</param> internal ResponseBodyWriter( IDataService service, QueryResultInfo queryResults, RequestDescription requestDescription, IODataResponseMessage actualResponseMessageWhoseHeadersMayBeOverridden) { Debug.Assert(service != null, "service != null"); Debug.Assert(requestDescription != null, "requestDescription != null"); Debug.Assert(actualResponseMessageWhoseHeadersMayBeOverridden != null, "actualResponseMessageWhoseHeadersMayBeOverridden != null"); this.service = service; this.queryResults = queryResults; this.requestDescription = requestDescription; this.actualResponseMessageWhoseHeadersMayBeOverridden = actualResponseMessageWhoseHeadersMayBeOverridden; Debug.Assert(this.PayloadKind != ODataPayloadKind.Unsupported, "payloadKind != ODataPayloadKind.Unsupported"); this.encoding = ContentTypeUtil.EncodingFromAcceptCharset(this.service.OperationContext.RequestMessage.GetRequestAcceptCharsetHeader()); if (this.PayloadKind == ODataPayloadKind.Entry || this.PayloadKind == ODataPayloadKind.Feed || this.PayloadKind == ODataPayloadKind.Property || this.PayloadKind == ODataPayloadKind.Collection || this.PayloadKind == ODataPayloadKind.EntityReferenceLink || this.PayloadKind == ODataPayloadKind.EntityReferenceLinks || this.PayloadKind == ODataPayloadKind.Error || this.PayloadKind == ODataPayloadKind.ServiceDocument || this.PayloadKind == ODataPayloadKind.Parameter) { AstoriaRequestMessage requestMessage = service.OperationContext.RequestMessage; IODataResponseMessage responseMessageOnOperationContext = service.OperationContext.ResponseMessage; Version effectiveMaxResponseVersion = VersionUtil.GetEffectiveMaxResponseVersion(service.Configuration.DataServiceBehavior.MaxProtocolVersion.ToVersion(), requestMessage.RequestMaxVersion); bool isEntityOrFeed = this.PayloadKind == ODataPayloadKind.Entry || this.PayloadKind == ODataPayloadKind.Feed; if (ContentTypeUtil.IsResponseMediaTypeJsonLight(requestMessage.GetAcceptableContentTypes(), isEntityOrFeed, effectiveMaxResponseVersion)) { // If JSON light 'wins', then bump the version to V3. requestDescription.VerifyAndRaiseResponseVersion(VersionUtil.Version4Dot0, service); responseMessageOnOperationContext.SetHeader(XmlConstants.HttpODataVersion, XmlConstants.ODataVersion4Dot0 + ";"); } } if (this.requestDescription.TargetKind == RequestTargetKind.MediaResource) { Debug.Assert(this.PayloadKind == ODataPayloadKind.BinaryValue, "payloadKind == ODataPayloadKind.BinaryValue"); // Note that GetReadStream will set the ResponseETag before it returns this.mediaResourceStream = service.StreamProvider.GetReadStream( this.queryResults.Current, this.requestDescription.StreamProperty, this.service.OperationContext); } else if (this.PayloadKind != ODataPayloadKind.BinaryValue) { IEdmModel model; if (this.PayloadKind == ODataPayloadKind.MetadataDocument) { model = MetadataSerializer.PrepareModelForSerialization(this.service.Provider, this.service.Configuration); } else { model = this.GetModelFromService(); } // Create the message writer using which the response needs to be written. this.messageWriterBuilder = MessageWriterBuilder.ForNormalRequest( this.service, this.requestDescription, this.actualResponseMessageWhoseHeadersMayBeOverridden, model); this.messageWriter = this.messageWriterBuilder.CreateWriter(); try { // Make sure all the headers are written before the method returns. this.contentFormat = ODataUtils.SetHeadersForPayload(this.messageWriter, this.PayloadKind); } catch (ODataContentTypeException contentTypeException) { throw new DataServiceException(415, null, Strings.DataServiceException_UnsupportedMediaType, null, contentTypeException); } Debug.Assert(requestDescription.ResponseFormat != null, "Response format should already have been determined."); Debug.Assert(ReferenceEquals(this.contentFormat, requestDescription.ResponseFormat.Format), "Response format in request description did not match format when writing."); if (this.PayloadKind == ODataPayloadKind.Value && !String.IsNullOrEmpty(this.requestDescription.MimeType)) { this.actualResponseMessageWhoseHeadersMayBeOverridden.SetHeader(XmlConstants.HttpContentType, this.requestDescription.MimeType); } // EPM is currently removed, but this doesn't seem to be used for EPM only. The old comment was saying: // In astoria, there is a bug in V1/V2 that while computing response version, we did not take // epm into account. Hence while creating the writer, we need to pass the RequestDescription.ActualResponseVersion // so that ODataLib can do the correct payload validation. But we need to write the response version without // the epm into the response headers because of backward-compat issue. Hence over-writing the response version // header with the wrong version value. string responseVersion = this.requestDescription.ResponseVersion.ToString() + ";"; this.actualResponseMessageWhoseHeadersMayBeOverridden.SetHeader(XmlConstants.HttpODataVersion, responseVersion); } }
public static bool GetPostServiceOperation(this RequestDescription requestDescription) { return(requestDescription.GetAnnotation <bool?>(PostServiceOperationName) == true); }
/// <summary> /// Creates a Media Link Entry. /// </summary> /// <param name="fullTypeName">Full type name for the MLE to be created.</param> /// <param name="requestStream">Request stream from the host.</param> /// <param name="service">Service this request is against.</param> /// <param name="description">Description of the target request.</param> /// <param name="tracker">Update tracker instance to fire change interceptor calls</param> /// <returns>Newly created Media Link Entry.</returns> internal static object CreateMediaLinkEntry(string fullTypeName, Stream requestStream, IDataService service, RequestDescription description, UpdateTracker tracker) { Debug.Assert(!string.IsNullOrEmpty(fullTypeName), "!string.IsNullOrEmpty(fullTypeName)"); Debug.Assert(requestStream != null, "requestStream != null"); Debug.Assert(service != null, "service != null"); Debug.Assert(description != null, "description != null"); Debug.Assert(tracker != null, "tracker != null"); object entity = service.Updatable.CreateResource(description.LastSegmentInfo.TargetResourceSet.Name, fullTypeName); tracker.TrackAction(entity, description.LastSegmentInfo.TargetResourceSet, UpdateOperations.Add); SetStreamPropertyValue(entity, requestStream, service, description); return entity; }
internal NonEntitySerializer(RequestDescription requestDescription, Uri absoluteServiceUri, IDataService service, ODataMessageWriter messageWriter) : base(requestDescription, absoluteServiceUri, service, null) { this.writer = messageWriter; }
/// <summary> /// Copy the contents of the request stream into the default stream of the specified entity. /// </summary> /// <param name="resourceToBeModified">Entity with the associated stream which we will write to.</param> /// <param name="requestStream">Request stream from the host</param> /// <param name="service">Service this is request is against</param> /// <param name="description">Description of the target request.</param> internal static void SetStreamPropertyValue(object resourceToBeModified, Stream requestStream, IDataService service, RequestDescription description) { Debug.Assert(resourceToBeModified != null, "resourceToBeModified != null"); Debug.Assert(requestStream.CanRead, "requestStream.CanRead"); Debug.Assert(service != null, "service != null"); resourceToBeModified = service.Updatable.ResolveResource(resourceToBeModified); ResourceType resourceType = service.Provider.GetResourceType(resourceToBeModified); if (!resourceType.IsMediaLinkEntry) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidUriForMediaResource(service.OperationContext.AbsoluteRequestUri)); } if (service.OperationContext.Host.AstoriaHttpVerb == AstoriaVerbs.MERGE) { throw DataServiceException.CreateMethodNotAllowed( Strings.BadRequest_InvalidUriForMergeOperation(service.OperationContext.AbsoluteRequestUri), DataServiceConfiguration.GetAllowedMethods(service.Configuration, description)); } using (Stream writeStream = service.StreamProvider.GetWriteStream(resourceToBeModified, service.OperationContext)) { WebUtil.CopyStream(requestStream, writeStream, service.StreamProvider.StreamBufferSize); } }
/// <summary> /// Initializes a new instance of <see cref="RawValueDeserializer"/>. /// </summary> /// <param name="update">true if we're reading an update operation; false if not.</param> /// <param name="dataService">Data service for which the deserializer will act.</param> /// <param name="tracker">Tracker to use for modifications.</param> /// <param name="requestDescription">The request description to use.</param> internal RawValueDeserializer(bool update, IDataService dataService, UpdateTracker tracker, RequestDescription requestDescription) : base(update, dataService, tracker, requestDescription, true /*enableODataServerBehavior*/) { }
/// <summary> /// Returns the last segment info whose target request kind is resource /// </summary> /// <param name="description">description about the target request</param> /// <param name="service">data service type to which the request was made</param> /// <param name="allowCrossReferencing">whether cross-referencing is allowed for the resource in question.</param> /// <param name="entityResource">entity resource which is getting modified.</param> /// <param name="entityContainer">entity container of the entity which is getting modified.</param> /// <param name="checkETag">whether to check the etag for the entity resource that is getting modified.</param> /// <returns>Returns the object that needs to get modified</returns> internal static object GetResourceToModify( RequestDescription description, IDataService service, bool allowCrossReferencing, out object entityResource, out ResourceSetWrapper entityContainer, bool checkETag) { Debug.Assert(description.SegmentInfos.Length >= 2, "description.SegmentInfos.Length >= 2"); UpdatableWrapper updatable = service.Updatable; if (!allowCrossReferencing && description.RequestEnumerable == null) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_ResourceCanBeCrossReferencedOnlyForBindOperation); } // Set the index of the modifying resource int modifyingResourceIndex = -1; if ( description.TargetKind == RequestTargetKind.OpenPropertyValue || description.TargetKind == RequestTargetKind.PrimitiveValue) { modifyingResourceIndex = description.SegmentInfos.Length - 3; } else { modifyingResourceIndex = description.SegmentInfos.Length - 2; } // Get the index of the entity resource that is getting modified int entityResourceIndex = -1; if (description.LinkUri) { entityResourceIndex = modifyingResourceIndex; } else { for (int j = modifyingResourceIndex; j >= 0; j--) { if (description.SegmentInfos[j].TargetKind == RequestTargetKind.Resource || description.SegmentInfos[j].HasKeyValues) { entityResourceIndex = j; break; } } } Debug.Assert(entityResourceIndex != -1, "This method should never be called for request that doesn't have a parent resource"); entityContainer = description.SegmentInfos[entityResourceIndex].TargetContainer; if (entityContainer != null) { DataServiceHostWrapper host = service.OperationContext.Host; // Since this is the entity which is going to get modified, then we need to check for rights if (host.AstoriaHttpVerb == AstoriaVerbs.PUT) { DataServiceConfiguration.CheckResourceRights(entityContainer, EntitySetRights.WriteReplace); } else if (host.AstoriaHttpVerb == AstoriaVerbs.MERGE) { DataServiceConfiguration.CheckResourceRights(entityContainer, EntitySetRights.WriteMerge); } else { Debug.Assert( host.AstoriaHttpVerb == AstoriaVerbs.POST || host.AstoriaHttpVerb == AstoriaVerbs.DELETE, "expecting POST and DELETE methods"); DataServiceConfiguration.CheckResourceRights(entityContainer, EntitySetRights.WriteMerge | EntitySetRights.WriteReplace); } } entityResource = service.GetResource(description, entityResourceIndex, null); if (entityResource == null) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_DereferencingNullPropertyValue(description.SegmentInfos[entityResourceIndex].Identifier)); } // now walk from the entity resource to the resource to modify. // for open types, as you walk, if the intermediate resource is an entity, // update the entityResource accordingly. object resourceToModify = entityResource; for (int i = entityResourceIndex + 1; i <= modifyingResourceIndex; i++) { resourceToModify = updatable.GetValue(resourceToModify, description.SegmentInfos[i].Identifier); } if (entityContainer == null) { Debug.Assert( description.TargetKind == RequestTargetKind.OpenProperty || description.TargetKind == RequestTargetKind.OpenPropertyValue, "its a open property target. Hence resource set must be null"); // Open navigation properties are not supported on OpenTypes. throw DataServiceException.CreateBadRequestError(Strings.OpenNavigationPropertiesNotSupportedOnOpenTypes(description.SegmentInfos[entityResourceIndex].Identifier)); } // If checkETag is true, then we need to check the etag for the resource // Note that MediaResource has a separate etag, we don't need to check the MLE etag if the target kind is MediaResource if (checkETag && !Deserializer.IsCrossReferencedSegment(description.SegmentInfos[modifyingResourceIndex], service) && description.TargetKind != RequestTargetKind.MediaResource) { service.Updatable.SetETagValues(entityResource, entityContainer); } return resourceToModify; }
public void AddRequest(RequestDescription request) { AddToAnyCache(request); }
/// <summary> /// Gets the resource to modify. /// </summary> /// <param name="description">description about the target request</param> /// <param name="service">data service type to which the request was made</param> /// <param name="entityResource">entity resource which is getting modified.</param> /// <param name="container">entity container of the entity which is getting modified.</param> /// <returns>Returns the object that needs to get modified</returns> internal static object GetResourceToModify(RequestDescription description, IDataService service, out object entityResource, out ResourceSetWrapper container) { return GetResourceToModify(description, service, false /*allowCrossReference*/, out entityResource, out container, false /*checkETag*/); }
internal MediaResourceDeserializer(bool update, IDataService dataService, UpdateTracker tracker, RequestDescription requestDescription) : base(update, dataService, tracker, requestDescription) { }
/// <summary> /// Update the resource specified in the given request description /// </summary> /// <param name="description">description about the request uri</param> /// <param name="dataService">data service type to which the request was made</param> /// <param name="stream">Stream from which request body should be read.</param> /// <returns>The tracked modifications.</returns> internal static RequestDescription HandlePutRequest(RequestDescription description, IDataService dataService, Stream stream) { Debug.Assert(stream != null, "stream != null"); Debug.Assert(dataService != null, "dataService != null"); object requestValue = null; ContentFormat requestFormat; object entityGettingModified = null; ResourceSetWrapper container = null; string mimeType; Encoding encoding; DataServiceHostWrapper host = dataService.OperationContext.Host; HttpProcessUtility.ReadContentType(host.RequestContentType, out mimeType, out encoding); UpdateTracker tracker = UpdateTracker.CreateUpdateTracker(dataService); Debug.Assert(tracker != null, "Change tracker must always be created."); // If its a primitive value that is getting modified, then we need to use the text or binary // serializer depending on the mime type if (description.TargetKind == RequestTargetKind.OpenPropertyValue || description.TargetKind == RequestTargetKind.PrimitiveValue) { string contentType; requestFormat = WebUtil.GetResponseFormatForPrimitiveValue(description.TargetResourceType, out contentType); if (!WebUtil.CompareMimeType(contentType, mimeType)) { if (description.TargetResourceType != null) { throw new DataServiceException(415, Strings.BadRequest_InvalidContentType(host.RequestContentType, description.TargetResourceType.Name)); } else { throw new DataServiceException(415, Strings.BadRequest_InvalidContentTypeForOpenProperty(host.RequestContentType, description.ContainerName)); } } if (requestFormat == ContentFormat.Binary) { byte[] propertyValue = ReadByteStream(stream); if (description.Property != null && description.Property.Type == typeof(System.Data.Linq.Binary)) { requestValue = new System.Data.Linq.Binary(propertyValue); } else { requestValue = propertyValue; } } else { Debug.Assert(requestFormat == ContentFormat.Text, "requestFormat == ContentFormat.Text"); Debug.Assert(encoding != null, "encoding != null"); StreamReader requestReader = new StreamReader(stream, encoding); string propertyValue = Deserializer.ReadStringFromStream(requestReader); if (description.Property != null && propertyValue != null) { try { // Convert the property value to the correct type requestValue = WebConvert.StringToPrimitive((string)propertyValue, description.Property.Type); } catch (FormatException e) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_ErrorInConvertingPropertyValue(description.Property.Name, description.Property.Type), e); } } else { // For open types, there is no conversion required. There is not enough information to do the conversion. requestValue = propertyValue; } } } else if (description.TargetKind == RequestTargetKind.MediaResource) { requestFormat = ContentFormat.Binary; requestValue = stream; } else { requestFormat = WebUtil.SelectRequestFormat(mimeType, description); using (Deserializer deserializer = Deserializer.CreateDeserializer(description, dataService, true /*update*/, tracker)) { if (description.LinkUri) { string uri = deserializer.GetLinkUriFromPayload(); // No need to check for null - if the uri in the payload is /Customer(1)/BestFriend, // and the value is null, it means that the user wants to set the current link to null // i.e. in other words, unbind the relationship. object linkResource = deserializer.GetTargetResourceToBind(uri, true /*checkNull*/); entityGettingModified = Deserializer.HandleBindOperation(description, linkResource, deserializer.Service, deserializer.Tracker); container = description.LastSegmentInfo.TargetContainer; } else { requestValue = deserializer.ReadEntity(description); if (requestValue == null && description.LastSegmentInfo.HasKeyValues && description.TargetSource == RequestTargetSource.EntitySet) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_CannotSetTopLevelResourceToNull(description.ResultUri.OriginalString)); } } } } // Update the property value, if the request target is property if (!description.LinkUri && IsQueryRequired(description, requestValue, dataService.Provider)) { // Get the parent entity and its container and the resource to modify object resourceToModify = GetResourceToModify( description, dataService, false /*allowCrossReferencing*/, out entityGettingModified, out container, true /*checkETag*/); tracker.TrackAction(entityGettingModified, container, UpdateOperations.Change); Deserializer.ModifyResource(description, resourceToModify, requestValue, requestFormat, dataService); } tracker.FireNotifications(); if (entityGettingModified == null) { entityGettingModified = requestValue; container = description.LastSegmentInfo.TargetContainer; } return RequestDescription.CreateSingleResultRequestDescription(description, entityGettingModified, container); }
public string Read(string key, out RequestDescription result) { return(_redisTable.Read(key, out result)); }
/// <summary> /// Copy the contents of the request stream into the default stream of the specified entity. /// </summary> /// <param name="resourceToBeModified">Entity with the associated stream which we will write to.</param> /// <param name="requestStream">Request stream from the host</param> /// <param name="service">Service this is request is against</param> /// <param name="description">Description of the target request.</param> internal static void SetStreamPropertyValue(object resourceToBeModified, Stream requestStream, IDataService service, RequestDescription description) { Debug.Assert(resourceToBeModified != null, "resourceToBeModified != null"); Debug.Assert(requestStream.CanRead, "requestStream.CanRead"); Debug.Assert(service != null, "service != null"); resourceToBeModified = service.Updatable.ResolveResource(resourceToBeModified); ResourceType resourceType = service.Provider.GetResourceType(resourceToBeModified); // We are here because one of the following conditions is true: // 1. This is a POST MR, in which case we get here because resourceType.IsMediaLinkEntry is true. // 2. This is a PUT default/named stream, so target kind is MediaResource but resourceType can be either an MLE or non-MLE. // // If target kind is MediaResource and this is not a named stream, the current endpoint is /entity/$value. We need to verify that // resourceType is an MLE. At URI processing time, we don't have the actual entity instance to test whether it is an MLE or not, so // we postpone the test untill now. if (description.TargetKind == RequestTargetKind.MediaResource && !description.IsNamedStream && !resourceType.IsMediaLinkEntry) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidUriForMediaResource(service.OperationContext.AbsoluteRequestUri)); } if (service.OperationContext.RequestMessage.HttpVerb == HttpVerbs.PATCH) { throw DataServiceException.CreateMethodNotAllowed( Strings.BadRequest_InvalidUriForPatchOperation(service.OperationContext.AbsoluteRequestUri), DataServiceConfiguration.GetAllowedMethods(service.Configuration, description)); } Debug.Assert( (service.OperationContext.RequestMessage.HttpVerb == HttpVerbs.POST && resourceType.IsMediaLinkEntry) || (service.OperationContext.RequestMessage.HttpVerb == HttpVerbs.PUT && description.TargetKind == RequestTargetKind.MediaResource), "We are here because this is either a POST to an Atom MR or a PUT to a default/named stream."); ResourceProperty streamProperty = null; // null for default stream. if (description.TargetKind == RequestTargetKind.MediaResource) { streamProperty = description.StreamProperty; } using (Stream writeStream = service.StreamProvider.GetWriteStream(resourceToBeModified, streamProperty, service.OperationContext)) { WebUtil.CopyStream(requestStream, writeStream, service.StreamProvider.StreamBufferSize); } }