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); }
// 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); }
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 } }