Esempio n. 1
0
        private static string GetRootElementName(ODataPath path)
        {
            if (path != null)
            {
                ODataPathSegment lastSegment = path.Segments.LastOrDefault();
                if (lastSegment != null)
                {
                    OperationSegment actionSegment = lastSegment as OperationSegment;
                    if (actionSegment != null)
                    {
                        IEdmAction action = actionSegment.Operations.Single() as IEdmAction;
                        if (action != null)
                        {
                            return(action.Name);
                        }
                    }

                    PropertySegment propertyAccessSegment = lastSegment as PropertySegment;
                    if (propertyAccessSegment != null)
                    {
                        return(propertyAccessSegment.Property.Name);
                    }
                }
            }
            return(null);
        }
        internal static IEdmAction GetAction(ODataDeserializerContext readContext)
        {
            if (readContext == null)
            {
                throw Error.ArgumentNull("readContext");
            }

            ODataPath path = readContext.Path;

            if (path == null || path.Segments.Count == 0)
            {
                throw new SerializationException(SRResources.ODataPathMissing);
            }

            IEdmAction action = null;

            if (path.PathTemplate == "~/unboundaction")
            {
                // only one segment, it may be an unbound action
                OperationImportSegment unboundActionSegment = path.Segments.Last() as OperationImportSegment;
                if (unboundActionSegment != null)
                {
                    IEdmActionImport actionImport = unboundActionSegment.OperationImports.First() as IEdmActionImport;
                    if (actionImport != null)
                    {
                        action = actionImport.Action;
                    }
                }
            }
            else
            {
                // otherwise, it may be a bound action
                OperationSegment actionSegment = path.Segments.Last() as OperationSegment;
                if (actionSegment != null)
                {
                    action = actionSegment.Operations.First() as IEdmAction;
                }
            }

            if (action == null)
            {
                string message = Error.Format(SRResources.RequestNotActionInvocation, path.ToString());
                throw new SerializationException(message);
            }

            return(action);
        }
