/// <summary>
        /// Initializes a new instance of the <see cref="QueryDescription"/> class with the specified
        /// <see cref="DomainOperationEntry"/> and parameter values.
        /// </summary>
        /// <param name="domainOperationEntry">The query operation to be processed</param>
        /// <param name="parameterValues">Parameter values for the method if it requires any</param>
        public QueryDescription(DomainOperationEntry domainOperationEntry, object[] parameterValues) : this(domainOperationEntry)
        {
            if (parameterValues == null)
            {
                throw new ArgumentNullException("parameterValues");
            }

            this._parameterValues = parameterValues;
        }
        /// <summary>
        /// Initializes a new instance of the InvokeDescription class
        /// </summary>
        /// <param name="domainOperationEntry">The invoke operation to be processed</param>
        /// <param name="parameterValues">The parameter values for the method if it requires any.</param>
        public InvokeDescription(DomainOperationEntry domainOperationEntry, object[] parameterValues)
        {
            if (domainOperationEntry == null)
            {
                throw new ArgumentNullException("domainOperationEntry");
            }

            this._domainOperationEntry = domainOperationEntry;
            this._parameterValues = parameterValues;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="QueryDescription"/> class with the specified
        /// <see cref="DomainOperationEntry"/>.
        /// </summary>
        /// <param name="domainOperationEntry">The query operation to be processed</param>
        public QueryDescription(DomainOperationEntry domainOperationEntry)
        {
            if (domainOperationEntry == null)
            {
                throw new ArgumentNullException("domainOperationEntry");
            }
            if (domainOperationEntry.Operation != DomainOperation.Query)
            {
                throw new ArgumentOutOfRangeException("domainOperationEntry");
            }

            this._domainOperationEntry = domainOperationEntry;
        }
Пример #4
0
        public async Task InvokeOperation_ServerValidationException()
        {
            TestProvider_Scenarios   provider                       = ServerTestHelper.CreateInitializedDomainService <TestProvider_Scenarios>(DomainOperationType.Invoke);
            DomainServiceDescription serviceDescription             = DomainServiceDescription.GetDescription(typeof(TestProvider_Scenarios));
            DomainOperationEntry     throwValidationExceptionMethod = serviceDescription.GetInvokeOperation("ThrowValidationException");

            Assert.IsNotNull(throwValidationExceptionMethod);

            var invokeResult = await provider.InvokeAsync(new InvokeDescription(throwValidationExceptionMethod, Array.Empty <object>()), CancellationToken.None);

            Assert.IsNull(invokeResult.Result);
            Assert.IsNotNull(invokeResult.ValidationErrors);
            Assert.AreEqual(1, invokeResult.ValidationErrors.Count);
            Assert.AreEqual("Validation error.", invokeResult.ValidationErrors.ElementAt(0).ErrorMessage);
        }
Пример #5
0
        /// <summary>
        /// Get the <see cref="WebInvokeAttribute.UriTemplate"/> which corresponds to the default generated
        /// UriTemplate for "GET" methods for a given query operation.
        /// </summary>
        /// <param name="operation">the query operation for which to get the UriTemplate</param>
        /// <returns>the default UriTemplate for "GET" methods in case no UriTemplate is specified</returns>
        private static string GetDefaultQueryUriTemplate(DomainOperationEntry operation)
        {
            StringBuilder stringBuilder = new StringBuilder(operation.Name);

            if (operation.Parameters.Count > 0)
            {
                stringBuilder.Append("?");
                foreach (DomainOperationParameter parameter in operation.Parameters)
                {
                    stringBuilder.AppendFormat("{0}={{{0}}}&", parameter.Name);
                }
                stringBuilder.Remove(stringBuilder.Length - 1, 1);
            }
            return(stringBuilder.ToString());
        }
        /// <summary>
        /// Determines whether the specified <see cref="DomainOperationEntry"/> can legally
        /// be generated.  Logs warnings or errors as appropriate.
        /// </summary>
        /// <param name="domainOperationEntry">The operation to generate.</param>
        /// <returns><c>false</c> means an error or warning has been logged and it should not be generated.</returns>
        private bool CanGenerateDomainOperationEntry(DomainOperationEntry domainOperationEntry)
        {
            string methodName = (domainOperationEntry.Operation == DomainOperation.Query) ? domainOperationEntry.Name : domainOperationEntry.Name + QuerySuffix;

            // Check for name conflicts.  Log error and exit if collision.
            if (this._proxyClass.Members.Cast <CodeTypeMember>().Any(c => c.Name == methodName))
            {
                this.ClientProxyGenerator.LogError(
                    string.Format(CultureInfo.CurrentCulture,
                                  Resource.ClientCodeGen_NamingCollision_MemberAlreadyExists,
                                  this._proxyClass.Name,
                                  methodName));

                return(false);
            }

            // Check each parameter type to see if is enum
            DomainOperationParameter[] paramInfos = domainOperationEntry.Parameters.ToArray();
            for (int i = 0; i < paramInfos.Length; i++)
            {
                DomainOperationParameter paramInfo = paramInfos[i];

                // If this is an enum type, we need to ensure it is either shared or
                // can be generated.  Failure logs an error.  The test for legality also causes
                // the enum to be generated if required.
                Type enumType = TypeUtility.GetNonNullableType(paramInfo.ParameterType);
                if (enumType.IsEnum)
                {
                    string errorMessage = null;
                    if (!this.ClientProxyGenerator.CanExposeEnumType(enumType, out errorMessage))
                    {
                        this.ClientProxyGenerator.LogError(string.Format(CultureInfo.CurrentCulture,
                                                                         Resource.ClientCodeGen_Domain_Op_Enum_Error,
                                                                         domainOperationEntry.Name,
                                                                         this._proxyClass.Name,
                                                                         enumType.FullName,
                                                                         errorMessage));
                        return(false);
                    }
                    else
                    {
                        // Register use of this enum type, which could cause deferred generation
                        this.ClientProxyGenerator.RegisterUseOfEnumType(enumType);
                    }
                }
            }
            return(true);
        }
 /// <summary>
 /// Determines whether caching is supported for the current request to the specified domain operation entry.
 /// </summary>
 /// <param name="context">The context for the request.</param>
 /// <param name="domainOperationEntry">The requested domain operation entry, if any.</param>
 /// <returns>True if caching is supported.</returns>
 private static bool SupportsCaching(HttpContext context, DomainOperationEntry domainOperationEntry)
 {
     if (domainOperationEntry != null &&
         context.Request.HttpMethod.Equals("GET", StringComparison.OrdinalIgnoreCase))
     {
         foreach (string queryParameter in QueryOperationInvoker.supportedQueryParameters)
         {
             if (context.Request.QueryString[queryParameter] != null)
             {
                 return(false);
             }
         }
         return(true);
     }
     return(false);
 }
Пример #8
0
        public void InvokeOperation_ServerValidationException()
        {
            TestProvider_Scenarios   provider                       = ServerTestHelper.CreateInitializedDomainService <TestProvider_Scenarios>(DomainOperationType.Invoke);
            DomainServiceDescription serviceDescription             = DomainServiceDescription.GetDescription(typeof(TestProvider_Scenarios));
            DomainOperationEntry     throwValidationExceptionMethod = serviceDescription.GetInvokeOperation("ThrowValidationException");

            Assert.IsNotNull(throwValidationExceptionMethod);

            IEnumerable <ValidationResult> validationErrors;
            object result = provider.Invoke(new InvokeDescription(throwValidationExceptionMethod, new object[0]), out validationErrors);

            Assert.IsNull(result);
            Assert.IsNotNull(validationErrors);
            Assert.AreEqual(1, validationErrors.Count());
            Assert.AreEqual("Validation error.", validationErrors.ElementAt(0).ErrorMessage);
        }
Пример #9
0
        private void GenerateContractMethod(DomainOperationEntry operation)
        {
            this.Write("[OpenRiaServices.DomainServices.Client.HasSideEffects(");

            this.Write(this.ToStringHelper.ToStringWithCulture(DomainContextGenerator.OperationHasSideEffects(operation).ToString().ToLower()));

            this.Write(")]\r\n");


            this.GenerateContractMethodAttributes(operation.Name);

            this.Write("System.IAsyncResult Begin");

            this.Write(this.ToStringHelper.ToStringWithCulture(operation.Name));

            this.Write("(\r\n");


            foreach (DomainOperationParameter parameter in operation.Parameters)
            {
                Type parameterType = CodeGenUtilities.TranslateType(parameter.ParameterType);

                this.Write(this.ToStringHelper.ToStringWithCulture(CodeGenUtilities.GetTypeName(parameterType)));

                this.Write(" ");

                this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name));

                this.Write(",\r\n");
            }

            this.Write("System.AsyncCallback callback, object asyncState);\r\n");


            string returnTypeName = CSharpDomainContextGenerator.GetEndOperationReturnType(operation);

            this.Write("\t\t\r\n");

            this.Write(this.ToStringHelper.ToStringWithCulture(returnTypeName));

            this.Write(" End");

            this.Write(this.ToStringHelper.ToStringWithCulture(operation.Name));

            this.Write("(System.IAsyncResult result);\r\n");
        }
