/// <summary> /// Gets the EDM model for the given type and request. /// </summary> /// <param name="elementClrType">The CLR type to retrieve a model for.</param> /// <param name="request">The request message to retrieve a model for.</param> /// <param name="actionDescriptor">The action descriptor for the action being queried on.</param> /// <returns>The EDM model for the given type and request.</returns> /// <remarks> /// Override this method to customize the EDM model used for querying. /// </remarks> public virtual IEdmModel GetModel(Type elementClrType, HttpRequestMessage request, HttpActionDescriptor actionDescriptor) { // Get model for the request IEdmModel model = request.GetEdmModel(); if (model == null || model.GetEdmType(elementClrType) == null) { // user has not configured anything or has registered a model without the element type // let's create one just for this type and cache it in the action descriptor model = actionDescriptor.GetEdmModel(elementClrType); } Contract.Assert(model != null); return(model); }
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) { if (actionContext == null) { throw Error.ArgumentNull("actionContext"); } HttpRequestMessage request = actionContext.Request; if (request == null) { throw Error.Argument("actionContext", SRResources.ActionContextMustHaveRequest); } HttpActionDescriptor actionDescriptor = actionContext.ActionDescriptor; if (actionDescriptor == null) { throw Error.Argument("actionContext", SRResources.ActionContextMustHaveDescriptor); } HttpConfiguration configuration = request.GetConfiguration(); if (configuration == null) { throw Error.Argument("actionContext", SRResources.RequestMustContainConfiguration); } // Get the entity type from the parameter type if it is ODataQueryOptions<T>. // Fall back to the return type if not. Also, note that the entity type from the return type and ODataQueryOptions<T> // can be different (example implementing $select or $expand). Type entityClrType = GetEntityClrTypeFromParameterType(Descriptor) ?? GetEntityClrTypeFromActionReturnType(actionDescriptor); IEdmModel model = configuration.GetEdmModel() ?? actionDescriptor.GetEdmModel(entityClrType); ODataQueryContext entitySetContext = new ODataQueryContext(model, entityClrType); Func <ODataQueryContext, HttpRequestMessage, ODataQueryOptions> createODataQueryOptions = (Func <ODataQueryContext, HttpRequestMessage, ODataQueryOptions>)Descriptor.Properties.GetOrAdd(CreateODataQueryOptionsCtorKey, _ => { return(Delegate.CreateDelegate(typeof(Func <ODataQueryContext, HttpRequestMessage, ODataQueryOptions>), _createODataQueryOptions.MakeGenericMethod(entityClrType))); }); ODataQueryOptions parameterValue = createODataQueryOptions(entitySetContext, request); SetValue(actionContext, parameterValue); return(TaskHelpers.FromResult(0)); }
private static ODataQueryContext CreateQueryContext(Type entityClrType, HttpConfiguration configuration, HttpActionDescriptor actionDescriptor) { // Primitive types do not construct an EDM model and deal only with the CLR Type if (TypeHelper.IsQueryPrimitiveType(entityClrType)) { return(new ODataQueryContext(entityClrType)); } else { // Get model for the entire app IEdmModel model = configuration.GetEdmModel(); if (model == null) { // user has not configured anything, now let's create one just for this type // and cache it in the action descriptor model = actionDescriptor.GetEdmModel(entityClrType); Contract.Assert(model != null); } // parses the query from request uri return(new ODataQueryContext(model, entityClrType)); } }
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) { if (actionContext == null) { throw Error.ArgumentNull("actionContext"); } HttpRequestMessage request = actionContext.Request; if (request == null) { throw Error.Argument("actionContext", SRResources.ActionContextMustHaveRequest); } HttpActionDescriptor actionDescriptor = actionContext.ActionDescriptor; if (actionDescriptor == null) { throw Error.Argument("actionContext", SRResources.ActionContextMustHaveDescriptor); } HttpConfiguration configuration = request.GetConfiguration(); if (configuration == null) { throw Error.Argument("actionContext", SRResources.RequestMustContainConfiguration); } IEdmModel model = configuration.GetEdmModel(); if (actionDescriptor.ReturnType == null) { throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.InternalServerError, Error.Format(SRResources.FailedToBuildEdmModelBecauseReturnTypeIsNull, actionDescriptor.ActionName, actionDescriptor.ControllerDescriptor.ControllerName))); } Type entityClrType = TypeHelper.GetImplementedIEnumerableType(actionDescriptor.ReturnType); if (entityClrType == null) { throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.InternalServerError, Error.Format(SRResources.FailedToRetrieveTypeToBuildEdmModel, actionDescriptor.ReturnType.FullName, actionDescriptor.ActionName, actionDescriptor.ControllerDescriptor.ControllerName))); } if (model == null) { model = actionDescriptor.GetEdmModel(entityClrType); } ODataQueryOptions parameterValue = null; ODataQueryContext entitySetContext = new ODataQueryContext(model, entityClrType); try { parameterValue = new ODataQueryOptions(entitySetContext, request); SetValue(actionContext, parameterValue); } catch (ODataException exception) { throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.BadRequest, exception)); } return(TaskHelpers.FromResult(0)); }
/// <summary> /// Gets the EDM model for the given type and request. Override this method to customize the EDM model used for /// querying. /// </summary> /// <param name="elementClrType">The CLR type to retrieve a model for.</param> /// <param name="request">The request message to retrieve a model for.</param> /// <param name="actionDescriptor">The action descriptor for the action being queried on.</param> /// <returns>The EDM model for the given type and request.</returns> public virtual IEdmModel GetModel(Type elementClrType, HttpRequestMessage request, HttpActionDescriptor actionDescriptor) { // Get model for the request IEdmModel model = request.ODataProperties().Model; if (model == null || model.GetEdmType(elementClrType) == null) { // user has not configured anything or has registered a model without the element type // let's create one just for this type and cache it in the action descriptor model = actionDescriptor.GetEdmModel(elementClrType); } Contract.Assert(model != null); return model; }
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { if (actionExecutedContext == null) { throw Error.ArgumentNull("actionExecutedContext"); } HttpRequestMessage request = actionExecutedContext.Request; if (request == null) { throw Error.Argument("actionExecutedContext", SRResources.ActionExecutedContextMustHaveRequest); } HttpConfiguration configuration = request.GetConfiguration(); if (configuration == null) { throw Error.Argument("actionExecutedContext", SRResources.RequestMustContainConfiguration); } if (actionExecutedContext.ActionContext == null) { throw Error.Argument("actionExecutedContext", SRResources.ActionExecutedContextMustHaveActionContext); } HttpActionDescriptor actionDescriptor = actionExecutedContext.ActionContext.ActionDescriptor; if (actionDescriptor == null) { throw Error.Argument("actionExecutedContext", SRResources.ActionContextMustHaveDescriptor); } HttpResponseMessage response = actionExecutedContext.Response; IEnumerable query; IQueryable queryable = null; if (response != null && response.IsSuccessStatusCode && response.TryGetContentValue(out query)) { if (request.RequestUri != null && !String.IsNullOrWhiteSpace(request.RequestUri.Query)) { ValidateQuery(request); try { ODataQueryContext queryContext; Type originalQueryType = query.GetType(); Type entityClrType = TypeHelper.GetImplementedIEnumerableType(originalQueryType); // Primitive types do not construct an EDM model and deal only with the CLR Type if (TypeHelper.IsQueryPrimitiveType(entityClrType)) { queryContext = new ODataQueryContext(entityClrType); } else { // Get model for the entire app IEdmModel model = configuration.GetEdmModel(); if (entityClrType == null) { // The actual type is not IEnumerable or IQueryable actionExecutedContext.Response = request.CreateErrorResponse( HttpStatusCode.InternalServerError, Error.Format(SRResources.FailedToRetrieveTypeToBuildEdmModel, originalQueryType.FullName, actionDescriptor.ActionName, actionDescriptor.ControllerDescriptor.ControllerName)); return; } if (model == null) { // user has not configured anything, now let's create one just for this type // and cache it in the action descriptor model = actionDescriptor.GetEdmModel(entityClrType); } if (model == null) { // we need to send 500 if we can't create a model actionExecutedContext.Response = request.CreateErrorResponse( HttpStatusCode.InternalServerError, Error.Format(SRResources.FailedToBuildEdmModel, entityClrType.FullName, actionDescriptor.ActionName, actionDescriptor.ControllerDescriptor.ControllerName)); return; } // parses the query from request uri queryContext = new ODataQueryContext(model, entityClrType); } ODataQueryOptions queryOptions = new ODataQueryOptions(queryContext, request); // Filter and OrderBy require entity sets. Top and Skip may accept primitives. if (queryContext.IsPrimitiveClrType && (queryOptions.Filter != null || queryOptions.OrderBy != null)) { // An attempt to use a query option not allowed for primitive types // generates a BadRequest with a general message that avoids information disclosure. actionExecutedContext.Response = request.CreateErrorResponse( HttpStatusCode.BadRequest, SRResources.OnlySkipAndTopSupported); return; } // apply the query queryable = query as IQueryable; if (queryable == null) { queryable = query.AsQueryable(); } if (_handleNullPropagation != null) { queryable = queryOptions.ApplyTo(queryable, _handleNullPropagation.Value); } else { queryable = queryOptions.ApplyTo(queryable); } Contract.Assert(queryable != null); // we don't support shape changing query composition ((ObjectContent)response.Content).Value = queryable; } catch (ODataException e) { actionExecutedContext.Response = request.CreateErrorResponse( HttpStatusCode.BadRequest, SRResources.UriQueryStringInvalid, e); return; } } } }
private static ODataQueryContext CreateQueryContext(Type entityClrType, HttpConfiguration configuration, HttpActionDescriptor actionDescriptor) { // Primitive types do not construct an EDM model and deal only with the CLR Type if (TypeHelper.IsQueryPrimitiveType(entityClrType)) { return new ODataQueryContext(entityClrType); } else { // Get model for the entire app IEdmModel model = configuration.GetEdmModel(); if (model == null) { // user has not configured anything, now let's create one just for this type // and cache it in the action descriptor model = actionDescriptor.GetEdmModel(entityClrType); Contract.Assert(model != null); } // parses the query from request uri return new ODataQueryContext(model, entityClrType); } }
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) { if (actionContext == null) { throw Error.ArgumentNull("actionContext"); } HttpRequestMessage request = actionContext.Request; if (request == null) { throw Error.Argument("actionContext", SRResources.ActionContextMustHaveRequest); } HttpActionDescriptor actionDescriptor = actionContext.ActionDescriptor; if (actionDescriptor == null) { throw Error.Argument("actionContext", SRResources.ActionContextMustHaveDescriptor); } HttpConfiguration configuration = request.GetConfiguration(); if (configuration == null) { throw Error.Argument("actionContext", SRResources.RequestMustContainConfiguration); } IEdmModel model = configuration.GetEdmModel(); // It is a developer programming error to use this binding attribute // on actions that return void. if (actionDescriptor.ReturnType == null) { throw Error.InvalidOperation( SRResources.FailedToBuildEdmModelBecauseReturnTypeIsNull, this.GetType().Name, actionDescriptor.ActionName, actionDescriptor.ControllerDescriptor.ControllerName); } Type entityClrType = TypeHelper.GetImplementedIEnumerableType(actionDescriptor.ReturnType); if (entityClrType == null) { // It is a developer programming error to use this binding attribute // on actions that return a collection whose element type cannot be // determined, such as a non-generic IQueryable or IEnumerable. throw Error.InvalidOperation( SRResources.FailedToRetrieveTypeToBuildEdmModel, this.GetType().Name, actionDescriptor.ActionName, actionDescriptor.ControllerDescriptor.ControllerName, actionDescriptor.ReturnType.FullName); } if (model == null) { model = actionDescriptor.GetEdmModel(entityClrType); } ODataQueryOptions parameterValue = null; ODataQueryContext entitySetContext = new ODataQueryContext(model, entityClrType); try { parameterValue = new ODataQueryOptions(entitySetContext, request); SetValue(actionContext, parameterValue); } catch (ODataException exception) { throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.BadRequest, exception)); } return(TaskHelpers.FromResult(0)); }