Esempio n. 3
0
        // This function is used to determine whether an OData path includes operation (import) path segments.
        // We use this function to make sure the value of ODataUri.Path in ODataMessageWriterSettings is null
        // when any path segment is an operation. ODL will try to calculate the context URL if the ODataUri.Path
        // equals to null.
        private static bool IsOperationPath(ODataPath path)
        {
            if (path == null)
            {
                return(false);
            }

            foreach (ODataPathSegment segment in path.Segments)
            {
                if (segment is OperationSegment ||
                    segment is OperationImportSegment)
                {
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 4
0
        private void WriteResponseBody(OutputFormatterWriteContext context)
        {
            HttpContext  httpContext = context.HttpContext;
            HttpRequest  request     = context.HttpContext.Request;
            HttpResponse response    = context.HttpContext.Response;

            IEdmModel model = context.HttpContext.ODataFeature().Model;

            if (model == null)
            {
                throw Error.InvalidOperation(SRResources.RequestMustHaveModel);
            }

            object value        = null;
            object graph        = null;
            var    objectResult = context.Object as PageResult <object>;

            if (objectResult != null)
            {
                value = objectResult.Items;
                graph = objectResult;
            }
            else
            {
                value = context.Object;
                graph = value;
            }
            var type = value.GetType();

            ODataSerializer serializer = GetSerializer(type, value, context);

            IUrlHelper urlHelper = context.HttpContext.UrlHelper();

            ODataPath            path = httpContext.ODataFeature().Path;
            IEdmNavigationSource targetNavigationSource = path == null ? null : path.NavigationSource;

            string preferHeader     = RequestPreferenceHelpers.GetRequestPreferHeader(request);
            string annotationFilter = null;

            if (!String.IsNullOrEmpty(preferHeader))
            {
                ODataMessageWrapper messageWrapper = new ODataMessageWrapper(response.Body, response.Headers);
                messageWrapper.SetHeader(RequestPreferenceHelpers.PreferHeaderName, preferHeader);
                annotationFilter = messageWrapper.PreferHeader().AnnotationFilter;
            }

            IODataResponseMessage responseMessage = new ODataMessageWrapper(response.Body, response.Headers);

            if (annotationFilter != null)
            {
                responseMessage.PreferenceAppliedHeader().AnnotationFilter = annotationFilter;
            }

            Uri baseAddress = GetBaseAddress(request);
            ODataMessageWriterSettings writerSettings = _messageWriterSettings.Clone();

            writerSettings.BaseUri     = baseAddress;
            writerSettings.Version     = ODataVersion.V4;
            writerSettings.Validations = writerSettings.Validations & ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType;

            string metadataLink = urlHelper.CreateODataLink(request, MetadataSegment.Instance);

            if (metadataLink == null)
            {
                throw new SerializationException(SRResources.UnableToDetermineMetadataUrl);
            }

            writerSettings.ODataUri = new ODataUri
            {
                ServiceRoot = baseAddress,

                // TODO: 1604 Convert webapi.odata's ODataPath to ODL's ODataPath, or use ODL's ODataPath.
                SelectAndExpand = httpContext.ODataFeature().SelectExpandClause,
                Path            = (path == null) ? null : path.ODLPath
                                  //Path = (path == null || IsOperationPath(path)) ? null : path.ODLPath,
            };

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model))
            {
                ODataSerializerContext writeContext = new ODataSerializerContext()
                {
                    Context          = context.HttpContext,
                    Url              = urlHelper,
                    NavigationSource = targetNavigationSource,
                    Model            = model,
                    RootElementName  = GetRootElementName(path) ?? "root",
                    SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.ResourceSet,
                    Path               = path,
                    MetadataLevel      = ODataMediaTypes.GetMetadataLevel(MediaTypeHeaderValue.Parse(context.ContentType.Value)),
                    SelectExpandClause = request.ODataFeature().SelectExpandClause,
                };

                serializer.WriteObject(graph, type, messageWriter, writeContext);
            }
        }
        private static void GenerateBaseODataPathSegmentsForNonSingletons(
            ODataPath path,
            IEdmNavigationSource navigationSource,
            IList <ODataPathSegment> odataPath)
        {
            // If the navigation is not a singleton we need to walk all of the path segments to generate a
            // contextually accurate URI.
            bool segmentFound   = false;
            bool containedFound = false;

            if (path != null)
            {
                var segments = path.Segments;
                int length   = segments.Count;
                int previousNavigationPathIndex = -1;
                for (int i = 0; i < length; i++)
                {
                    ODataPathSegment     pathSegment             = segments[i];
                    IEdmNavigationSource currentNavigationSource = null;

                    var entitySetPathSegment = pathSegment as EntitySetSegment;
                    if (entitySetPathSegment != null)
                    {
                        currentNavigationSource = entitySetPathSegment.EntitySet;
                    }

                    var navigationPathSegment = pathSegment as NavigationPropertySegment;
                    if (navigationPathSegment != null)
                    {
                        currentNavigationSource = navigationPathSegment.NavigationSource;
                    }
                    if (containedFound)
                    {
                        odataPath.Add(pathSegment);
                    }
                    else
                    {
                        if (navigationPathSegment != null &&
                            navigationPathSegment.NavigationProperty.ContainsTarget)
                        {
                            containedFound = true;
                            //The path should have the last non-contained navigation property
                            if (previousNavigationPathIndex != -1)
                            {
                                for (int j = previousNavigationPathIndex; j <= i; j++)
                                {
                                    odataPath.Add(segments[j]);
                                }
                            }
                        }
                    }

                    // If we've found our target navigation in the path that means we've correctly populated the
                    // segments up to the navigation and we can ignore the remaining segments.
                    if (currentNavigationSource != null)
                    {
                        previousNavigationPathIndex = i;
                        if (currentNavigationSource == navigationSource)
                        {
                            segmentFound = true;
                            break;
                        }
                    }
                }
            }

            if (!segmentFound || !containedFound)
            {
                // If the target navigation was not found in the current path that means we lack any context that
                // would suggest a scenario other than directly accessing an entity set, so we must assume that's
                // the case.
                odataPath.Clear();

                IEdmContainedEntitySet containmnent = navigationSource as IEdmContainedEntitySet;
                if (containmnent != null)
                {
                    EdmEntityContainer container = new EdmEntityContainer("NS", "Default");
                    IEdmEntitySet      entitySet = new EdmEntitySet(container, navigationSource.Name,
                                                                    navigationSource.EntityType());
                    odataPath.Add(new EntitySetSegment(entitySet));
                }
                else
                {
                    odataPath.Add(new EntitySetSegment((IEdmEntitySet)navigationSource));
                }
            }
        }
        ///// <summary>
        ///// Initializes a new instance of the <see cref="ODataCountMediaTypeMapping"/> class.
        ///// </summary>
        //public ODataCountMediaTypeMapping()
        //    : base("text/plain")
        //{
        //}

        ///// <inheritdoc/>
        //public override double TryMatchMediaType(HttpRequestMessage request)
        //{
        //    if (request == null)
        //    {
        //        throw Error.ArgumentNull("request");
        //    }

        //    return IsCountRequest(request) ? 1 : 0;
        //}

        internal static bool IsCountRequest(HttpContext context)
        {
            ODataPath path = context.ODataFeature().Path;

            return(path != null && path.Segments.LastOrDefault() is CountSegment);
        }
        private void WriteResponseBody(OutputFormatterWriteContext context)
        {
            HttpContext  httpContext = context.HttpContext;
            HttpRequest  request     = context.HttpContext.Request;
            HttpResponse response    = context.HttpContext.Response;

            IEdmModel model = context.HttpContext.ODataFeature().Model;

            if (model == null)
            {
                throw Error.InvalidOperation(SRResources.RequestMustHaveModel);
            }

            object value        = null;
            object graph        = null;
            var    objectResult = context.Object as PageResult <object>;

            if (objectResult != null)
            {
                value = objectResult.Items;
                graph = objectResult;
            }
            else
            {
                value = context.Object;
                graph = value;
            }
            var type = value.GetType();

            ODataSerializer serializer = GetSerializer(type, value, context);

            IUrlHelper urlHelper = context.HttpContext.UrlHelper();

            ODataPath            path = httpContext.ODataFeature().Path;
            IEdmNavigationSource targetNavigationSource = path == null ? null : path.NavigationSource;

            string preferHeader     = RequestPreferenceHelpers.GetRequestPreferHeader(request);
            string annotationFilter = null;

            if (!String.IsNullOrEmpty(preferHeader))
            {
                ODataMessageWrapper messageWrapper = new ODataMessageWrapper(response.Body, response.Headers);
                messageWrapper.SetHeader(RequestPreferenceHelpers.PreferHeaderName, preferHeader);
                annotationFilter = messageWrapper.PreferHeader().AnnotationFilter;
            }

            IODataResponseMessage responseMessage = new ODataMessageWrapper(response.Body, response.Headers);

            if (annotationFilter != null)
            {
                responseMessage.PreferenceAppliedHeader().AnnotationFilter = annotationFilter;
            }

            Uri baseAddress = GetBaseAddress(request);
            ODataMessageWriterSettings writerSettings = _messageWriterSettings.Clone();

            writerSettings.BaseUri     = baseAddress;
            writerSettings.Version     = ODataVersion.V4;
            writerSettings.Validations = writerSettings.Validations & ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType;

            string metadataLink = urlHelper.CreateODataLink(request, MetadataSegment.Instance);

            if (metadataLink == null)
            {
                throw new SerializationException(SRResources.UnableToDetermineMetadataUrl);
            }

            writerSettings.ODataUri = new ODataUri
            {
                ServiceRoot = baseAddress,

                // TODO: 1604 Convert webapi.odata's ODataPath to ODL's ODataPath, or use ODL's ODataPath.
                SelectAndExpand = httpContext.ODataFeature().SelectExpandClause,
                Path            = (path == null) ? null : path.ODLPath
                                  //Path = (path == null || IsOperationPath(path)) ? null : path.ODLPath,
            };

            #region 为OData添加缓存  使用的EF二级缓存 这里是先从缓存获取数据
            //var queryResult = graph as IQueryable;
            //PageResult<object> target = null;
            //if (queryResult == null)
            //{
            //    target = graph as PageResult<object>;
            //    if (target != null) queryResult = target.Items.AsQueryable();
            //}
            //var isReadCache = queryResult != null || target != null;

            //var cacheValue = isReadCache?queryResult.CacheResult(context.HttpContext.RequestServices):null;

            //if (isReadCache&&target != null && cacheValue != null)
            //{
            //    var pageResult = cacheValue as IEnumerable<object>;
            //    //long? count = target.Count.HasValue ? (long?)pageResult.LongCount() : null;
            //    cacheValue = new PageResult<object>(pageResult, null, target.Count);
            //}

            //if (isReadCache&&cacheValue != null) graph = cacheValue;

            #endregion

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model))
            {
                ODataSerializerContext writeContext = new ODataSerializerContext()
                {
                    Context          = context.HttpContext,
                    Url              = urlHelper,
                    NavigationSource = targetNavigationSource,
                    Model            = model,
                    RootElementName  = GetRootElementName(path) ?? "root",
                    SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.ResourceSet,
                    Path               = path,
                    MetadataLevel      = ODataMediaTypes.GetMetadataLevel(MediaTypeHeaderValue.Parse(context.ContentType.Value)),
                    SelectExpandClause = request.ODataFeature().SelectExpandClause,
                };

                serializer.WriteObject(graph, type, messageWriter, writeContext);

                #region 这里是往缓存中 存储数据
                //if (isReadCache&&cacheValue == null)
                //{
                //    writeContext.Context.Response.Body.Position = 0;
                //    StreamReader reder = new StreamReader(writeContext.Context.Response.Body);
                //    var bodyStr = reder.ReadToEnd();
                //    JObject.Parse(bodyStr).TryGetValue("value",out JToken values);
                //    cacheValue = values.ToObject(type.MarkListType());

                //    queryResult.CacheQuerable(cacheValue, writeContext.Context.RequestServices);
                //}
                #endregion
            }
        }