Пример #10
0
        public async Task DomainService_InvalidOperationType()
        {
            TestDomainServices.EF.Northwind nw  = new TestDomainServices.EF.Northwind();
            DomainServiceContext            dsc = new DomainServiceContext(new MockDataService(new MockUser("mathew")
            {
                IsAuthenticated = true
            }), DomainOperationType.Submit);

            nw.Initialize(dsc);

            DomainServiceDescription dsd   = DomainServiceDescription.GetDescription(typeof(TestDomainServices.EF.Northwind));
            DomainOperationEntry     entry = dsd.GetQueryMethod(nameof(TestDomainServices.EF.Northwind.GetOrderDetails));
            QueryDescription         qd    = new QueryDescription(entry);
            await ExceptionHelper.ExpectExceptionAsync <InvalidOperationException>(() =>
            {
                return(nw.QueryAsync <NorthwindModel.Order_Detail>(qd, CancellationToken.None).AsTask());
            }, string.Format(Resource.DomainService_InvalidOperationType, DomainOperationType.Submit, DomainOperationType.Query));

            InvokeDescription id = new InvokeDescription(entry, null);
            await ExceptionHelper.ExpectExceptionAsync <InvalidOperationException>(() =>
            {
                return(nw.InvokeAsync(id, CancellationToken.None).AsTask());
            }, string.Format(Resource.DomainService_InvalidOperationType, DomainOperationType.Submit, DomainOperationType.Invoke));

            nw  = new TestDomainServices.EF.Northwind();
            dsc = new DomainServiceContext(new MockDataService(new MockUser("mathew")
            {
                IsAuthenticated = true
            }), DomainOperationType.Query);
            nw.Initialize(dsc);

            ChangeSet cs = new ChangeSet(new ChangeSetEntry[] {
                new ChangeSetEntry()
                {
                    Entity = new ServiceContext_CurrentOperation_Entity()
                    {
                        Key = 1
                    },
                    Operation = DomainOperation.Insert
                }
            });
            await ExceptionHelper.ExpectExceptionAsync <InvalidOperationException>(async() =>
            {
                await nw.SubmitAsync(cs, CancellationToken.None);
            }, string.Format(Resource.DomainService_InvalidOperationType, DomainOperationType.Query, DomainOperationType.Submit));
        }
Пример #11
0
        public async Task ServiceContext_CurrentOperation()
        {
            DomainServiceDescription dsd = DomainServiceDescription.GetDescription(typeof(ServiceContext_CurrentOperation_DomainService));
            ServiceContext_CurrentOperation_DomainService ds;

            // Execute a query.
            ds = new ServiceContext_CurrentOperation_DomainService(DomainOperationType.Query);
            DomainOperationEntry queryOp = dsd.GetQueryMethod("GetEntities");

            Assert.IsNotNull(queryOp);
            QueryDescription desc = new QueryDescription(queryOp);
            var queryResult       = await ds.QueryAsync <ServiceContext_CurrentOperation_Entity>(desc, CancellationToken.None);

            Assert.AreEqual(queryOp, ServiceContext_CurrentOperation_DomainService.LastOperation);
            Assert.IsNull(ds.Context.Operation);

            // Invoke an operation.
            ds = new ServiceContext_CurrentOperation_DomainService(DomainOperationType.Invoke);
            DomainOperationEntry invokeOp = dsd.GetInvokeOperation("Echo");

            Assert.IsNotNull(invokeOp);
            await ds.InvokeAsync(new InvokeDescription(invokeOp, null), CancellationToken.None);

            Assert.AreEqual(invokeOp, ServiceContext_CurrentOperation_DomainService.LastOperation);
            Assert.IsNull(ds.Context.Operation);

            // Invoke an insert operation.
            ds = new ServiceContext_CurrentOperation_DomainService(DomainOperationType.Submit);
            DomainOperationEntry insertOp = dsd.GetSubmitMethod(typeof(ServiceContext_CurrentOperation_Entity), DomainOperation.Insert);

            Assert.IsNotNull(insertOp);
            await ds.SubmitAsync(new ChangeSet(new ChangeSetEntry[] {
                new ChangeSetEntry()
                {
                    Entity = new ServiceContext_CurrentOperation_Entity()
                    {
                        Key = 1
                    },
                    Operation = DomainOperation.Insert
                }
            }), CancellationToken.None);

            Assert.AreEqual(insertOp, ServiceContext_CurrentOperation_DomainService.LastOperation);
            Assert.IsNull(ds.Context.Operation);
        }
Пример #12
0
        public void ServiceContext_CurrentOperation()
        {
            DomainServiceDescription dsd = DomainServiceDescription.GetDescription(typeof(ServiceContext_CurrentOperation_DomainService));
            ServiceContext_CurrentOperation_DomainService ds;
            IEnumerable <ValidationResult> validationErrors;

            // Execute a query.
            ds = new ServiceContext_CurrentOperation_DomainService(DomainOperationType.Query);
            DomainOperationEntry queryOp = dsd.GetQueryMethod("GetEntities");

            Assert.IsNotNull(queryOp);
            QueryDescription desc = new QueryDescription(queryOp);
            int totalCount;

            ds.Query(desc, out validationErrors, out totalCount);
            Assert.AreEqual(queryOp, ServiceContext_CurrentOperation_DomainService.LastOperation);
            Assert.IsNull(ds.Context.Operation);

            // Invoke an operation.
            ds = new ServiceContext_CurrentOperation_DomainService(DomainOperationType.Invoke);
            DomainOperationEntry invokeOp = dsd.GetInvokeOperation("Echo");

            Assert.IsNotNull(invokeOp);
            ds.Invoke(new InvokeDescription(invokeOp, null), out validationErrors);
            Assert.AreEqual(invokeOp, ServiceContext_CurrentOperation_DomainService.LastOperation);
            Assert.IsNull(ds.Context.Operation);

            // Invoke an insert operation.
            ds = new ServiceContext_CurrentOperation_DomainService(DomainOperationType.Submit);
            DomainOperationEntry insertOp = dsd.GetSubmitMethod(typeof(ServiceContext_CurrentOperation_Entity), DomainOperation.Insert);

            Assert.IsNotNull(insertOp);
            ds.Submit(new ChangeSet(new ChangeSetEntry[] {
                new ChangeSetEntry()
                {
                    Entity = new ServiceContext_CurrentOperation_Entity()
                    {
                        Key = 1
                    },
                    Operation = DomainOperation.Insert
                }
            }));
            Assert.AreEqual(insertOp, ServiceContext_CurrentOperation_DomainService.LastOperation);
            Assert.IsNull(ds.Context.Operation);
        }
Пример #13
0
        public static InvokeDescription GetInvokeDescription(OperationContext context, Expression expression)
        {
            context.OperationName = Utility.GetNameFromLambda(expression);
            IEnumerable <object> parameterValues = Utility.GetParametersFromLambda(expression);

            DomainOperationEntry domainOperationEntry = context.DomainServiceDescription.GetInvokeOperation(context.OperationName);

            if (domainOperationEntry == null)
            {
                throw new InvalidOperationException(string.Format(
                                                        CultureInfo.CurrentCulture,
                                                        Resources.NoInvokeOperation,
                                                        context.OperationName,
                                                        context.DomainServiceDescription.DomainServiceType));
            }

            return(new InvokeDescription(domainOperationEntry, parameterValues.ToArray()));
        }
Пример #14
0
        public async Task TestDomainService_QueryDirect_Throws()
        {
            MockDomainService_SelectThrows provider = ServerTestHelper.CreateInitializedDomainService <MockDomainService_SelectThrows>(DomainOperationType.Query);

            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(provider.GetType());
            DomainOperationEntry     method             = serviceDescription.DomainOperationEntries.First(p => p.Name == "GetEntities" && p.Operation == DomainOperation.Query);
            QueryDescription         qd = new QueryDescription(method, Array.Empty <object>());
            await ExceptionHelper.ExpectExceptionAsync <Exception>(async() =>
            {
                try
                {
                    await provider.QueryAsync <TestEntity>(qd, CancellationToken.None);
                }
                catch (TargetInvocationException ex)
                {
                    throw ex.InnerException;
                }
            }, "Test");
        }
        /// <summary>
        /// Helper method performs a invoke operation against a given proxy instance.
        /// </summary>
        /// <param name="domainService">The type of <see cref="DomainService"/> to perform this query operation against.</param>
        /// <param name="context">The current context.</param>
        /// <param name="domainServiceInstances">The list of tracked <see cref="DomainService"/> instances that any newly created
        /// <see cref="DomainServices"/> will be added to.</param>
        /// <param name="name">The name of the operation to invoke.</param>
        /// <param name="parameters">The operation parameters.</param>
        /// <returns>The result of the invoke operation.</returns>
        /// <exception cref="ArgumentNullException">if <paramref name="context"/> is null.</exception>
        /// <exception cref="ArgumentNullException">if <paramref name="name"/> is null or an empty string.</exception>
        /// <exception cref="OperationException">if operation errors are thrown during execution of the invoke operation.</exception>
        public static object Invoke(Type domainService, DomainServiceContext context, IList <DomainService> domainServiceInstances, string name, object[] parameters)
        {
            context = new DomainServiceContext(context, DomainOperationType.Invoke);
            DomainService                  service            = CreateDomainServiceInstance(domainService, context, domainServiceInstances);
            DomainServiceDescription       serviceDescription = DomainServiceDescription.GetDescription(service.GetType());
            DomainOperationEntry           method             = serviceDescription.GetInvokeOperation(name);
            IEnumerable <ValidationResult> validationErrors;

            InvokeDescription invokeDescription = new InvokeDescription(method, parameters);
            object            result            = service.Invoke(invokeDescription, out validationErrors);

            if (validationErrors != null && validationErrors.Any())
            {
                IEnumerable <ValidationResultInfo> operationErrors = validationErrors.Select(ve => new ValidationResultInfo(ve.ErrorMessage, ve.MemberNames));
                throw new OperationException(Resource.DomainServiceProxy_OperationError, operationErrors);
            }

            return(result);
        }
