/// <inheritdoc/> public override bool CanWriteType(Type type) { if (type == null) { throw Error.ArgumentNull("type"); } if (Request != null) { ODataSerializerProvider serializerProvider = Request.GetRequestContainer() .GetRequiredService <ODataSerializerProvider>(); // See if this type is a SingleResult or is derived from SingleResult. bool isSingleResult = false; if (type.IsGenericType) { Type genericType = type.GetGenericTypeDefinition(); Type baseType = TypeHelper.GetBaseType(type); isSingleResult = (genericType == typeof(SingleResult <>) || baseType == typeof(SingleResult)); } return(ODataOutputFormatterHelper.CanWriteType( type, _payloadKinds, isSingleResult, new WebApiRequestMessage(Request), (objectType) => serializerProvider.GetODataPayloadSerializer(objectType, Request))); } return(false); }
/// <inheritdoc/> public override bool CanWriteType(Type type) { if (type == null) { throw Error.ArgumentNull("type"); } ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(type); if (serializer == null) { return(false); } return(_payloadKinds.Contains(serializer.ODataPayloadKind)); }
/// <inheritdoc/> public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) { Type type = context.ObjectType; if (type == null) { throw Error.ArgumentNull("type"); } type = TypeHelper.GetTaskInnerTypeOrSelf(type); HttpRequest request = context.HttpContext.Request; if (request == null) { throw Error.InvalidOperation(SRResources.WriteToStreamAsyncMustHaveRequest); } HttpResponse response = context.HttpContext.Response; if (typeof(Stream).IsAssignableFrom(type)) { // Ideally, it should go into the "ODataRawValueSerializer", // However, OData lib doesn't provide the method to overwrite/copyto stream // So, Here's the workaround Stream objStream = context.Object as Stream; return(CopyStreamAsync(objStream, response)); } Uri baseAddress = GetBaseAddressInternal(request); MediaTypeHeaderValue contentType = GetContentType(response.Headers[HeaderNames.ContentType].FirstOrDefault()); Func <ODataSerializerContext> getODataSerializerContext = () => { return(new ODataSerializerContext() { Request = request, }); }; ODataSerializerProvider serializerProvider = request.GetRequestContainer().GetRequiredService <ODataSerializerProvider>(); return(ODataOutputFormatterHelper.WriteToStreamAsync( type, context.Object, request.GetModel(), ResultHelpers.GetODataResponseVersion(request), baseAddress, contentType, new WebApiUrlHelper(request.GetUrlHelper()), new WebApiRequestMessage(request), new WebApiRequestHeaders(request.Headers), (services) => ODataMessageWrapperHelper.Create(new StreamWrapper(response.Body), response.Headers, services), (edmType) => serializerProvider.GetEdmTypeSerializer(edmType), (objectType) => serializerProvider.GetODataPayloadSerializer(objectType, request), getODataSerializerContext)); }
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) { Type type = context.ObjectType; if (type == null) { throw Error.ArgumentNull("type"); } type = TypeHelper.GetTaskInnerTypeOrSelf(type); HttpRequest request = context.HttpContext.Request; if (request == null) { throw Error.InvalidOperation(SRResources.WriteToStreamAsyncMustHaveRequest); } try { HttpResponse response = context.HttpContext.Response; Uri baseAddress = GetBaseAddressInternal(request); MediaTypeHeaderValue contentType = GetContentType(response.Headers[HeaderNames.ContentType].FirstOrDefault()); Func <ODataSerializerContext> getODataSerializerContext = () => { return(new ODataSerializerContext() { Request = request, }); }; ODataSerializerProvider serializerProvider = request.GetRequestContainer().GetRequiredService <ODataSerializerProvider>(); ODataOutputFormatterHelper.WriteToStream( type, context.Object, request.GetModel(), ResultHelpers.GetODataResponseVersion(request), baseAddress, contentType, new WebApiUrlHelper(request.GetUrlHelper()), new WebApiRequestMessage(request), new WebApiRequestHeaders(request.Headers), (services) => ODataMessageWrapperHelper.Create(response.Body, response.Headers, services), (edmType) => serializerProvider.GetEdmTypeSerializer(edmType), (objectType) => serializerProvider.GetODataPayloadSerializer(objectType, request), getODataSerializerContext); return(TaskHelpers.Completed()); } catch (Exception ex) { return(TaskHelpers.FromError(ex)); } }
/// <inheritdoc/> public override bool CanWriteType(Type type) { if (type == null) { throw Error.ArgumentNull("type"); } ODataSerializer serializer = ODataSerializerProvider.GetODataPayloadSerializer(type); return(serializer != null); }
private ODataPayloadKind?GetClrObjectResponsePayloadKind(Type type, IEdmModel model) { // SingleResult<T> should be serialized as T. if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(SingleResult <>)) { type = type.GetGenericArguments()[0]; } ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(model, type, Request); return(serializer == null ? null : (ODataPayloadKind?)serializer.ODataPayloadKind); }
/// <inheritdoc/> public override bool CanWriteType(Type type) { if (type == null) { throw Error.ArgumentNull("type"); } if (_request != null) { IEdmModel model = _request.GetEdmModel(); if (model != null) { ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(model, type); if (serializer != null) { return(_payloadKinds.Contains(serializer.ODataPayloadKind)); } } } return(false); }
private static ODataPayloadKind?GetClrObjectResponsePayloadKind(Type type, bool isGenericSingleResult, ODataSerializerProvider serializerProvider, HttpRequest request) { // SingleResult<T> should be serialized as T. if (isGenericSingleResult) { type = type.GetGenericArguments()[0]; } ODataSerializer serializer = serializerProvider.GetODataPayloadSerializer(type, request); return(serializer == null ? null : (ODataPayloadKind?)serializer.ODataPayloadKind); }
private ODataSerializer GetSerializer(Type type, object value, ODataSerializerProvider serializerProvider) { ODataSerializer serializer; IEdmObject edmObject = value as IEdmObject; if (edmObject != null) { IEdmStructuredObject edmStructuredObject = edmObject as IEdmStructuredObject; if (edmStructuredObject != null) { edmStructuredObject.SetModel(Request.GetModel()); } IEdmTypeReference edmType = edmObject.GetEdmType(); if (edmType == null) { throw new SerializationException(Error.Format(SRResources.EdmTypeCannotBeNull, edmObject.GetType().FullName, typeof(IEdmObject).Name)); } serializer = serializerProvider.GetEdmTypeSerializer(edmType); if (serializer == null) { string message = Error.Format(SRResources.TypeCannotBeSerialized, edmType.ToTraceString(), typeof(ODataMediaTypeFormatter).Name); throw new SerializationException(message); } } else { var applyClause = Request.ODataProperties().ApplyClause; // get the most appropriate serializer given that we support inheritance. if (applyClause == null) { type = value == null ? type : value.GetType(); } serializer = serializerProvider.GetODataPayloadSerializer(type, Request); if (serializer == null) { string message = Error.Format(SRResources.TypeCannotBeSerialized, type.Name, typeof(ODataMediaTypeFormatter).Name); throw new SerializationException(message); } } return(serializer); }
/// <summary> /// Gets the serializer for the given result type. /// The proxy provider will get the real provider to return the serializer. /// </summary> /// <param name="model">The EDM model.</param> /// <param name="type">The type of result to serialize.</param> /// <param name="request">The HTTP request.</param> /// <returns>The serializer instance.</returns> public override ODataSerializer GetODataPayloadSerializer( IEdmModel model, Type type, HttpRequestMessage request) { this.api = request.GetApiInstance(); if (this.api != null) { ODataSerializerProvider provider = api.Context.GetApiService <ODataSerializerProvider>(); if (provider != null) { return(provider.GetODataPayloadSerializer(model, type, request)); } } // In case user uses his own controller or NonFound error for request return(DefaultRestierSerializerProvider.SingletonInstance.GetODataPayloadSerializer(model, type, request)); }
private ODataSerializer GetSerializer(Type type, object value, IEdmModel model, ODataSerializerProvider serializerProvider) { ODataSerializer serializer; IEdmObject edmObject = value as IEdmObject; if (edmObject != null) { IEdmTypeReference edmType = edmObject.GetEdmType(); if (edmType == null) { throw new SerializationException(Error.Format(SRResources.EdmTypeCannotBeNull, edmObject.GetType().FullName, typeof(IEdmObject).Name)); } serializer = serializerProvider.GetEdmTypeSerializer(edmType); if (serializer == null) { string message = Error.Format(SRResources.TypeCannotBeSerialized, edmType.ToTraceString(), typeof(ODataJsonSerializer).Name); throw new SerializationException(message); } } else { // TODO: Support $apply // Currently don't support $apply //var applyClause = Request.ODataProperties().ApplyClause; //// get the most appropriate serializer given that we support inheritance. //if (applyClause == null) //{ // type = value == null ? type : value.GetType(); //} serializer = serializerProvider.GetODataPayloadSerializer(model, type, Request); if (serializer == null) { string message = Error.Format(SRResources.TypeCannotBeSerialized, type.Name, typeof(ODataJsonSerializer).Name); throw new SerializationException(message); } } return(serializer); }
private IEnumerable <KeyValuePair <string, string> > GetResponseMessageHeaders(Type graphType, ODataFormat odataFormat, ODataVersion version) { IODataResponseMessage responseMessage = new ODataMessageWrapper(); ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings() { BaseUri = new Uri(ODataFormatterConstants.DefaultNamespace), Version = version, Indent = false }; writerSettings.SetContentType(odataFormat); using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings)) { ODataSerializer serializer = ODataSerializerProvider.GetODataPayloadSerializer(graphType); // get the OData specific headers for the payloadkind ODataUtils.SetHeadersForPayload(messageWriter, serializer.ODataPayloadKind); } return(responseMessage.Headers); }
private ODataSerializer GetSerializer(Type type, object value, IEdmModel model, ODataSerializerProvider serializerProvider, HttpRequest request) { ODataSerializer serializer; IEdmObject edmObject = value as IEdmObject; if (edmObject != null) { IEdmTypeReference edmType = edmObject.GetEdmType(); if (edmType == null) { throw new SerializationException(Error.Format(SRResources.EdmTypeCannotBeNull, edmObject.GetType().FullName, typeof(IEdmObject).Name)); } serializer = serializerProvider.GetEdmTypeSerializer(edmType); if (serializer == null) { string message = Error.Format(SRResources.TypeCannotBeSerialized, edmType.ToTraceString(), typeof(ODataOutputFormatter).Name); throw new SerializationException(message); } } else { // get the most appropriate serializer given that we support inheritance. type = value == null ? type : value.GetType(); serializer = serializerProvider.GetODataPayloadSerializer(model, type, request); if (serializer == null) { string message = Error.Format(SRResources.TypeCannotBeSerialized, type.Name, typeof(ODataOutputFormatter).Name); throw new SerializationException(message); } } return(serializer); }
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken) { if (type == null) { throw Error.ArgumentNull("type"); } if (writeStream == null) { throw Error.ArgumentNull("writeStream"); } if (Request == null) { throw Error.InvalidOperation(SRResources.WriteToStreamAsyncMustHaveRequest); } if (cancellationToken.IsCancellationRequested) { return(TaskHelpers.Canceled()); } try { HttpConfiguration configuration = Request.GetConfiguration(); if (configuration == null) { throw Error.InvalidOperation(SRResources.RequestMustContainConfiguration); } HttpContentHeaders contentHeaders = (content == null) ? null : content.Headers; UrlHelper urlHelper = Request.GetUrlHelper() ?? new UrlHelper(Request); Func <ODataSerializerContext> getODataSerializerContext = () => { return(new ODataSerializerContext() { Request = Request, Url = urlHelper, }); }; ODataSerializerProvider serializerProvider = Request.GetRequestContainer() .GetRequiredService <ODataSerializerProvider>(); ODataOutputFormatterHelper.WriteToStream( type, value, Request.GetModel(), ResultHelpers.GetODataResponseVersion(Request), GetBaseAddressInternal(Request), contentHeaders == null ? null : contentHeaders.ContentType, new WebApiUrlHelper(urlHelper), new WebApiRequestMessage(Request), new WebApiRequestHeaders(Request.Headers), (services) => ODataMessageWrapperHelper.Create(writeStream, contentHeaders, services), (edmType) => serializerProvider.GetEdmTypeSerializer(edmType), (objectType) => serializerProvider.GetODataPayloadSerializer(objectType, Request), getODataSerializerContext); return(TaskHelpers.Completed()); } catch (Exception ex) { return(TaskHelpers.FromError(ex)); } }
public void GetODataPayloadSerializer_ThrowsArgumentNull_Type() { // Arrange var request = RequestFactory.Create(); // Act & Assert ExceptionAssert.ThrowsArgumentNull( () => _serializerProvider.GetODataPayloadSerializer(type: null, request: request), "type"); }
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext) { if (type == null) { throw Error.ArgumentNull("type"); } if (writeStream == null) { throw Error.ArgumentNull("writeStream"); } HttpContentHeaders contentHeaders = content == null ? null : content.Headers; return(TaskHelpers.RunSynchronously(() => { // Get the format and version to use from the ODataServiceVersion content header or if not available use the // values configured for the specialized formatter instance. ODataVersion version; ODataFormat odataFormat; if (contentHeaders == null) { version = _defaultODataVersion; odataFormat = ODataFormatterConstants.DefaultODataFormat; } else { version = GetODataVersion(contentHeaders, ODataFormatterConstants.ODataServiceVersion) ?? _defaultODataVersion; odataFormat = GetODataFormat(contentHeaders); } ODataSerializer serializer = ODataSerializerProvider.GetODataPayloadSerializer(type); if (serializer == null) { throw Error.InvalidOperation(SRResources.TypeCannotBeSerialized, type.Name, typeof(ODataMediaTypeFormatter).Name); } if (IsClient) { // TODO: Bug 467617: figure out the story for the operation name on the client side and server side. string operationName = (value != null ? value.GetType() : type).Name; // serialize a request IODataRequestMessage requestMessage = new ODataMessageWrapper(writeStream); ODataResponseContext responseContext = new ODataResponseContext(requestMessage, odataFormat, version, new Uri(ODataFormatterConstants.DefaultNamespace), operationName); ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings() { BaseUri = responseContext.BaseAddress, Version = responseContext.ODataVersion, Indent = responseContext.IsIndented, DisableMessageStreamDisposal = true, }; writerSettings.SetContentType(responseContext.ODataFormat); using (ODataMessageWriter messageWriter = new ODataMessageWriter(requestMessage, writerSettings, Model)) { ODataSerializerWriteContext writeContext = new ODataSerializerWriteContext(responseContext); serializer.WriteObject(value, messageWriter, writeContext); } } else { UrlHelper urlHelper = Request.GetUrlHelper(); NameValueCollection queryStringValues = Request.RequestUri.ParseQueryString(); IEdmEntitySet targetEntitySet = null; ODataUriHelpers.TryGetEntitySetAndEntityType(Request.RequestUri, Model, out targetEntitySet); ODataQueryProjectionNode rootProjectionNode = null; if (targetEntitySet != null) { // TODO: Bug 467621: Move to ODataUriParser once it is done. rootProjectionNode = ODataUriHelpers.GetODataQueryProjectionNode(queryStringValues["$select"], queryStringValues["$expand"], targetEntitySet); } // serialize a response Uri baseAddress = new Uri(Request.RequestUri, Request.GetConfiguration().VirtualPathRoot); // TODO: Bug 467617: figure out the story for the operation name on the client side and server side. // This is clearly a workaround. We are assuming that the operation name is the last segment in the request uri // which works for most cases and fall back to the type name of the object being written. // We should rather use uri parser semantic tree to figure out the operation name from the request url. string operationName = ODataUriHelpers.GetOperationName(Request.RequestUri, baseAddress); operationName = operationName ?? type.Name; IODataResponseMessage responseMessage = new ODataMessageWrapper(writeStream); ODataResponseContext responseContext = new ODataResponseContext(responseMessage, odataFormat, version, baseAddress, operationName); ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings() { BaseUri = responseContext.BaseAddress, Version = responseContext.ODataVersion, Indent = responseContext.IsIndented, DisableMessageStreamDisposal = true, }; if (contentHeaders != null && contentHeaders.ContentType != null) { writerSettings.SetContentType(contentHeaders.ContentType.ToString(), Encoding.UTF8.WebName); } using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, ODataDeserializerProvider.EdmModel)) { ODataSerializerWriteContext writeContext = new ODataSerializerWriteContext(responseContext) { EntitySet = targetEntitySet, UrlHelper = urlHelper, RootProjectionNode = rootProjectionNode, CurrentProjectionNode = rootProjectionNode }; serializer.WriteObject(value, messageWriter, writeContext); } } })); }
/// <inheritdoc/> public override bool CanWriteResult(OutputFormatterCanWriteContext context) { if (context == null) { throw Error.ArgumentNull("context"); } // Ensure we have a valid request. HttpRequest request = context.HttpContext.Request; if (request == null) { throw Error.InvalidOperation(SRResources.ReadFromStreamAsyncMustHaveRequest); } // Ignore non-OData requests. if (request.ODataFeature().Path == null) { return(false); } // The following base.CanWriteResult(context) will change the context.ContentType // If this formatter can't write the result, we should reset the context.ContentType to its original value. // So that, the other formatter can make a descison based on the original content type. // Be noted: in .NET 5, the context.ContentType is a new StringSegment everytime when goes into each formatter // formatterContext.ContentType = new StringSegment(); // So, in .NET 5, we don't need to reset the contentType to backupContentType. StringSegment backupContentType = context.ContentType; // Allow the base class to make its determination, which includes // checks for SupportedMediaTypes. bool suportedMediaTypeFound = false; if (SupportedMediaTypes.Any()) { suportedMediaTypeFound = base.CanWriteResult(context); } // See if the request satisfies any mappings. IEnumerable <MediaTypeMapping> matchedMappings = (MediaTypeMappings == null) ? null : MediaTypeMappings .Where(m => (m.TryMatchMediaType(request) > 0)); // Now pick the best content type. If a media mapping was found, use that and override the // value specified by the controller, if any. Otherwise, let the base class decide. if (matchedMappings != null && matchedMappings.Any()) { context.ContentType = matchedMappings.First().MediaType.ToString(); } else if (!suportedMediaTypeFound) { context.ContentType = backupContentType; return(false); } // We need the type in order to write it. Type type = context.ObjectType ?? context.Object?.GetType(); if (type == null) { context.ContentType = backupContentType; return(false); } type = TypeHelper.GetTaskInnerTypeOrSelf(type); ODataSerializerProvider serializerProvider = request.GetRequestContainer().GetRequiredService <ODataSerializerProvider>(); // See if this type is a SingleResult or is derived from SingleResult. bool isSingleResult = false; if (type.IsGenericType) { Type genericType = type.GetGenericTypeDefinition(); Type baseType = TypeHelper.GetBaseType(type); isSingleResult = (genericType == typeof(SingleResult <>) || baseType == typeof(SingleResult)); } bool result = ODataOutputFormatterHelper.CanWriteType( type, _payloadKinds, isSingleResult, new WebApiRequestMessage(request), (objectType) => serializerProvider.GetODataPayloadSerializer(objectType, request)); if (!result) { context.ContentType = backupContentType; } return(result); }
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext) { if (type == null) { throw Error.ArgumentNull("type"); } if (writeStream == null) { throw Error.ArgumentNull("writeStream"); } if (Request == null) { throw Error.NotSupported(SRResources.WriteToStreamAsyncMustHaveRequest); } HttpContentHeaders contentHeaders = content == null ? null : content.Headers; return(TaskHelpers.RunSynchronously(() => { // Get the format and version to use from the ODataServiceVersion content header or if not available use the // values configured for the specialized formatter instance. ODataVersion version; if (contentHeaders == null) { version = _defaultODataVersion; } else { version = GetODataVersion(contentHeaders, ODataFormatterConstants.ODataServiceVersion) ?? _defaultODataVersion; } // get the most appropriate serializer given that we support inheritance. type = value == null ? type : value.GetType(); ODataSerializer serializer = ODataSerializerProvider.GetODataPayloadSerializer(type); if (serializer == null) { throw Error.InvalidOperation(SRResources.TypeCannotBeSerialized, type.Name, typeof(ODataMediaTypeFormatter).Name); } UrlHelper urlHelper = Request.GetUrlHelper(); IEdmEntitySet targetEntitySet = null; ODataUriHelpers.TryGetEntitySetAndEntityType(Request.RequestUri, Model, out targetEntitySet); // serialize a response Uri baseAddress = new Uri(Request.RequestUri, Request.GetConfiguration().VirtualPathRoot); // TODO: Bug 467617: figure out the story for the operation name on the client side and server side. // This is clearly a workaround. We are assuming that the operation name is the last segment in the request uri // which works for most cases and fall back to the type name of the object being written. // We should rather use uri parser semantic tree to figure out the operation name from the request url. string operationName = ODataUriHelpers.GetOperationName(Request.RequestUri, baseAddress); operationName = operationName ?? type.Name; IODataResponseMessage responseMessage = new ODataMessageWrapper(writeStream); // TODO: Issue 483: http://aspnetwebstack.codeplex.com/workitem/483 // We need to set the MetadataDocumentUri when this property is added to ODataMessageWriterSettings as // part of the JSON Light work. // This is required so ODataLib can coerce AbsoluteUri's into RelativeUri's when appropriate in JSON Light. ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings() { BaseUri = baseAddress, Version = version, Indent = true, DisableMessageStreamDisposal = true }; if (contentHeaders != null && contentHeaders.ContentType != null) { writerSettings.SetContentType(contentHeaders.ContentType.ToString(), Encoding.UTF8.WebName); } using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, ODataDeserializerProvider.EdmModel)) { ODataSerializerContext writeContext = new ODataSerializerContext() { EntitySet = targetEntitySet, UrlHelper = urlHelper, ServiceOperationName = operationName, SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.Feed, Request = Request }; serializer.WriteObject(value, messageWriter, writeContext); } })); }