Esempio n. 1
0
        public async Task Posting_NonDerivedType_To_Action_Expecting_BaseType_Throws()
        {
            // Arrange
            StringContent        content      = new StringContent("{ '@odata.type' : '#Microsoft.AspNet.OData.Test.Builder.TestModels.Motorcycle' }");
            var                  headers      = FormatterTestHelper.GetContentHeaders("application/json");
            IODataRequestMessage oDataRequest = ODataMessageWrapperHelper.Create(await content.ReadAsStreamAsync(), headers);
            ODataMessageReader   reader       = new ODataMessageReader(oDataRequest, new ODataMessageReaderSettings(), _model);

            ODataDeserializerProvider deserializerProvider = ODataDeserializerProviderFactory.Create();

            ODataDeserializerContext context = new ODataDeserializerContext {
                Model = _model
            };
            IEdmActionImport action = _model.EntityContainer
                                      .OperationImports()
                                      .Single(f => f.Name == "PostMotorcycle_When_Expecting_Car") as IEdmActionImport;

            Assert.NotNull(action);
            IEdmEntitySetBase actionEntitySet;

            action.TryGetStaticEntitySet(_model, out actionEntitySet);
            context.Path = new ODataPath(new OperationImportSegment(new[] { action }, actionEntitySet, null));

            // Act & Assert
            ExceptionAssert.Throws <ODataException>(
                () => new ODataResourceDeserializer(deserializerProvider).Read(reader, typeof(Car), context),
                "A resource with type 'Microsoft.AspNet.OData.Test.Builder.TestModels.Motorcycle' was found, " +
                "but it is not assignable to the expected type 'Microsoft.AspNet.OData.Test.Builder.TestModels.Car'. " +
                "The type specified in the resource must be equal to either the expected type or a derived type.");
        }
Esempio n. 2
0
        public void Posting_NonDerivedType_To_Action_Expecting_BaseType_Throws()
        {
            // Arrange
            StringContent content = new StringContent("{ '@odata.type' : '#System.Web.OData.Builder.TestModels.Motorcycle' }");

            content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
            IODataRequestMessage oDataRequest = new ODataMessageWrapper(content.ReadAsStreamAsync().Result, content.Headers);
            ODataMessageReader   reader       = new ODataMessageReader(oDataRequest, new ODataMessageReaderSettings(), _model);

            ODataDeserializerProvider deserializerProvider = DependencyInjectionHelper.GetDefaultODataDeserializerProvider();

            ODataDeserializerContext context = new ODataDeserializerContext {
                Model = _model
            };
            IEdmActionImport action = _model.EntityContainer
                                      .OperationImports()
                                      .Single(f => f.Name == "PostMotorcycle_When_Expecting_Car") as IEdmActionImport;

            Assert.NotNull(action);
            IEdmEntitySetBase actionEntitySet;

            action.TryGetStaticEntitySet(_model, out actionEntitySet);
            context.Path = new ODataPath(new OperationImportSegment(new[] { action }, actionEntitySet, null));

            // Act & Assert
            Assert.Throws <ODataException>(
                () => new ODataResourceDeserializer(deserializerProvider).Read(reader, typeof(Car), context),
                "An resource with type 'System.Web.OData.Builder.TestModels.Motorcycle' was found, " +
                "but it is not assignable to the expected type 'System.Web.OData.Builder.TestModels.Car'. " +
                "The type specified in the resource must be equal to either the expected type or a derived type.");
        }
Esempio n. 3
0
        /// <inheritdoc />
        public virtual bool AppliesToAction(ODataControllerActionContext context)
        {
            if (context == null)
            {
                throw Error.ArgumentNull(nameof(context));
            }

            ActionModel action = context.Action;
            IEdmModel   model  = context.Model;

            // By convention, we use the operation import name as the action name in the controller
            string actionMethodName = action.ActionName;

            var edmOperationImports = model.ResolveOperationImports(actionMethodName, enableCaseInsensitive: true);

            if (!edmOperationImports.Any())
            {
                return(true);
            }

            (var actionImports, var functionImports) = edmOperationImports.SplitOperationImports();

            // It's not allowed to have an action import and function import with the same name.
            if (actionImports.Count > 0 && functionImports.Count > 0)
            {
                throw new ODataException(Error.Format(SRResources.OperationMustBeUniqueInEntitySetContainer, actionMethodName));
            }
            else if (actionImports.Count > 0 && context.Action.Attributes.Any(a => a is HttpPostAttribute))
            {
                if (actionImports.Count != 1)
                {
                    throw new ODataException(Error.Format(SRResources.MultipleActionImportFound, actionMethodName));
                }

                IEdmActionImport actionImport = actionImports[0];

                IEdmEntitySetBase targetEntitySet;
                actionImport.TryGetStaticEntitySet(model, out targetEntitySet);

                // TODO:
                // 1. shall we check the [HttpPost] attribute, or does the ASP.NET Core have the default?
                // 2) shall we check the action has "ODataActionParameters" parameter type?
                ODataPathTemplate template = new ODataPathTemplate(new ActionImportSegmentTemplate(actionImport, targetEntitySet));
                action.AddSelector("Post", context.Prefix, context.Model, template, context.Options?.RouteOptions);
                return(true);
            }
            else if (functionImports.Count > 0 && context.Action.Attributes.Any(a => a is HttpGetAttribute))
            {
                IEdmFunctionImport functionImport = FindFunctionImport(functionImports, action);
                if (functionImport == null)
                {
                    return(false);
                }

                IEdmEntitySetBase targetSet;
                functionImport.TryGetStaticEntitySet(model, out targetSet);

                // TODO:
                // 1) shall we check the [HttpGet] attribute, or does the ASP.NET Core have the default?
                ODataPathTemplate template = new ODataPathTemplate(new FunctionImportSegmentTemplate(functionImport, targetSet));
                action.AddSelector("Get", context.Prefix, context.Model, template, context.Options?.RouteOptions);
                return(true);
            }
            else
            {
                // doesn't find an operation, return true means to skip the remaining conventions.
                return(false);
            }
        }