Пример #16
0
        public void AuthorizationAttribute_Custom_Method_Custom_Attribute_Null_Entity_Throws()
        {
            IPrincipal user = this.CreateIPrincipal("user1");

            // Instantiate a new DomainService to use for a custom method via a Submit
            using (AuthorizationTestDomainService testDomainService = new AuthorizationTestDomainService())
            {
                // Note: Submit context enforces null entity test
                testDomainService.Initialize(new DomainServiceContext(new MockDataService(user), DomainOperationType.Submit));

                DomainServiceDescription description = DomainServiceDescription.GetDescription(typeof(AuthorizationTestDomainService));
                DomainOperationEntry     entry       = description.DomainOperationEntries.SingleOrDefault(p => p.Name == "CustomUpdate");
                Assert.IsNotNull(entry, "Did not find CustomUpdate entry");

                // The null entity here should raise ArgNull because the context is Submit
                AuthorizationTestEntity entity = null;
                ExceptionHelper.ExpectArgumentNullExceptionStandard(() => testDomainService.IsAuthorized(entry, entity), "entity");
            }
        }
Пример #17
0
        /// <summary>
        /// Builds the default URI temaplate to be used for side-effecting (POST) operations.
        /// </summary>
        /// <param name="operation">Domain operation.</param>
        /// <returns>string representing the default URI temaplate.</returns>
        private static string BuildDefaultUriTemplate(DomainOperationEntry operation)
        {
            StringBuilder builder = new StringBuilder(operation.Name);

            if (operation.Parameters.Count > 0)
            {
                builder.Append("?");
                foreach (var parameter in operation.Parameters)
                {
                    builder.Append(parameter.Name);
                    builder.Append("={");
                    builder.Append(parameter.Name);
                    builder.Append("}&");
                }
                builder.Remove(builder.Length - 1, 1);
            }

            return(builder.ToString());
        }
Пример #18
0
        private void GenerateInvokeOperationDeclaration(DomainOperationEntry domainOperationEntry, InvokeKind invokeKind)
        {
            // First generate custom attributes for the qery method
            IEnumerable <Attribute> methodAttributes = domainOperationEntry.Attributes.Cast <Attribute>();

            this.GenerateAttributes(methodAttributes);
            string invokeOperationReturnTypeName = this.GetInvokeMethodReturnTypeName(domainOperationEntry, invokeKind);
            var    name = domainOperationEntry.Name;

            if (invokeKind == InvokeKind.Async)
            {
                name = name + "Async";
            }

            this.Write("public ");

            this.Write(this.ToStringHelper.ToStringWithCulture(invokeOperationReturnTypeName));

            this.Write(" ");

            this.Write(this.ToStringHelper.ToStringWithCulture(name));

            this.Write("(\r\n");


            this.GenerateParameterDeclaration(domainOperationEntry.Parameters, true);

            if (invokeKind == InvokeKind.WithCallback)
            {
                if (domainOperationEntry.Parameters.Count() > 0)
                {
                    this.Write(", ");
                }

                this.Write("Action<");

                this.Write(this.ToStringHelper.ToStringWithCulture(invokeOperationReturnTypeName));

                this.Write("> callback, object userState\r\n");
            }

            this.Write(")\r\n");
        }
Пример #19
0
        public async Task InvokeOperation_ServerValidationError()
        {
            TestProvider_Scenarios   provider                  = ServerTestHelper.CreateInitializedDomainService <TestProvider_Scenarios>(DomainOperationType.Invoke);
            DomainServiceDescription serviceDescription        = DomainServiceDescription.GetDescription(typeof(TestProvider_Scenarios));
            DomainOperationEntry     incrementBid1ForAByMethod = serviceDescription.GetInvokeOperation("IncrementBid1ForABy");

            Assert.IsNotNull(incrementBid1ForAByMethod);

            TestDomainServices.A inputA = new TestDomainServices.A()
            {
                BID1 = 1
            };
            var invokeResult = await provider.InvokeAsync(new InvokeDescription(incrementBid1ForAByMethod, new object[] { inputA, 2 }), CancellationToken.None);

            Assert.IsNull(invokeResult.Result);
            Assert.IsNotNull(invokeResult.ValidationErrors);
            Assert.AreEqual(2, invokeResult.ValidationErrors.Count);
            Assert.AreEqual("The field delta must be between 5 and 10.", invokeResult.ValidationErrors.ElementAt(0).ErrorMessage);
            Assert.AreEqual("The RequiredString field is required.", invokeResult.ValidationErrors.ElementAt(1).ErrorMessage);
        }
        public void RequiresRoleAttribute_Authorize_MultipleAttributes_Allowed()
        {
            IPrincipal user = this.CreateIPrincipal("user1", "role1", "role4");

            // Instantiate a new DomainService to use for an Invoke
            using (RequiresRoleTestService testDomainService = new RequiresRoleTestService())
            {
                testDomainService.Initialize(new DomainServiceContext(new MockDataService(user), DomainOperationType.Invoke));

                // Get a DomainServiceDescription for that same domain service
                DomainServiceDescription description = DomainServiceDescription.GetDescription(typeof(RequiresRoleTestService));

                // Locate the invoke method
                DomainOperationEntry invokeEntry = description.DomainOperationEntries.Single(p => p.Name == "Method1");

                AuthorizationResult result = testDomainService.IsAuthorized(invokeEntry, entity: null);

                Assert.AreSame(AuthorizationResult.Allowed, result, "Expected user in role1 and role4 to be allowed against invoke requiring roles (1 or 2) && (3 or 4) in multiple attributes");
            }
        }
Пример #21
0
        internal string GetInvokeMethodReturnTypeName(DomainOperationEntry domainOperationEntry, InvokeKind invokeKind)
        {
            Type   returnType       = CodeGenUtilities.TranslateType(domainOperationEntry.ReturnType);
            string returnTypeString = (invokeKind == InvokeKind.Async) ? "InvokeResult" :  "InvokeOperation";

            if (returnType != typeof(void))
            {
                if (!this.RegisterEnumTypeIfNecessary(returnType, domainOperationEntry))
                {
                    return(String.Empty);
                }
                returnTypeString = returnTypeString + "<" + CodeGenUtilities.GetTypeName(returnType) + ">";
            }

            if (invokeKind == InvokeKind.Async)
            {
                returnTypeString = string.Format("System.Threading.Tasks.Task<{0}>", returnTypeString);
            }
            return(returnTypeString);
        }
Пример #22
0
        /// <summary>
        /// Helper method performs a invoke operation against a given proxy instance.
        /// </summary>
        /// <param name="domainService">The type of <see cref="DomainService"/> to perform this query operation against.</param>
        /// <param name="context">The current context.</param>
        /// <param name="domainServiceInstances">The list of tracked <see cref="DomainService"/> instances that any newly created
        /// <see cref="DomainServices"/> will be added to.</param>
        /// <param name="name">The name of the operation to invoke.</param>
        /// <param name="parameters">The operation parameters.</param>
        /// <returns>The result of the invoke operation.</returns>
        /// <exception cref="ArgumentNullException">if <paramref name="context"/> is null.</exception>
        /// <exception cref="ArgumentNullException">if <paramref name="name"/> is null or an empty string.</exception>
        /// <exception cref="OperationException">if operation errors are thrown during execution of the invoke operation.</exception>
        public static object Invoke(Type domainService, DomainServiceContext context, IList <DomainService> domainServiceInstances, string name, object[] parameters)
        {
            context = new DomainServiceContext(context, DomainOperationType.Invoke);
            DomainService            service            = CreateDomainServiceInstance(domainService, context, domainServiceInstances);
            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(service.GetType());
            DomainOperationEntry     method             = serviceDescription.GetInvokeOperation(name);

            InvokeDescription invokeDescription = new InvokeDescription(method, parameters);
            // TODO: Look into removing this blocking Wait
            var loadResult = service.InvokeAsync(invokeDescription, CancellationToken.None)
                             .GetAwaiter().GetResult();

            if (loadResult.HasValidationErrors)
            {
                IEnumerable <ValidationResultInfo> operationErrors = loadResult.ValidationErrors.Select(ve => new ValidationResultInfo(ve.ErrorMessage, ve.MemberNames));
                throw new OperationException(Resource.DomainServiceProxy_OperationError, operationErrors);
            }

            return(loadResult.Result);
        }
Пример #23
0
        internal static string GetEndOperationReturnType(DomainOperationEntry operation)
        {
            string returnTypeName = null;

            if (operation.Operation == DomainOperation.Query)
            {
                if (operation.ReturnType == typeof(void))
                {
                    returnTypeName = "OpenRiaServices.DomainServices.Client.QueryResult";
                }
                else
                {
                    returnTypeName = "OpenRiaServices.DomainServices.Client.QueryResult<" + CodeGenUtilities.GetTypeName(CodeGenUtilities.TranslateType(operation.AssociatedType)) + ">";
                }
            }
            else
            {
                returnTypeName = CodeGenUtilities.GetTypeName(CodeGenUtilities.TranslateType(operation.ReturnType));
            }
            return(returnTypeName);
        }
Пример #24
0
        public async Task TestDomainService_QueryDirect()
        {
            TestDomainServices.LTS.Catalog provider = ServerTestHelper.CreateInitializedDomainService <TestDomainServices.LTS.Catalog>(DomainOperationType.Query);

            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(provider.GetType());
            DomainOperationEntry     method             = serviceDescription.DomainOperationEntries.Where(p => p.Operation == DomainOperation.Query).First(p => p.Name == "GetProductsByCategory");
            QueryDescription         qd = new QueryDescription(method, new object[] { 1 });

            var queryResult = await provider.QueryAsync <DataTests.AdventureWorks.LTS.Product>(qd, CancellationToken.None);

            int count = queryResult.Result.Cast <DataTests.AdventureWorks.LTS.Product>().Count();

            Assert.AreEqual(32, count);

            // verify that we can use the same provider to execute another query
            qd          = new QueryDescription(method, new object[] { 2 });
            queryResult = await provider.QueryAsync <DataTests.AdventureWorks.LTS.Product>(qd, CancellationToken.None);

            count = queryResult.Result.Cast <DataTests.AdventureWorks.LTS.Product>().Count();
            Assert.AreEqual(43, count);
        }
        /// <summary>
        /// Validates that the operation entry represents <see cref="IAuthentication{T}.GetUser"/> for use in codegen.
        /// </summary>
        /// <param name="doe">The entry to validate</param>
        /// <param name="userType">The user type. <c>T</c> in <see cref="IAuthentication{T}"/>.</param>
        /// <returns>Whether the operation entry represents GetUser</returns>
        private static bool CheckIAuthenticationGetUser(DomainOperationEntry doe, Type userType)
        {
            bool implementsGetUser = true;

            // [Query]
            // public T GetUser()
            if (doe.Operation != DomainOperation.Query)
            {
                implementsGetUser = false;
            }
            if (doe.ReturnType != userType)
            {
                implementsGetUser = false;
            }
            if (doe.Parameters.Any())
            {
                implementsGetUser = false;
            }

            return(implementsGetUser);
        }
Пример #26
0
        public void TestDomainService_QueryDirect()
        {
            TestDomainServices.LTS.Catalog provider = ServerTestHelper.CreateInitializedDomainService <TestDomainServices.LTS.Catalog>(DomainOperationType.Query);

            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(provider.GetType());
            DomainOperationEntry     method             = serviceDescription.DomainOperationEntries.Where(p => p.Operation == DomainOperation.Query).First(p => p.Name == "GetProductsByCategory");
            QueryDescription         qd = new QueryDescription(method, new object[] { 1 });
            int totalCount;
            IEnumerable <ValidationResult> validationErrors;
            IEnumerable result = provider.Query(qd, out validationErrors, out totalCount);

            int count = result.Cast <DataTests.AdventureWorks.LTS.Product>().Count();

            Assert.AreEqual(32, count);

            // verify that we can use the same provider to execute another query
            qd     = new QueryDescription(method, new object[] { 2 });
            result = provider.Query(qd, out validationErrors, out totalCount);
            count  = result.Cast <DataTests.AdventureWorks.LTS.Product>().Count();
            Assert.AreEqual(43, count);
        }
Пример #27
0
        public async Task ServerValidation_InvokeOperation()
        {
            TestDomainServices.TestProvider_Scenarios service = ServerTestHelper.CreateInitializedDomainService <TestDomainServices.TestProvider_Scenarios>(DomainOperationType.Invoke);

            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(service.GetType());
            DomainOperationEntry     method             = serviceDescription.DomainOperationEntries.Single(p => p.Name == "InvokeOperationWithParamValidation");
            InvokeDescription        invokeDescription  = new InvokeDescription(method, new object[] { -3, "ABC", new TestDomainServices.CityWithCacheData() });
            var invokeResult = await service.InvokeAsync(invokeDescription, CancellationToken.None);

            Assert.IsNotNull(invokeResult.ValidationErrors);
            Assert.AreEqual(2, invokeResult.ValidationErrors.Count());

            ValidationResult error = invokeResult.ValidationErrors.ElementAt(0);

            Assert.AreEqual("The field a must be between 0 and 10.", error.ErrorMessage);
            Assert.AreEqual("a", error.MemberNames.Single());

            error = invokeResult.ValidationErrors.ElementAt(1);
            Assert.AreEqual("The field b must be a string with a maximum length of 2.", error.ErrorMessage);
            Assert.AreEqual("b", error.MemberNames.Single());
        }
Пример #28
0
        /// <summary>
        /// Helper method performs a query operation against a given proxy instance.
        /// </summary>
        /// <param name="domainService">The type of <see cref="DomainService"/> to perform this query operation against.</param>
        /// <param name="context">The current context.</param>
        /// <param name="domainServiceInstances">The list of tracked <see cref="DomainService"/> instances that any newly created
        /// <see cref="DomainServices"/> will be added to.</param>
        /// <param name="queryName">The name of the query to invoke.</param>
        /// <param name="parameters">The query parameters.</param>
        /// <returns>The query results. May be null if there are no query results.</returns>
        /// <exception cref="ArgumentNullException">if <paramref name="context"/> is null.</exception>
        /// <exception cref="ArgumentNullException">if <paramref name="queryName"/> is null or an empty string.</exception>
        /// <exception cref="InvalidOperationException">if no match query operation exists on the <paramref name="context"/>.</exception>
        /// <exception cref="OperationException">if operation errors are thrown during execution of the query operation.</exception>
        public static IEnumerable Query(Type domainService, DomainServiceContext context, IList <DomainService> domainServiceInstances, string queryName, object[] parameters)
        {
            context = new DomainServiceContext(context, DomainOperationType.Query);
            DomainService            service            = CreateDomainServiceInstance(domainService, context, domainServiceInstances);
            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(service.GetType());
            DomainOperationEntry     queryOperation     = serviceDescription.GetQueryMethod(queryName);

            if (queryOperation == null)
            {
                string errorMessage =
                    string.Format(
                        CultureInfo.InvariantCulture,
                        Resource.DomainServiceProxy_QueryOperationNotFound,
                        queryName,
                        domainService);

                throw new InvalidOperationException(errorMessage);
            }

            IEnumerable <ValidationResult> validationErrors;

            object[]         parameterValues  = parameters ?? Array.Empty <object>();
            QueryDescription queryDescription = new QueryDescription(queryOperation, parameterValues);

            // TODO: Look into removing this blocking Wait
            var actualMethod = s_queryAsync.MakeGenericMethod(queryDescription.Method.AssociatedType);
            var queryResult  = ((ValueTask <ServiceQueryResult>)actualMethod.Invoke(service, new object[] { queryDescription, CancellationToken.None }))
                               .GetAwaiter().GetResult();

            validationErrors = queryResult.ValidationErrors;
            var result = queryResult.Result;

            if (validationErrors != null && validationErrors.Any())
            {
                IEnumerable <ValidationResultInfo> operationErrors = validationErrors.Select(ve => new ValidationResultInfo(ve.ErrorMessage, ve.MemberNames));
                throw new OperationException(Resource.DomainServiceProxy_OperationError, operationErrors);
            }

            return(result);
        }
        /// <summary>
        /// If the query operation has a result limit, this operation will compose Take(limit) on top 
        /// of the specified results.
        /// </summary>
        /// <param name="results">The results that may need to be limited.</param>
        /// <param name="queryOperation">The query operation that was invoked to get the results.</param>
        /// <param name="limitedResults">The limited results. It will be <value>null</value> if there is no result limit.</param>
        /// <returns>True if a limited result query is returned, false otherwise.</returns>
        internal static bool TryComposeWithLimit(IEnumerable results, DomainOperationEntry queryOperation, out IEnumerable limitedResults)
        {
            int limit = ((QueryAttribute)queryOperation.OperationAttribute).ResultLimit;
            if (limit > 0)
            {
                IQueryable queryableResult = results.AsQueryable();

                // Compose Take(limit) over the results.
                IQueryable limitQuery = Array.CreateInstance(queryOperation.AssociatedType, 0).AsQueryable();
                limitQuery = limitQuery.Provider.CreateQuery(
                    Expression.Call(
                        typeof(Queryable), "Take",
                        new Type[] { limitQuery.ElementType },
                        limitQuery.Expression, Expression.Constant(limit)));

                limitedResults = QueryComposer.Compose(queryableResult, limitQuery);
                return true;
            }

            limitedResults = null;
            return false;
        }
Пример #30
0
        public void DomainServiceWithMultipleValidOnlineMethods()
        {
            DomainServiceDescription description = DomainServiceDescription.GetDescription(typeof(OnlineMethod_ValidProvider_MultipleMethods));

            Assert.IsNotNull(description);

            // verify GetOnlineMethod returns the correct DomainOperationEntry
            DomainOperationEntry returnedMethod = description.GetInvokeOperation("Process_VoidReturn");

            Assert.IsNotNull(returnedMethod);
            Assert.AreEqual(DomainOperation.Invoke, returnedMethod.Operation);
            Assert.AreEqual("Process_VoidReturn", returnedMethod.Name);

            // verify GetOnlineMethods return all the invoke operations on this provider
            IEnumerable <DomainOperationEntry> returnedMethods = description.DomainOperationEntries.Where(p => p.Operation == DomainOperation.Invoke);

            Assert.IsNotNull(returnedMethods);
            Assert.AreEqual(10, returnedMethods.Count());
            Assert.IsTrue(returnedMethods.Any(p => p.Name == "Process_EntitiesAndSimpleParams"));

            Assert.IsTrue(returnedMethods.Any(p => p.Name == "Process_Return_EntityListParam"));
        }
        /// <summary>
        /// Validates that the operation entry represents <see cref="IAuthentication{T}.UpdateUser"/> for use in codegen.
        /// </summary>
        /// <param name="doe">The entry to validate</param>
        /// <param name="userType">The user type. <c>T</c> in <see cref="IAuthentication{T}"/>.</param>
        /// <returns>Whether the operation entry represents UpdateUser</returns>
        private static bool CheckIAuthenticationUpdateUser(DomainOperationEntry doe, Type userType)
        {
            bool implementsUpdateUser = true;

            // [Update]
            // public void UpdateUser(T user)
            if (doe.Operation != DomainOperation.Update)
            {
                implementsUpdateUser = false;
            }
            if (doe.ReturnType != typeof(void))
            {
                implementsUpdateUser = false;
            }
            if ((doe.Parameters.Count() != 1) ||
                (doe.Parameters[0].ParameterType != userType))
            {
                implementsUpdateUser = false;
            }

            return(implementsUpdateUser);
        }
Пример #32
0
        private void GenerateCustomMethodProperties(DomainOperationEntry customMethod)
        {
            this.Write("[System.ComponentModel.DataAnnotations.Display(AutoGenerateField=false)]\r\npublic " +
                       "bool Can");

            this.Write(this.ToStringHelper.ToStringWithCulture(customMethod.Name));

            this.Write("\r\n{\r\n\tget\r\n\t{\r\n\t\treturn base.CanInvokeAction(\"");

            this.Write(this.ToStringHelper.ToStringWithCulture(customMethod.Name));

            this.Write("\");\r\n\t}\r\n}\r\n\r\n[System.ComponentModel.DataAnnotations.Display(AutoGenerateField=fa" +
                       "lse)]\r\npublic bool Is");

            this.Write(this.ToStringHelper.ToStringWithCulture(customMethod.Name));

            this.Write("Invoked\r\n{\r\n\tget\r\n\t{\r\n\t\treturn base.IsActionInvoked(\"");

            this.Write(this.ToStringHelper.ToStringWithCulture(customMethod.Name));

            this.Write("\");\r\n\t}\r\n}\r\n");
        }
Пример #33
0
        public void TestDomainService_QueryDirect_Throws()
        {
            MockDomainService_SelectThrows provider = ServerTestHelper.CreateInitializedDomainService <MockDomainService_SelectThrows>(DomainOperationType.Query);

            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(provider.GetType());
            DomainOperationEntry     method             = serviceDescription.DomainOperationEntries.First(p => p.Name == "GetEntities" && p.Operation == DomainOperation.Query);
            QueryDescription         qd = new QueryDescription(method, new object[0]);
            int totalCount;
            IEnumerable <ValidationResult> validationErrors;

            ExceptionHelper.ExpectException <Exception>(delegate
            {
                try
                {
                    provider.Query(qd, out validationErrors, out totalCount);
                }
                catch (TargetInvocationException ex)
                {
                    throw ex.InnerException;
                }
            }, "Test");
        }
Пример #34
0
        public async Task ServerValidation_Query()
        {
            TestDomainServices.TestProvider_Scenarios service = ServerTestHelper.CreateInitializedDomainService <TestDomainServices.TestProvider_Scenarios>(DomainOperationType.Query);

            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(service.GetType());
            DomainOperationEntry     method             = serviceDescription.DomainOperationEntries.Single(p => p.Name == "QueryWithParamValidation");
            QueryDescription         qd = new QueryDescription(method, new object[] { -1, "ABC" });

            var queryResult = await service.QueryAsync <TestDomainServices.A>(qd, CancellationToken.None);

            Assert.IsNotNull(queryResult.ValidationErrors);
            Assert.AreEqual(2, queryResult.ValidationErrors.Count());

            ValidationResult error = queryResult.ValidationErrors.ElementAt(0);

            Assert.AreEqual("The field a must be between 0 and 10.", error.ErrorMessage);
            Assert.AreEqual("a", error.MemberNames.Single());

            error = queryResult.ValidationErrors.ElementAt(1);
            Assert.AreEqual("The field b must be a string with a maximum length of 2.", error.ErrorMessage);
            Assert.AreEqual("b", error.MemberNames.Single());
        }
		internal string GetInvokeMethodReturnTypeName(DomainOperationEntry domainOperationEntry, InvokeKind invokeKind)
		{
			Type returnType = CodeGenUtilities.TranslateType(domainOperationEntry.ReturnType);
			string returnTypeString = (invokeKind == InvokeKind.Async) ? "InvokeResult" : "InvokeOperation";
			if (returnType != typeof (void))
			{
				if (!this.RegisterEnumTypeIfNecessary(returnType, domainOperationEntry))
				{
					return String.Empty;
				}
				returnTypeString = returnTypeString + "<" + CodeGenUtilities.GetTypeName(returnType) + ">";
			}

			if (invokeKind == InvokeKind.Async)
				returnTypeString = string.Format("System.Threading.Tasks.Task<{0}>", returnTypeString);
			return returnTypeString;
		}
	private void GenerateContractMethod(DomainOperationEntry operation)
	{

this.Write("[OpenRiaServices.DomainServices.Client.HasSideEffects(");

this.Write(this.ToStringHelper.ToStringWithCulture(DomainContextGenerator.OperationHasSideEffects(operation).ToString().ToLower()));

this.Write(")]\r\n");


		this.GenerateContractMethodAttributes(operation.Name);

this.Write("System.IAsyncResult Begin");

this.Write(this.ToStringHelper.ToStringWithCulture(operation.Name));

this.Write("(\r\n");


		foreach (DomainOperationParameter parameter in operation.Parameters)
		{
			Type parameterType = CodeGenUtilities.TranslateType(parameter.ParameterType);

this.Write(this.ToStringHelper.ToStringWithCulture(CodeGenUtilities.GetTypeName(parameterType)));

this.Write(" ");

this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name));

this.Write(",\r\n");


		}

this.Write("System.AsyncCallback callback, object asyncState);\r\n");


		string returnTypeName = CSharpDomainContextGenerator.GetEndOperationReturnType(operation);

this.Write("\t\t\r\n");

this.Write(this.ToStringHelper.ToStringWithCulture(returnTypeName));

this.Write(" End");

this.Write(this.ToStringHelper.ToStringWithCulture(operation.Name));

this.Write("(System.IAsyncResult result);\r\n");


	}
private string GenerateServiceOpMethodBody(DomainOperationEntry domainOperationEntry, string methodName)
{
	string parameterDictionaryName = "null";
	DomainOperationParameter[] domainOperationEntryParameters = domainOperationEntry.Parameters.ToArray();
	if(domainOperationEntryParameters.Length > 0)
	{
		parameterDictionaryName = "parameters";

this.Write("Dictionary<string, object> ");

this.Write(this.ToStringHelper.ToStringWithCulture(parameterDictionaryName));

this.Write(" = new Dictionary<string, object>();\r\n");


		foreach(DomainOperationParameter paramInfo in domainOperationEntryParameters)
		{
			if (!this.RegisterEnumTypeIfNecessary(paramInfo.ParameterType, domainOperationEntry))
			{
				return String.Empty;
			}
			string paramName = CodeGenUtilities.GetSafeName(paramInfo.Name);

this.Write(this.ToStringHelper.ToStringWithCulture(parameterDictionaryName));

this.Write(".Add(\"");

this.Write(this.ToStringHelper.ToStringWithCulture(paramName));

this.Write("\", ");

this.Write(this.ToStringHelper.ToStringWithCulture(paramName));

this.Write(");\r\n");


		}
	}


this.Write("this.ValidateMethod(\"");

this.Write(this.ToStringHelper.ToStringWithCulture(methodName));

this.Write("\", ");

this.Write(this.ToStringHelper.ToStringWithCulture(parameterDictionaryName));

this.Write(");\r\n");


	return parameterDictionaryName;
}
private void GenerateInvokeMethodReturn(DomainOperationEntry domainOperationEntry, string parameterDictionaryString, InvokeKind invokeKind)
{
	InvokeAttribute invokeAttribute = (InvokeAttribute)domainOperationEntry.OperationAttribute;
	string returnTypeNameString = CodeGenUtilities.GetTypeName(CodeGenUtilities.TranslateType(domainOperationEntry.ReturnType));

	if(invokeKind == InvokeKind.Async)
	{
		returnTypeNameString = (domainOperationEntry.ReturnType == typeof(void)) ? string.Empty : string.Format("<{0}>", returnTypeNameString);

this.Write("return this.InvokeOperationAsync");

this.Write(this.ToStringHelper.ToStringWithCulture(returnTypeNameString));

this.Write("(\"");

this.Write(this.ToStringHelper.ToStringWithCulture(domainOperationEntry.Name));

this.Write("\", ");

this.Write(this.ToStringHelper.ToStringWithCulture(parameterDictionaryString));

this.Write(", \r\n");

this.Write(this.ToStringHelper.ToStringWithCulture(CodeGenUtilities.GetBooleanString(invokeAttribute.HasSideEffects, true)));

this.Write(");\r\n");


	}
	else
	{

this.Write("return this.");

this.Write(this.ToStringHelper.ToStringWithCulture(this.GetInvokeMethodReturnTypeName(domainOperationEntry, invokeKind)));

this.Write("(\"");

this.Write(this.ToStringHelper.ToStringWithCulture(domainOperationEntry.Name));

this.Write("\", typeof(");

this.Write(this.ToStringHelper.ToStringWithCulture(returnTypeNameString));

this.Write("), ");

this.Write(this.ToStringHelper.ToStringWithCulture(parameterDictionaryString));

this.Write(", \r\n");

this.Write(this.ToStringHelper.ToStringWithCulture(CodeGenUtilities.GetBooleanString(invokeAttribute.HasSideEffects, true)));

this.Write(",\r\n");


		if(invokeKind == InvokeKind.WithCallback)
		{

this.Write("callback, userState);\r\n");


		}
		else
		{

this.Write("null, null);\r\n");


		}
	}

}
private void GenerateInvokeMethodBody(DomainOperationEntry domainOperationEntry, InvokeKind invokeKind)
{
	string parameterDictionaryString = this.GenerateServiceOpMethodBody(domainOperationEntry, domainOperationEntry.Name);
	this.GenerateInvokeMethodReturn(domainOperationEntry, parameterDictionaryString, invokeKind);
}
	/// <summary>
	/// Generates a custom method.
	/// </summary>
	/// <param name="domainMethod">The custom method to be generated.</param>
	protected virtual void GenerateCustomMethod(DomainOperationEntry domainMethod)
	{

this.Write("public void ");

this.Write(this.ToStringHelper.ToStringWithCulture(domainMethod.Name));

this.Write("(");


		List<string> invokeParams = new List<string>();
		DomainOperationParameter[] paramInfos = domainMethod.Parameters.ToArray();
		for(int i = 0; i < paramInfos.Length; i++)
		{
			DomainOperationParameter paramInfo = paramInfos[i];
			string paramTypeName = CodeGenUtilities.GetTypeName(CodeGenUtilities.TranslateType(paramInfo.ParameterType));
			
this.Write(this.ToStringHelper.ToStringWithCulture(paramTypeName));

this.Write(" ");

this.Write(this.ToStringHelper.ToStringWithCulture(CodeGenUtilities.GetSafeName(paramInfo.Name)));


			if(i + 1 < paramInfos.Length)
			{
				
this.Write(", ");


			}
			if(i > 0)
			{
				invokeParams.Add(paramInfo.Name);
			}
		}

this.Write(")\r\n");


		this.GenerateOpeningBrace();

this.Write(this.ToStringHelper.ToStringWithCulture(paramInfos[0].Name));

this.Write(".");

this.Write(this.ToStringHelper.ToStringWithCulture(domainMethod.Name));

this.Write("(");

  
			for(int i = 0; i < invokeParams.Count; i ++)
			{
				
this.Write(this.ToStringHelper.ToStringWithCulture(invokeParams[i]));


				if(i + 1 < invokeParams.Count)
				{
					
this.Write(", ");


				}
			}
		
this.Write(");\r\n");


		this.GenerateClosingBrace();
	}
        internal bool CanGenerateDomainOperationEntry(DomainOperationEntry domainOperationEntry)
        {
            string methodName = (domainOperationEntry.Operation == DomainOperation.Query) ? domainOperationEntry.Name : domainOperationEntry.Name + QuerySuffix;

            // Check each parameter type to see if is enum
            DomainOperationParameter[] paramInfos = domainOperationEntry.Parameters.ToArray();
            for (int i = 0; i < paramInfos.Length; i++)
            {
                DomainOperationParameter paramInfo = paramInfos[i];

                // If this is an enum type, we need to ensure it is either shared or
                // can be generated.  Failure logs an error.  The test for legality also causes
                // the enum to be generated if required.
                Type enumType = TypeUtility.GetNonNullableType(paramInfo.ParameterType);
                if (enumType.IsEnum)
                {
                    string errorMessage = null;
                    if (!this.ClientCodeGenerator.CanExposeEnumType(enumType, out errorMessage))
                    {
                        this.ClientCodeGenerator.CodeGenerationHost.LogError(string.Format(CultureInfo.CurrentCulture,
                                                                Resource.ClientCodeGen_Domain_Op_Enum_Error,
                                                                domainOperationEntry.Name,
                                                                this.DomainContextTypeName,
                                                                enumType.FullName,
                                                                errorMessage));
                        return false;
                    }
                    else
                    {
                        // Register use of this enum type, which could cause deferred generation
                        this.ClientCodeGenerator.AddEnumTypeToGenerate(enumType);
                    }
                }
            }
            return true;
        }
/// <summary>
/// Generates an invoke operation.
/// </summary>
/// <param name="domainOperationEntry">The invoke operation to be generated.</param>
/// <param name="generateCallback">If set to true, causes callback to be generated on the method.</param>
protected virtual void GenerateInvokeOperation(DomainOperationEntry domainOperationEntry, bool generateCallback)
{
	var invokeKind = generateCallback ? (InvokeKind.WithCallback) : (InvokeKind.WithoutCallback);
	GenerateInvokeOperation(domainOperationEntry, invokeKind);
}
 internal static bool OperationHasSideEffects(DomainOperationEntry operation)
 {
     if (operation.Operation == DomainOperation.Query)
     {
         return ((QueryAttribute)operation.OperationAttribute).HasSideEffects;
     }
     else if (operation.Operation == DomainOperation.Invoke)
     {
         return ((InvokeAttribute)operation.OperationAttribute).HasSideEffects;
     }
     return false;
 }        
 /// <summary>
 /// Initializes a new instance of the <see cref="QueryDescription"/> class with the specified
 /// <see cref="DomainOperationEntry"/>, parameter values, flag indicating whether
 /// to evaluate and include total entity count in the result and (optional) query to compose over
 /// the results.
 /// </summary>
 /// <param name="domainOperationEntry">The query operation to be processed</param>
 /// <param name="parameterValues">Parameter values for the method if it requires any</param>
 /// <param name="includeTotalCount">Flag to indicate that total entity count is required</param>
 /// <param name="query">The query to compose over the results</param>
 public QueryDescription(DomainOperationEntry domainOperationEntry, object[] parameterValues, bool includeTotalCount, IQueryable query)
     : this(domainOperationEntry, parameterValues)
 {
     this._query = query;
     this._includeTotalCount = includeTotalCount;
 }
	private void GenerateEntityQueryMethodDeclaration(DomainOperationEntry domainOperationEntry, string queryMethodName)
	{
		// First generate custom attributes for the qery method
		IEnumerable<Attribute> methodAttributes = domainOperationEntry.Attributes.Cast<Attribute>();
		this.GenerateAttributes(methodAttributes);


this.Write("public EntityQuery<");

this.Write(this.ToStringHelper.ToStringWithCulture(this.GetEntityQueryMethodElementReturnTypeName(domainOperationEntry)));

this.Write("> ");

this.Write(this.ToStringHelper.ToStringWithCulture(queryMethodName));

this.Write("(");


	this.GenerateParameterDeclaration(domainOperationEntry.Parameters.AsEnumerable(), true);

this.Write(")\r\n");


	}
 public void InsertEntity(ServiceContext_CurrentOperation_Entity entity)
 {
     LastOperation = this.ServiceContext.Operation;
 }
		internal static string GetEndOperationReturnType(DomainOperationEntry operation)
		{
			string returnTypeName = null;
			if (operation.Operation == DomainOperation.Query)
			{
				if (operation.ReturnType == typeof (void))
				{
					returnTypeName = "OpenRiaServices.DomainServices.Client.QueryResult";
				}
				else
				{
					returnTypeName = "OpenRiaServices.DomainServices.Client.QueryResult<" +
					                 CodeGenUtilities.GetTypeName(CodeGenUtilities.TranslateType(operation.AssociatedType)) + ">";
				}
			}
			else
			{
				returnTypeName = CodeGenUtilities.GetTypeName(CodeGenUtilities.TranslateType(operation.ReturnType));
			}
			return returnTypeName;
		}
/// <summary>
/// Generates an async invoke operation.
/// </summary>
/// <param name="domainOperationEntry">The invoke operation to be generated.</param>
/// <param name="invokeKind">The type of invoke operation to be generated.</param>
protected virtual void GenerateInvokeOperation(DomainOperationEntry domainOperationEntry, InvokeKind invokeKind)
{
	this.GenerateInvokeOperationDeclaration(domainOperationEntry, invokeKind);

	this.GenerateOpeningBrace();
	this.GenerateInvokeMethodBody(domainOperationEntry, invokeKind);
	this.GenerateClosingBrace();
}
        private void GenerateCustomMethod(string customMethodName, DomainOperationEntry customMethod)
        {
            this.ClientProxyGenerator.LogMessage(string.Format(CultureInfo.CurrentCulture, Resource.EntityCodeGen_Generating_InvokeMethod, customMethodName));

            // ----------------------------------------------------------------
            // Method decl
            // ----------------------------------------------------------------
            CodeMemberMethod method = new CodeMemberMethod();
            method.Name = customMethodName;
            method.Attributes = MemberAttributes.Public | MemberAttributes.Final;

            // The custom method parameter list is the same as the domain operation entries -- except for the first parameter
            // which is the entity.  We omit that first parameter in code gen
            DomainOperationParameter[] paramInfos = customMethod.Parameters.ToArray();

            // Generate <summary> doc comment for the custom method body
            string comment = string.Format(CultureInfo.CurrentCulture, Resource.CodeGen_Entity_Custom_Method_Summary_Comment, customMethodName);
            method.Comments.AddRange(CodeGenUtilities.GenerateSummaryCodeComment(comment, this.ClientProxyGenerator.IsCSharp));

            // Generate <param> doc comment for all the parameters
            for (int i = 1; i < paramInfos.Length; ++i)
            {
                comment = string.Format(CultureInfo.CurrentCulture, Resource.CodeGen_Entity_Custom_Method_Parameter_Comment, paramInfos[i].Name);
                method.Comments.AddRange(CodeGenUtilities.GenerateParamCodeComment(paramInfos[i].Name, comment, this.ClientProxyGenerator.IsCSharp));
            }

            // Propagate custom validation attributes from the DomainOperationEntry to this custom method
            var methodAttributes = customMethod.Attributes.Cast<Attribute>().ToList();
            CustomAttributeGenerator.GenerateCustomAttributes(
                this.ClientProxyGenerator,
                this._proxyClass,
                ex => string.Format(CultureInfo.CurrentCulture, Resource.ClientCodeGen_Attribute_ThrewException_CodeMethod, ex.Message, method.Name, this._proxyClass.Name, ex.InnerException.Message),
                methodAttributes,
                method.CustomAttributes,
                method.Comments);

            // Add [CustomMethod("...")] property
            var customMethodAttribute = customMethod.OperationAttribute as EntityActionAttribute;
            bool allowMultipleInvocations = customMethodAttribute != null && customMethodAttribute.AllowMultipleInvocations;
            method.CustomAttributes.Add(
                
                new CodeAttributeDeclaration(
                    CodeGenUtilities.GetTypeReference(TypeConstants.EntityActionAttributeFullName, (string)this._proxyClass.UserData["Namespace"], false),
                    new CodeAttributeArgument(new CodePrimitiveExpression(customMethodName)),
                    new CodeAttributeArgument("AllowMultipleInvocations", 
                                                new CodePrimitiveExpression(allowMultipleInvocations))
                        ));

            // ----------------------------------------------------------------
            // generate custom method body:
            //    this.OnMethodNameInvoking(params);
            //    base.Invoke(methodName, params);
            //    this.OnMethodNameInvoked();
            // ----------------------------------------------------------------
            List<CodeExpression> invokeParams = new List<CodeExpression>();
            invokeParams.Add(new CodePrimitiveExpression(customMethodName));

            // Create an expression for each parameter, and also use this loop to
            // propagate the custom attributes for each parameter in the DomainOperationEntry to the custom method.
            for (int i = 1; i < paramInfos.Length; ++i)
            {
                DomainOperationParameter paramInfo = paramInfos[i];

                // build up the method parameter signature from the DomainOperationEntry.MethodInfo
                CodeParameterDeclarationExpression paramDecl = new CodeParameterDeclarationExpression(
                    CodeGenUtilities.GetTypeReference(
                        CodeGenUtilities.TranslateType(paramInfo.ParameterType),
                        this.ClientProxyGenerator,
                        this._proxyClass),
                    paramInfo.Name);

                // Propagate parameter level validation attributes from custom operation entry.
                IEnumerable<Attribute> paramAttributes = paramInfo.Attributes.Cast<Attribute>();

                string commentHeader = 
                    string.Format(
                        CultureInfo.CurrentCulture, 
                        Resource.ClientCodeGen_Attribute_Parameter_FailedToGenerate, 
                        paramInfo.Name);

                CustomAttributeGenerator.GenerateCustomAttributes(
                    this.ClientProxyGenerator, 
                    this._proxyClass, 
                    ex => string.Format(CultureInfo.CurrentCulture, Resource.ClientCodeGen_Attribute_ThrewException_CodeMethodParameter, ex.Message, paramDecl.Name, method.Name, this._proxyClass.Name, ex.InnerException.Message),
                    paramAttributes, 
                    paramDecl.CustomAttributes, 
                    method.Comments,
                    commentHeader);

                method.Parameters.Add(paramDecl);

                // build up the invoke call parameters
                invokeParams.Add(new CodeVariableReferenceExpression(paramInfo.Name));
            }

            // generate 'OnCustomMethodInvoked/Invoking'
            string methodInvokingName = customMethodName + "Invoking";
            string methodInvokedName = customMethodName + "Invoked";
            this._notificationMethodGen.AddMethodFor(methodInvokingName, method.Parameters, null);
            this._notificationMethodGen.AddMethodFor(methodInvokedName, null);

            method.Statements.Add(this._notificationMethodGen.GetMethodInvokeExpressionStatementFor(methodInvokingName));
            method.Statements.Add(
                new CodeExpressionStatement(
                    new CodeMethodInvokeExpression(
                        new CodeBaseReferenceExpression(), "InvokeAction", invokeParams.ToArray())));
            method.Statements.Add(this._notificationMethodGen.GetMethodInvokeExpressionStatementFor(methodInvokedName));

            this._proxyClass.Members.Add(method);

            // ----------------------------------------------------------------
            // generate Is<CustomMethod>Invoked property:
            // [Display(AutoGenerateField=false)]
            // public bool IsMyCustomMethodInvoked { get { base.IsActionInvoked(methodName);}}
            // ----------------------------------------------------------------
            CodeMemberProperty invokedProperty = new CodeMemberProperty();
            invokedProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            invokedProperty.HasGet = true;
            invokedProperty.HasSet = false;
            invokedProperty.Type = new CodeTypeReference(typeof(bool));
            invokedProperty.GetStatements.Add(new CodeMethodReturnStatement(
                                                    new CodeMethodInvokeExpression(
                                                        new CodeBaseReferenceExpression(),
                                                        "IsActionInvoked",
                                                        new CodeExpression[] { new CodeArgumentReferenceExpression("\"" + customMethodName + "\"") })));
            invokedProperty.Name = GetIsInvokedPropertyName(customMethodName);

            // Generate <summary> doc comment
            comment = string.Format(CultureInfo.CurrentCulture, Resource.CodeGen_Entity_IsInvoked_Property_Summary_Comment, customMethodName);
            invokedProperty.Comments.AddRange(CodeGenUtilities.GenerateSummaryCodeComment(comment, this.ClientProxyGenerator.IsCSharp));

            CodeAttributeDeclaration displayAttribute = CodeGenUtilities.CreateDisplayAttributeDeclaration(this.ClientProxyGenerator, this._proxyClass);
            invokedProperty.CustomAttributes.Add(displayAttribute);

            this._proxyClass.Members.Add(invokedProperty);
        }
private void GenerateInvokeOperationDeclaration(DomainOperationEntry domainOperationEntry, InvokeKind invokeKind)
{
	// First generate custom attributes for the qery method
	IEnumerable<Attribute> methodAttributes = domainOperationEntry.Attributes.Cast<Attribute>();
	this.GenerateAttributes(methodAttributes);
	string invokeOperationReturnTypeName = this.GetInvokeMethodReturnTypeName(domainOperationEntry, invokeKind);
	var name = domainOperationEntry.Name;

	if(invokeKind == InvokeKind.Async)
		name = name + "Async";

this.Write("public ");

this.Write(this.ToStringHelper.ToStringWithCulture(invokeOperationReturnTypeName));

this.Write(" ");

this.Write(this.ToStringHelper.ToStringWithCulture(name));

this.Write("(\r\n");


	this.GenerateParameterDeclaration(domainOperationEntry.Parameters, true);

	if(invokeKind == InvokeKind.WithCallback)
	{
		if(domainOperationEntry.Parameters.Count() > 0)
		{
			
this.Write(", ");


		}

this.Write("Action<");

this.Write(this.ToStringHelper.ToStringWithCulture(invokeOperationReturnTypeName));

this.Write("> callback, object userState\r\n");


	}

this.Write(")\r\n");


}
	private void GenerateEntityQueryMethodBody(DomainOperationEntry domainOperationEntry, string queryMethodName)
	{
		string parameterDictionaryName = this.GenerateServiceOpMethodBody(domainOperationEntry, queryMethodName);
		this.GenerateEntityQueryMethodReturn(domainOperationEntry, parameterDictionaryName);
	}
        /// <summary>
        /// Builds the default URI temaplate to be used for side-effecting (POST) operations.
        /// </summary>
        /// <param name="operation">Domain operation.</param>
        /// <returns>string representing the default URI temaplate.</returns>
        private static string BuildDefaultUriTemplate(DomainOperationEntry operation)
        {
            StringBuilder builder = new StringBuilder(operation.Name);
            if (operation.Parameters.Count > 0)
            {
                builder.Append("?");
                foreach (var parameter in operation.Parameters)
                {
                    builder.Append(parameter.Name);
                    builder.Append("={");
                    builder.Append(parameter.Name);
                    builder.Append("}&");
                }
                builder.Remove(builder.Length - 1, 1);
            }

            return builder.ToString();
        }
	private void GenerateEntityQueryMethodReturn(DomainOperationEntry domainOperationEntry, string parameterDictionaryName)
	{
		QueryAttribute queryAttribute = (QueryAttribute)domainOperationEntry.OperationAttribute;


this.Write("return base.CreateQuery<");

this.Write(this.ToStringHelper.ToStringWithCulture(this.GetEntityQueryMethodElementReturnTypeName(domainOperationEntry)));

this.Write(">(\"");

this.Write(this.ToStringHelper.ToStringWithCulture(domainOperationEntry.Name));

this.Write("\", ");

this.Write(this.ToStringHelper.ToStringWithCulture(parameterDictionaryName));

this.Write(", ");

this.Write(this.ToStringHelper.ToStringWithCulture(CodeGenUtilities.GetBooleanString(queryAttribute.HasSideEffects, true)));

this.Write(", ");

this.Write(this.ToStringHelper.ToStringWithCulture(CodeGenUtilities.GetBooleanString(queryAttribute.IsComposable, true)));

this.Write(");\r\n");


	}
	private string GetEntityQueryMethodElementReturnTypeName(DomainOperationEntry domainOperationEntry)
	{
		Type entityType = TypeUtility.GetElementType(domainOperationEntry.ReturnType);
		return CodeGenUtilities.GetTypeName(entityType);
	}
	/// <summary>
	/// Generates a query method.
	/// </summary>
	/// <param name="domainOperationEntry">The query method to be generated.</param>
	protected virtual void GenerateQueryMethod(DomainOperationEntry domainOperationEntry)
	{
		string queryMethodName = domainOperationEntry.Name + "Query";		
		this.GenerateEntityQueryMethodDeclaration(domainOperationEntry, queryMethodName);
		this.GenerateOpeningBrace();
		this.GenerateEntityQueryMethodBody(domainOperationEntry, queryMethodName);
		this.GenerateClosingBrace();
	}
        internal List<Attribute> GetContractServiceKnownTypes(DomainOperationEntry operation, HashSet<Type> registeredTypes)
        {
            List<Attribute> knownTypeAttributes = new List<Attribute>();

            foreach (DomainOperationParameter parameter in operation.Parameters)
            {
                Type t = CodeGenUtilities.TranslateType(parameter.ParameterType);

                // All Nullable<T> types are unwrapped to the underlying non-nullable, because
                // that is they type we need to represent, not typeof(Nullable<T>)
                t = TypeUtility.GetNonNullableType(t);

                if (TypeUtility.IsPredefinedListType(t) || TypeUtility.IsComplexTypeCollection(t))
                {
                    Type elementType = TypeUtility.GetElementType(t);
                    if (elementType != null)
                    {
                        t = elementType.MakeArrayType();
                    }
                }

                // Check if the type is a simple type or already registered
                if (registeredTypes.Contains(t) || !this.TypeRequiresRegistration(t))
                {
                    continue;
                }

                // Record the type to prevent redundant [ServiceKnownType]'s.
                // This loop executes within a larger loop over multiple
                // DomainOperationEntries that may have already processed it.
                registeredTypes.Add(t);

                // If we determine we need to generate this enum type on the client,
                // then we need to register that intent and conjure a virtual type
                // here in our list of registered types to account for the fact it
                // could get a different root namespace on the client.
                if (t.IsEnum && this.ClientCodeGenerator.NeedToGenerateEnumType(t))
                {
                    // Request deferred generation of the enum
                    this.ClientCodeGenerator.AddEnumTypeToGenerate(t);

                    // Compose a virtual type that will reflect the correct namespace
                    // on the client when the [ServiceKnownType] is created.
                    t = new VirtualType(t.Name, CodeGenUtilities.TranslateNamespace(t), t.Assembly, t.BaseType);
                }

                knownTypeAttributes.Add(new ServiceKnownTypeAttribute(t));
            }

            return knownTypeAttributes;
        }
 public IQueryable<ServiceContext_CurrentOperation_Entity> GetEntities()
 {
     LastOperation = this.ServiceContext.Operation;
     return null;
 }
        /// <summary>
        /// Create operation corresponding to given DomainService query operation.
        /// </summary>
        /// <param name="declaringContract">Contract to which operation will belong.</param>
        /// <param name="operation">DomainService query operation.</param>
        /// <returns>Created operation.</returns>
        private static OperationDescription CreateQueryOperationDescription(ContractDescription declaringContract, DomainOperationEntry operation)
        {
            OperationDescription operationDesc = ODataEndpointFactory.CreateOperationDescription(declaringContract, operation);

            // Change the return type to QueryResult<TEntity>.
            operationDesc.Messages[1].Body.ReturnValue.Type = typeof(IEnumerable<>).MakeGenericType(operation.AssociatedType);

            return operationDesc;
        }
 public string Echo()
 {
     LastOperation = this.ServiceContext.Operation;
     return "echo";
 }
        /// <summary>
        /// Create operation corresponding to given DomainService operation.
        /// </summary>
        /// <param name="declaringContract">Contract to which operation will belong.</param>
        /// <param name="operation">DomainService operation.</param>
        /// <returns>Created operation.</returns>
        private static OperationDescription CreateOperationDescription(ContractDescription declaringContract, DomainOperationEntry operation)
        {
            OperationDescription operationDesc = new OperationDescription(operation.Name, declaringContract);

            // Propagate behaviors.
            foreach (IOperationBehavior behavior in operation.Attributes.OfType<IOperationBehavior>())
            {
                operationDesc.Behaviors.Add(behavior);
            }

            // Add standard web behaviors behaviors.
            if ((operation.Operation == DomainOperation.Query && ((QueryAttribute)operation.OperationAttribute).HasSideEffects) ||
                (operation.Operation == DomainOperation.Invoke && ((InvokeAttribute)operation.OperationAttribute).HasSideEffects))
            {
                // For operations with side-effects i.e. with WebInvoke attribute, we need to build a default GET like
                // URI template so that, the parameter processing is taken care of by the WebHttpBehavior selector.
                WebInvokeAttribute attrib = ServiceUtils.EnsureBehavior<WebInvokeAttribute>(operationDesc);
                if (attrib.UriTemplate == null)
                {
                    attrib.UriTemplate = ODataEndpointFactory.BuildDefaultUriTemplate(operation);
                }
            }
            else
            {
                ServiceUtils.EnsureBehavior<WebGetAttribute>(operationDesc);
            }

            string action = ServiceUtils.GetRequestMessageAction(declaringContract, operationDesc.Name, null);

            // Define operation input.
            MessageDescription inputMessageDesc = new MessageDescription(action, MessageDirection.Input);
            inputMessageDesc.Body.WrapperName = operationDesc.Name;
            inputMessageDesc.Body.WrapperNamespace = ServiceUtils.DefaultNamespace;

            for (int i = 0; i < operation.Parameters.Count; i++)
            {
                DomainOperationParameter parameter = operation.Parameters[i];

                MessagePartDescription parameterPartDesc = new MessagePartDescription(parameter.Name, ServiceUtils.DefaultNamespace)
                {
                    Index = i,
                    Type = TypeUtils.GetClientType(parameter.ParameterType)
                };
                inputMessageDesc.Body.Parts.Add(parameterPartDesc);
            }

            operationDesc.Messages.Add(inputMessageDesc);

            // Define operation output.
            string responseAction = ServiceUtils.GetResponseMessageAction(declaringContract, operationDesc.Name, null);

            MessageDescription outputMessageDesc = new MessageDescription(responseAction, MessageDirection.Output);
            outputMessageDesc.Body.WrapperName = operationDesc.Name + "Response";
            outputMessageDesc.Body.WrapperNamespace = ServiceUtils.DefaultNamespace;

            if (operation.ReturnType != typeof(void))
            {
                outputMessageDesc.Body.ReturnValue = new MessagePartDescription(operationDesc.Name + "Result", ServiceUtils.DefaultNamespace)
                {
                    Type = TypeUtils.GetClientType(operation.ReturnType)
                };
            }
            operationDesc.Messages.Add(outputMessageDesc);

            return operationDesc;
        }