/// <summary> /// Initializes a new instance of the <see cref="DomainServiceHost"/> class with /// the type of service and its base addresses specified. /// </summary> /// <param name="domainServiceType">The type of the <see cref="DomainService"/> to host.</param> /// <param name="baseAddresses"> /// An array of type <see cref="System.Uri"/> that contains the base addresses for /// the hosted service. /// </param> public DomainServiceHost(Type domainServiceType, params Uri[] baseAddresses) { if (domainServiceType == null) { throw new ArgumentNullException("domainServiceType"); } if (baseAddresses == null) { throw new ArgumentNullException("baseAddresses"); } EnableClientAccessAttribute att = (EnableClientAccessAttribute)TypeDescriptor.GetAttributes(domainServiceType)[typeof(EnableClientAccessAttribute)]; // Filter out all non-HTTP addresses. HashSet<string> allowedSchemes = DomainServiceHost._allowedSchemes; // Additionally filter out HTTP addresses if this DomainService requires a secure endpoint. if (att != null && att.RequiresSecureEndpoint) { allowedSchemes = DomainServiceHost._allowedSecureSchemes; } // Apply the filter. baseAddresses = baseAddresses.Where(addr => allowedSchemes.Contains(addr.Scheme)).ToArray(); this._domainServiceDescription = DomainServiceDescription.GetDescription(domainServiceType); this.InitializeDescription(domainServiceType, new UriSchemeKeyedCollection(baseAddresses)); }
/// <summary> /// Creates endpoints based on the specified description. /// </summary> /// <param name="description">The <see cref="DomainServiceDescription"/> of the <see cref="DomainService"/> to create the endpoints for.</param> /// <param name="serviceHost">The service host for which the endpoints will be created.</param> /// <returns>The endpoints that were created.</returns> public override IEnumerable<ServiceEndpoint> CreateEndpoints(DomainServiceDescription description, DomainServiceHost serviceHost) { Debug.Assert(this.Name != null, "Name has not been set."); Debug.Assert(this.domainDataServiceMetadata == null, "this.domainDataServiceMetadata == null"); if (description.Attributes[typeof(EnableClientAccessAttribute)] != null) { // The metadata object will tell us which operations we should expose for the OData end point. this.domainDataServiceMetadata = new OData.DomainDataServiceMetadata(description); // The OData endpoint doesn't expose all operations in the DomainService, but only operations with parameter and return types // which are supported by the data service. WCF doesn't allow us to create a contract without any operation. if (this.domainDataServiceMetadata.Sets.Count > 0 || this.domainDataServiceMetadata.ServiceOperations.Count > 0) { // Infer the contract from Domain service description. ContractDescription contract = this.CreateContract(description); // Make endpoints that expose the inferred contract on the given base addresses. foreach (Uri address in serviceHost.BaseAddresses) { yield return this.CreateEndpointForAddress(description, contract, address); } } } }
/// <summary> /// Creates a contract from the specified description. /// </summary> /// <param name="description">The description to create a contract from.</param> /// <returns>A <see cref="ContractDescription"/>.</returns> private ContractDescription CreateContract(DomainServiceDescription description) { Type domainServiceType = description.DomainServiceType; // PERF: We should consider just looking at [ServiceDescription] directly. ServiceDescription serviceDesc = ServiceDescription.GetService(domainServiceType); // Use names from [ServiceContract], if specified. ServiceContractAttribute sca = TypeDescriptor.GetAttributes(domainServiceType)[typeof(ServiceContractAttribute)] as ServiceContractAttribute; if (sca != null) { if (!String.IsNullOrEmpty(sca.Name)) { serviceDesc.Name = sca.Name; } if (!String.IsNullOrEmpty(sca.Namespace)) { serviceDesc.Name = sca.Namespace; } } ContractDescription contractDesc = new ContractDescription(serviceDesc.Name + this.Name, serviceDesc.Namespace) { ConfigurationName = serviceDesc.ConfigurationName + this.Name, ContractType = domainServiceType }; // Add domain service behavior which takes care of instantiating DomainServices. ServiceUtility.EnsureBehavior<DomainServiceBehavior>(contractDesc); // Load the ContractDescription from the DomainServiceDescription. ServiceUtility.LoadContractDescription(contractDesc, description); return contractDesc; }
internal static IQueryable Deserialize(DomainServiceDescription domainServiceDescription, IQueryable query, IEnumerable<ServiceQueryPart> queryParts, QueryResolver queryResolver) { foreach (ServiceQueryPart part in queryParts) { switch (part.QueryOperator) { case "where": query = DynamicQueryable.Where(query, part.Expression, queryResolver); break; case "orderby": query = DynamicQueryable.OrderBy(query, part.Expression, queryResolver); break; case "skip": query = DynamicQueryable.Skip(query, Convert.ToInt32(part.Expression, System.Globalization.CultureInfo.InvariantCulture)); break; case "take": query = DynamicQueryable.Take(query, Convert.ToInt32(part.Expression, System.Globalization.CultureInfo.InvariantCulture)); break; } } // Perform any required post processing transformations to the // expression tree Expression expr = PostProcessor.Process(domainServiceDescription, query.Expression); query = query.Provider.CreateQuery(expr); return query; }
public override void ProcessGeneratedCode(DomainServiceDescription domainServiceDescription, CodeCompileUnit codeCompileUnit, IDictionary<Type, CodeTypeDeclaration> typeMapping) { // Get a reference to the entity class CodeTypeDeclaration codeGenEntity = typeMapping[typeof(TestEntity)]; AppDomain appDomain = AppDomain.CurrentDomain; AppDomainSetup setup = appDomain.SetupInformation; string baseDir = appDomain.BaseDirectory; codeGenEntity.Comments.Add(new CodeCommentStatement("[CodeProcessor] BaseDirectory:" + baseDir)); Configuration cfg = WebConfigurationManager.OpenWebConfiguration(null); AuthenticationSection authSection = (AuthenticationSection)cfg.GetSection("system.web/authentication"); FormsAuthenticationConfiguration formsAuth = authSection.Forms; if (formsAuth != null) { codeGenEntity.Comments.Add(new CodeCommentStatement("[CodeProcessor] Authentication:forms")); } ConnectionStringsSection connSect = cfg.ConnectionStrings; if (connSect != null) { ConnectionStringSettingsCollection connColl = connSect.ConnectionStrings; foreach (ConnectionStringSettings connSetting in connColl) { codeGenEntity.Comments.Add(new CodeCommentStatement("[CodeProcessor] ConnectionString:" + connSetting.ConnectionString)); } } }
/// <summary> /// Generates complex object code. /// </summary> /// <param name="complexObjectType">Type of the complex object for which the proxy is to be generates.</param> /// <param name="domainServiceDescription">The DomainServiceDescription for the domain service associated with this complex type.</param> /// <param name="clientCodeGenerator">ClientCodeGenerator object for this instance.</param> /// <returns>The generated complex object code.</returns> public string Generate(Type complexObjectType, DomainServiceDescription domainServiceDescription, ClientCodeGenerator clientCodeGenerator) { this.Type = complexObjectType; this.ClientCodeGenerator = clientCodeGenerator; this.DomainServiceDescription = domainServiceDescription; return this.GenerateDataContractProxy(); }
private PostProcessor(DomainServiceDescription domainServiceDescription) { if (domainServiceDescription == null) { throw new ArgumentNullException("domainServiceDescription"); } this.domainServiceDescription = domainServiceDescription; }
/// <summary> /// Creates endpoints based on the specified description. /// </summary> /// <param name="description">The <see cref="DomainServiceDescription"/> of the <see cref="DomainService"/> to create the endpoints for.</param> /// <param name="serviceHost">The service host for which the endpoints will be created.</param> /// <returns>The endpoints that were created.</returns> public override IEnumerable<ServiceEndpoint> CreateEndpoints(DomainServiceDescription description, DomainServiceHost serviceHost) { ContractDescription contract = this.CreateContract(description); List<ServiceEndpoint> endpoints = new List<ServiceEndpoint>(); foreach (Uri address in serviceHost.BaseAddresses) { endpoints.Add(this.CreateEndpointForAddress(contract, address)); } return endpoints; }
/// <summary> /// Creates endpoints based on the specified description. /// </summary> /// <param name="description">The <see cref="DomainServiceDescription"/> of the <see cref="DomainService"/> to create the endpoints for.</param> /// <param name="serviceHost">The service host for which the endpoints will be created.</param> /// <returns>The endpoints that were created.</returns> public override IEnumerable<ServiceEndpoint> CreateEndpoints(DomainServiceDescription description, DomainServiceHost serviceHost) { ContractDescription contract = this.CreateContract(description); contract.Behaviors.Add(new ServiceMetadataContractBehavior() { MetadataGenerationDisabled = true }); List<ServiceEndpoint> endpoints = new List<ServiceEndpoint>(); foreach (Uri address in serviceHost.BaseAddresses) { endpoints.Add(this.CreateEndpointForAddress(contract, address)); } return endpoints; }
public static void GenerateEntitiesMetadataJsonMap(DomainServiceDescription description) { foreach (Type entityType in description.EntityTypes) { entitiesMetadata.Add(new TypeMetadata(entityType)); } foreach (Type complexType in description.ComplexTypes) { entitiesMetadata.Add(new TypeMetadata(complexType)); } }
/// <summary> /// Constructs a description based on the specified <see cref="DomainServiceDescription"/>. /// </summary> /// <param name="baseDescription">The base <see cref="DomainServiceDescription"/></param> internal DomainServiceDescription(DomainServiceDescription baseDescription) { if (baseDescription == null) { throw new ArgumentNullException("baseDescription"); } this._domainServiceType = baseDescription._domainServiceType; this._attributes = baseDescription._attributes; this._operationEntries.AddRange(baseDescription._operationEntries); }
/// <summary> /// Creates a set of WCF REST service endpoints in the <see cref="OpenRiaServices.DomainServices.Hosting.DomainServiceHost"/> which /// expose traces of WCF services in the ATOM, XML, or HTML format. One WCF REST endpoint is added for each HTTP or HTTPS base address from the specified serviceHost. /// The address of the endpoint is obtained by appending the name of the TracingDomainServiceEndpointFactory as specified in the domainServices section of the configuration file /// to the base address. Furthermore, the UriTemplate of each of the endpoints is specified by the <see cref="WcfTraceService"/> service contract and allows for selection of the /// response contract between ATOM, XML, or HTML. /// </summary> /// <param name="description">WCF RIA service description.</param> /// <param name="serviceHost">Service host to which endpoints will be added.</param> /// <returns>The collection of endpoints.</returns> public override IEnumerable<ServiceEndpoint> CreateEndpoints(DomainServiceDescription description, DomainServiceHost serviceHost) { if (serviceHost == null) { throw new ArgumentNullException("serviceHost"); } if (this.Parameters["maxEntries"] != null) { int maxEntries; if (int.TryParse(this.Parameters["maxEntries"], out maxEntries)) { InMemoryTraceListener.MaxEntries = maxEntries; } else { throw new InvalidOperationException(Resx.MaxEntriesAttributeMustBeAPositiveInteger); } } ContractDescription contract = ContractDescription.GetContract(typeof(WcfTraceService)); contract.Behaviors.Add(new ServiceMetadataContractBehavior { MetadataGenerationDisabled = true }); List<ServiceEndpoint> tracingEndpoints = new List<ServiceEndpoint>(); foreach (Uri baseAddress in serviceHost.BaseAddresses) { WebHttpBinding binding = new WebHttpBinding(); if (baseAddress.Scheme.Equals(Uri.UriSchemeHttps)) { binding.Security.Mode = WebHttpSecurityMode.Transport; } else if (!baseAddress.Scheme.Equals(Uri.UriSchemeHttp)) { continue; } ServiceEndpoint endpoint = new ServiceEndpoint(contract, binding, new EndpointAddress(baseAddress.OriginalString + "/" + this.Name)); endpoint.Behaviors.Add(new WebHttpBehavior()); endpoint.Behaviors.Add(new TracingEndpointBehavior { ServiceHost = serviceHost }); tracingEndpoints.Add(endpoint); } return tracingEndpoints; }
public OperationContext(DomainServiceContext domainServiceContext, DomainService domainService, DomainServiceDescription domainServiceDescription) { if (domainServiceContext == null) { throw new ArgumentNullException("domainServiceContext"); } if (domainService == null) { throw new ArgumentNullException("domainService"); } if (domainServiceDescription == null) { throw new ArgumentNullException("domainServiceDescription"); } this._domainServiceContext = domainServiceContext; this._domainService = domainService; this._domainServiceDescription = domainServiceDescription; }
/// <summary> /// Creates a contract description for the domain data service endpoint based on the domain service description. /// </summary> /// <param name="description">Domain data service description.</param> /// <returns>Contract description for the domain data service endpoint.</returns> private ContractDescription CreateContract(DomainServiceDescription description) { Type domainServiceType = description.DomainServiceType; ServiceDescription serviceDesc = ServiceDescription.GetService(domainServiceType); // Use names from [ServiceContract], if specified. ServiceContractAttribute sca = TypeDescriptor.GetAttributes(domainServiceType)[typeof(ServiceContractAttribute)] as ServiceContractAttribute; if (sca != null) { if (!String.IsNullOrEmpty(sca.Name)) { serviceDesc.Name = sca.Name; } if (!String.IsNullOrEmpty(sca.Namespace)) { serviceDesc.Name = sca.Namespace; } } ContractDescription contractDesc = new ContractDescription(serviceDesc.Name + this.Name, serviceDesc.Namespace) { ConfigurationName = serviceDesc.ConfigurationName + this.Name, ContractType = domainServiceType }; // Disable metadata generation for the domain data service contract. contractDesc.Behaviors.Add(new ServiceMetadataContractBehavior(true)); // Add domain service behavior which takes care of instantiating DomainServices. ServiceUtils.EnsureBehavior<DomainDataServiceContractBehavior>(contractDesc); // Load the ContractDescription from the DomainServiceDescription. this.LoadContractDescription(contractDesc, description); return contractDesc; }
/// <summary> /// Creates an endpoint based on the specified address. /// </summary> /// <param name="domainServiceDescription">Domain service description from which the <paramref name="contract"/> was inferred.</param> /// <param name="contract">The endpoint's contract.</param> /// <param name="address">The endpoint's base address.</param> /// <returns>An endpoint.</returns> private ServiceEndpoint CreateEndpointForAddress(DomainServiceDescription domainServiceDescription, ContractDescription contract, Uri address) { WebHttpBinding binding = new WebHttpBinding(); binding.MaxReceivedMessageSize = Int32.MaxValue; ServiceUtils.SetReaderQuotas(binding.ReaderQuotas); if (address.Scheme.Equals(Uri.UriSchemeHttps)) { binding.Security.Mode = WebHttpSecurityMode.Transport; } else if (ServiceUtils.CredentialType != HttpClientCredentialType.None) { binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly; } if (ServiceUtils.CredentialType != HttpClientCredentialType.None) { binding.Security.Transport.ClientCredentialType = ServiceUtils.CredentialType; } ServiceEndpoint ep = new ServiceEndpoint(contract, binding, new EndpointAddress(address.OriginalString + "/" + this.Name)); // Data service end point has data service behavior. ep.Behaviors.Add(new DomainDataServiceEndpointBehavior() { DomainDataServiceMetadata = this.domainDataServiceMetadata, DefaultBodyStyle = WebMessageBodyStyle.Wrapped }); return ep; }
/// <summary> /// Geterates the DomainContext class. /// </summary> /// <param name="domainServiceDescription">DomainServcieDescription for the domain service for which the proxy is to be generated.</param> /// <param name="clientCodeGenerator">ClientCodeGenerator object for this instance.</param> /// <returns>The generated DomainContext class code.</returns> public string Generate(DomainServiceDescription domainServiceDescription, ClientCodeGenerator clientCodeGenerator) { this.DomainServiceDescription = domainServiceDescription; this.ClientCodeGenerator = clientCodeGenerator; return this.GenerateDomainContextClass(); }
internal static string GetDomainContextTypeName(DomainServiceDescription domainServiceDescription) { string domainContextTypeName = domainServiceDescription.DomainServiceType.Name; if (domainContextTypeName.EndsWith("Service", StringComparison.Ordinal)) { domainContextTypeName = domainContextTypeName.Substring(0, domainContextTypeName.Length - 7 /* "Service".Length */) + "Context"; } return domainContextTypeName; }
internal CodeMemberShareKind GetDomainContextTypeShareKind(DomainServiceDescription domainServiceDescription) { Type domainServiceType = domainServiceDescription.DomainServiceType; string domainContextTypeName = DomainContextGenerator.GetDomainContextTypeName(domainServiceDescription); string fullTypeName = domainServiceType.Namespace + "." + domainContextTypeName; CodeMemberShareKind shareKind = this._codeGenerationHost.GetTypeShareKind(fullTypeName); return shareKind; }
private void GenerateComplexObjectsIfNotGenerated(DomainServiceDescription dsd, List<Type> generatedComplexObjects) { foreach (Type t in dsd.ComplexTypes.OrderBy(e => e.Name)) { if (generatedComplexObjects.Contains(t)) { continue; } CodeMemberShareKind typeShareKind = this.GetTypeShareKind(t); if ((typeShareKind & CodeMemberShareKind.SharedByReference) != 0) { this.CodeGenerationHost.LogError(string.Format(CultureInfo.CurrentCulture, "Type already shared", t)); continue; } generatedComplexObjects.Add(t); this.Write(this.ComplexObjectGenerator.Generate(t, dsd, this)); } }
/// <summary> /// See <see cref="CodeProcessor.ProcessGeneratedCode"/>. /// </summary> /// <param name="domainServiceDescription">The domainServiceDescription</param> /// <param name="codeCompileUnit">The codeCompileUnit</param> /// <param name="typeMapping">The typeMapping</param> public override void ProcessGeneratedCode(DomainServiceDescription domainServiceDescription, CodeCompileUnit codeCompileUnit, IDictionary<Type, CodeTypeDeclaration> typeMapping) { // Make sure the provider extends IAuthentication<T> Type genericDomainServiceType; AuthenticationCodeProcessor.CheckIAuthentication(domainServiceDescription, out genericDomainServiceType); Type userEntityType = genericDomainServiceType.GetGenericArguments()[0]; AuthenticationCodeProcessor.CheckIUser(userEntityType); // Implement IPrincipal and IIdentity in the user type CodeTypeDeclaration entityTypeDeclaration; typeMapping.TryGetValue(userEntityType, out entityTypeDeclaration); if (entityTypeDeclaration != null) { CodeTypeReference identityInterfaceTypeReference = new CodeTypeReference(typeof(IIdentity)) { Options = CodeTypeReferenceOptions.GlobalReference }; CodeTypeReference principalInterfaceTypeReference = new CodeTypeReference(typeof(IPrincipal)) { Options = CodeTypeReferenceOptions.GlobalReference }; entityTypeDeclaration.BaseTypes.Add(identityInterfaceTypeReference); entityTypeDeclaration.BaseTypes.Add(principalInterfaceTypeReference); //// //// private string IIdentitiy.AuthenticationType //// CodeMemberProperty authenticationTypeProperty = new CodeMemberProperty() { Attributes = MemberAttributes.Private | MemberAttributes.Final, HasGet = true, Name = "AuthenticationType", Type = new CodeTypeReference(typeof(string)) }; // get { return string.Empty; } authenticationTypeProperty.GetStatements.Add(new CodeMethodReturnStatement( new CodePropertyReferenceExpression( new CodeTypeReferenceExpression(typeof(string)), "Empty"))); authenticationTypeProperty.PrivateImplementationType = identityInterfaceTypeReference; entityTypeDeclaration.Members.Add(authenticationTypeProperty); //// //// public bool IsAuthenticated //// CodeMemberProperty isAuthenticatedProperty = new CodeMemberProperty() { Attributes = MemberAttributes.Public | MemberAttributes.Final, HasGet = true, Name = "IsAuthenticated", Type = new CodeTypeReference(typeof(bool)) }; // get { return (true != string.IsNullOrEmpty(this.Name)); } isAuthenticatedProperty.GetStatements.Add( new CodeMethodReturnStatement( new CodeBinaryOperatorExpression( new CodePrimitiveExpression(true), CodeBinaryOperatorType.IdentityInequality, new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(typeof(string)), "IsNullOrEmpty", new CodePropertyReferenceExpression( new CodeThisReferenceExpression(), "Name"))))); isAuthenticatedProperty.Comments.AddRange( AuthenticationCodeProcessor.GetDocComments(Resources.ApplicationServices_CommentIsAuth)); isAuthenticatedProperty.ImplementationTypes.Add(identityInterfaceTypeReference); entityTypeDeclaration.Members.Add(isAuthenticatedProperty); //// //// private string IIdentity.Name //// // VB Codegen requires us to implement a ReadOnly version of Name as well CodeMemberProperty namePropertyExp = new CodeMemberProperty() { Attributes = MemberAttributes.Private | MemberAttributes.Final, HasGet = true, Name = "Name", Type = new CodeTypeReference(typeof(string)) }; // get { return this.Name; } namePropertyExp.GetStatements.Add( new CodeMethodReturnStatement( new CodePropertyReferenceExpression( new CodeThisReferenceExpression(), "Name"))); namePropertyExp.PrivateImplementationType = identityInterfaceTypeReference; entityTypeDeclaration.Members.Add(namePropertyExp); //// //// private IIdentity IPrincipal.Identity //// CodeMemberProperty identityProperty = new CodeMemberProperty() { Attributes = MemberAttributes.Private | MemberAttributes.Final, HasGet = true, Name = "Identity", Type = identityInterfaceTypeReference, }; // get { return this; } identityProperty.GetStatements.Add( new CodeMethodReturnStatement( new CodeThisReferenceExpression())); identityProperty.PrivateImplementationType = principalInterfaceTypeReference; entityTypeDeclaration.Members.Add(identityProperty); //// //// public bool IsInRole(string role) //// CodeMemberMethod isInRoleMethod = new CodeMemberMethod() { Attributes = MemberAttributes.Public | MemberAttributes.Final, Name = "IsInRole", ReturnType = new CodeTypeReference(typeof(bool)) }; isInRoleMethod.Parameters.Add( new CodeParameterDeclarationExpression( new CodeTypeReference(typeof(string)), "role")); // if (this.Roles == null) // { // return false; // } // return this.Roles.Contains(role); CodeConditionStatement ifRolesNullStatement = new CodeConditionStatement(); ifRolesNullStatement.Condition = new CodeBinaryOperatorExpression( new CodePropertyReferenceExpression( new CodeThisReferenceExpression(), "Roles"), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null)); ifRolesNullStatement.TrueStatements.Add( new CodeMethodReturnStatement(new CodePrimitiveExpression(false))); isInRoleMethod.Statements.Add(ifRolesNullStatement); isInRoleMethod.Statements.Add( new CodeMethodReturnStatement( new CodeMethodInvokeExpression( new CodeTypeReferenceExpression( new CodeTypeReference(typeof(Enumerable)) { Options = CodeTypeReferenceOptions.GlobalReference }), "Contains", new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Roles"), new CodeVariableReferenceExpression("role")))); isInRoleMethod.Comments.AddRange( AuthenticationCodeProcessor.GetDocComments(Resources.ApplicationServices_CommentIsInRole)); isInRoleMethod.ImplementationTypes.Add(principalInterfaceTypeReference); entityTypeDeclaration.Members.Add(isInRoleMethod); // Changes to Name need to raise change notification for IsAuthenticated. To accomplish this, // we'll insert a change event at the end of the "if (this._name != value)" block. // // >> this.RaisePropertyChanged("IsAuthenticated"); CodeMemberProperty nameProperty = entityTypeDeclaration.Members.OfType<CodeMemberProperty>().Where(c => c.Name == "Name").First(); nameProperty.SetStatements.OfType<CodeConditionStatement>().First().TrueStatements.Add( new CodeExpressionStatement( new CodeMethodInvokeExpression( new CodeThisReferenceExpression(), "RaisePropertyChanged", new CodePrimitiveExpression("IsAuthenticated")))); // Name should be set to string.Empty by default CodeMemberField nameField = entityTypeDeclaration.Members.OfType<CodeMemberField>().Where(c => c.Name == "_name").Single(); nameField.InitExpression = new CodePropertyReferenceExpression( new CodeTypeReferenceExpression(typeof(string)), "Empty"); } // Set context base type CodeTypeDeclaration providerTypeDeclaration; typeMapping.TryGetValue(domainServiceDescription.DomainServiceType, out providerTypeDeclaration); if (providerTypeDeclaration != null) { providerTypeDeclaration.BaseTypes.Clear(); providerTypeDeclaration.BaseTypes.Add( new CodeTypeReference(AuthenticationCodeProcessor.AuthenticationDomainContextBaseName) { Options = CodeTypeReferenceOptions.GlobalReference }); } }
private static bool IsValidMethodSignature(DomainServiceDescription description, DomainOperationEntry operationEntry, DomainOperation operation, out Exception error) { string methodName = operationEntry.Name; ReadOnlyCollection<DomainOperationParameter> parameters = operationEntry.Parameters; Type returnType = operationEntry.ReturnType; switch (operation) { case DomainOperation.Delete: case DomainOperation.Insert: case DomainOperation.Update: { // insert signature check: parameter length must be 1 if (parameters.Count != 1) { error = new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.InvalidInsertUpdateDeleteMethod_IncorrectParameterLength, methodName)); return false; } // parameter must be by-value if (!IsByVal(parameters[0])) { error = new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.InvalidDomainOperationEntry_ParamMustBeByVal, methodName, parameters[0].Name)); return false; } if (!description._entityTypes.Contains(parameters[0].ParameterType)) { error = new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.InvalidDomainMethod_ParamMustBeEntity, parameters[0].Name, methodName)); return false; } break; } case DomainOperation.Query: { // Ignore the optional "out count" parameter. IEnumerable<DomainOperationParameter> queryParameters = parameters; DomainOperationParameter lastParameter = queryParameters.LastOrDefault(); if (lastParameter != null && lastParameter.IsOut) { queryParameters = queryParameters.Take(queryParameters.Count() - 1).ToArray(); } foreach (DomainOperationParameter param in queryParameters) { if (!TypeUtility.IsPredefinedType(param.ParameterType)) { error = new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.InvalidDomainOperationEntry_ParamMustBeSimple, methodName, param.Name)); return false; } } // Determine the entity Type and validate the return type // (must return IEnumerable<T> or a singleton) bool isSingleton = false; Type entityType = DomainServiceDescription.GetQueryEntityReturnType(operationEntry, out isSingleton, out error); if (error != null) { return false; } // validate the entity Type if (entityType == null || !description._entityTypes.Contains(entityType)) { string errorMessage; if (!IsValidEntityType(entityType, out errorMessage)) { error = new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.Invalid_Entity_Type, entityType.Name, errorMessage)); return false; } } // Only IEnumerable<T> returning query methods can be marked composable if (isSingleton && ((QueryAttribute)operationEntry.OperationAttribute).IsComposable) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.DomainServiceDescription_SingletonQueryMethodCannotCompose, methodName, returnType)); } break; } case DomainOperation.Custom: { // check that the method signature is conforming to our expectations (Entity, one or more of pre-defined types) if (parameters.Count == 0) { error = new InvalidOperationException(Resource.InvalidCustomMethod_MethodCannotBeParameterless); return false; } bool first = true; foreach (DomainOperationParameter param in parameters) { if (first) { // if first parameter, ensure that its type is one of the Entity types associated with CRUD. if (!description._entityTypes.Contains(param.ParameterType)) { error = new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.InvalidDomainMethod_ParamMustBeEntity, param.Name, methodName)); return false; } first = false; } else if (!TypeUtility.IsPredefinedType(param.ParameterType) && !TypeUtility.IsSupportedComplexType(param.ParameterType)) { error = new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.InvalidDomainOperationEntry_ParamMustBeSimple, methodName, param.Name)); return false; } } break; } case DomainOperation.Invoke: { foreach (DomainOperationParameter param in parameters) { // parameter Type must be one of the predefined types, a supported complex type, an entity or collection of entities if (!description._entityTypes.Contains(param.ParameterType) && !TypeUtility.IsPredefinedType(param.ParameterType) && !TypeUtility.IsSupportedComplexType(param.ParameterType)) { // see if the parameter type is a supported collection of entities Type elementType = TypeUtility.GetElementType(param.ParameterType); bool isEntityCollection = description._entityTypes.Contains(elementType) && TypeUtility.IsSupportedCollectionType(param.ParameterType); if (!isEntityCollection) { error = new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.InvalidInvokeOperation_ParameterType, methodName)); return false; } } } // return Type must be one of the predefined types, an entity or collection of entities if (returnType != typeof(void) && !description._entityTypes.Contains(returnType) && !TypeUtility.IsPredefinedType(returnType) && !TypeUtility.IsSupportedComplexType(returnType)) { // see if the return is a supported collection of entities Type elementType = TypeUtility.GetElementType(returnType); bool isEntityCollection = description._entityTypes.Contains(elementType) && TypeUtility.IsSupportedCollectionType(returnType); if (!isEntityCollection) { error = new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.InvalidInvokeOperation_ReturnType, methodName)); return false; } } break; } } if (operation != DomainOperation.Invoke && operation != DomainOperation.Query) { // return type should be void for other domain operations except invoke operations if (returnType != typeof(void) || operationEntry.IsTaskAsync) { error = new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.InvalidDomainOperationEntry_NonQueryMustReturnVoid, methodName)); return false; } } error = null; return true; }
private static void ValidateMethodSignature(DomainServiceDescription description, DomainOperationEntry method) { Exception error; if (!IsValidMethodSignature(description, method, method.Operation, out error)) { throw error; } }
/// <summary> /// Populates a contract description from a domain service description. /// </summary> /// <param name="contractDesc">Contract description to populate.</param> /// <param name="domainServiceDescription">Domain service description.</param> private void LoadContractDescription(ContractDescription contractDesc, DomainServiceDescription domainServiceDescription) { OperationDescription operationDesc; Debug.Assert(this.domainDataServiceMetadata != null, "this.domainDataServiceMetadata != null"); // Create contract operations by inferring them from the [Query] & [Invoke] methods on the domain service. foreach (DomainOperationEntry operation in domainServiceDescription.DomainOperationEntries) { if (this.domainDataServiceMetadata.Sets.ContainsKey(operation.Name) || this.domainDataServiceMetadata.ServiceOperations.ContainsKey(operation.Name)) { switch (operation.Operation) { case DomainOperation.Query: operationDesc = ODataEndpointFactory.CreateQueryOperationDescription(contractDesc, operation); Type queryOperationType = typeof(DomainDataServiceQueryOperationBehavior<>).MakeGenericType(operation.AssociatedType); // Add as first behavior such that our operation invoker is the first in the chain. operationDesc.Behaviors.Insert(0, (IOperationBehavior)Activator.CreateInstance(queryOperationType, operation)); contractDesc.Operations.Add(operationDesc); break; case DomainOperation.Invoke: operationDesc = ODataEndpointFactory.CreateOperationDescription(contractDesc, operation); // Add as first behavior such that our operation invoker is the first in the chain. operationDesc.Behaviors.Insert(0, new DomainDataServiceInvokeOperationBehavior(operation)); contractDesc.Operations.Add(operationDesc); break; default: break; } } } }
/// <summary> /// Default constructor. /// </summary> /// <param name="description">A description of the <see cref="DomainService"/> this type creates surrogates for.</param> /// <param name="exposedTypeToSurrogateMap"> /// The map of known exposed types to surrogate types. This object is passed in externally for efficiency reasons. Its /// contents won't change; the set is owned by this type. /// </param> /// <param name="surrogateTypes"> /// The set of known surrogate types. This object is passed in externally for efficiency reasons. Its contents /// won't change; the set is owned by this type. /// </param> public DomainServiceSerializationSurrogate(DomainServiceDescription description, Dictionary<Type, Tuple<Type, Func<object, object>>> exposedTypeToSurrogateMap, HashSet<Type> surrogateTypes) { this.description = description; this.exposedTypeToSurrogateMap = exposedTypeToSurrogateMap; this.surrogateTypes = surrogateTypes; }
/// <summary> /// Initializes a new instance of the <see cref="ComplexTypeProxyGenerator"/> class. /// </summary> /// <param name="proxyGenerator">The client proxy generator against which this will generate code. Cannot be null.</param> /// <param name="complexType">The complex type. Cannot be null.</param> /// <param name="domainServiceDescription"><see cref="DomainServiceDescription"/> that exposes this complex type.</param> /// <param name="typeMapping">A dictionary of <see cref="DomainService"/> and related complex types that maps to their corresponding client-side <see cref="CodeTypeReference"/> representations.</param> public ComplexTypeProxyGenerator(CodeDomClientCodeGenerator proxyGenerator, Type complexType, DomainServiceDescription domainServiceDescription, IDictionary<Type, CodeTypeDeclaration> typeMapping) : base(proxyGenerator, complexType, typeMapping) { this._domainServiceDescription = domainServiceDescription; }
/// <summary> /// Validates that the authentication service implements the <see cref="IAuthentication{T}"/> interface /// naturally for use in codegen. /// </summary> /// <remarks> /// This check ensures no part of the interface was implemented explicitly. /// </remarks> /// <param name="authenticationServiceDescription">The domain service description for the type that implemented /// the <see cref="IAuthentication{T}"/> interface. /// </param> /// <param name="genericIAuthenticationType">The generic version of <see cref="IAuthentication{T}"/> implemented /// by the service type of the <paramref name="authenticationServiceDescription"/>. /// </param> /// <exception cref="InvalidOperationException"> is thrown if the <see cref="IAuthentication{T}"/> interface /// is not correctly implemented. /// </exception> private static void CheckIAuthentication(DomainServiceDescription authenticationServiceDescription, out Type genericIAuthenticationType) { bool implementsLogin = false; bool implementsLogout = false; bool implementsGetUser = false; bool implementsUpdateUser = false; if (!typeof(IAuthentication<>).DefinitionIsAssignableFrom(authenticationServiceDescription.DomainServiceType, out genericIAuthenticationType)) { throw new InvalidOperationException(Resources.ApplicationServices_MustBeIAuth); } Type userType = genericIAuthenticationType.GetGenericArguments()[0]; foreach (DomainOperationEntry doe in authenticationServiceDescription.DomainOperationEntries) { switch (doe.Name) { case "Login": implementsLogin = AuthenticationCodeProcessor.CheckIAuthenticationLogin(doe, userType); break; case "Logout": implementsLogout = AuthenticationCodeProcessor.CheckIAuthenticationLogout(doe, userType); break; case "GetUser": implementsGetUser = AuthenticationCodeProcessor.CheckIAuthenticationGetUser(doe, userType); break; case "UpdateUser": implementsUpdateUser = AuthenticationCodeProcessor.CheckIAuthenticationUpdateUser(doe, userType); break; default: break; } } if (!implementsLogin || !implementsLogout || !implementsGetUser || !implementsUpdateUser) { throw new InvalidOperationException(string.Format( CultureInfo.InstalledUICulture, Resources.ApplicationServices_MustBeIAuthImpl, authenticationServiceDescription.DomainServiceType.Name)); } }
public override void ProcessGeneratedCode(DomainServiceDescription domainServiceDescription, CodeCompileUnit codeCompileUnit, IDictionary<Type, CodeTypeDeclaration> typeMapping) { return; }
public virtual void GenerateDomainContextClass(DomainServiceDescription domainServiceDescription) { #line default #line hidden #line 5 "c:\dd\Alex_AppFx\AppFx\RiaServices\Main\OpenRiaServices.DomainServices.Tools\Test\T4DomainServiceCodeGenerator\DomainContext.ttinclude" this.Write("namespace "); #line default #line hidden #line 6 "c:\dd\Alex_AppFx\AppFx\RiaServices\Main\OpenRiaServices.DomainServices.Tools\Test\T4DomainServiceCodeGenerator\DomainContext.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(domainServiceDescription.DomainServiceType.Namespace)); #line default #line hidden #line 6 "c:\dd\Alex_AppFx\AppFx\RiaServices\Main\OpenRiaServices.DomainServices.Tools\Test\T4DomainServiceCodeGenerator\DomainContext.ttinclude" this.Write("\r\n{\r\n using System;\r\n using System.Collections.Generic;\r\n using System.C" + "omponentModel;\r\n using System.ComponentModel.DataAnnotations;\r\n using Syst" + "em.Data;\r\n using System.Linq;\r\n\r\n public class "); #line default #line hidden #line 15 "c:\dd\Alex_AppFx\AppFx\RiaServices\Main\OpenRiaServices.DomainServices.Tools\Test\T4DomainServiceCodeGenerator\DomainContext.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(domainServiceDescription.DomainServiceType.Name)); #line default #line hidden #line 15 "c:\dd\Alex_AppFx\AppFx\RiaServices\Main\OpenRiaServices.DomainServices.Tools\Test\T4DomainServiceCodeGenerator\DomainContext.ttinclude" this.Write("Context : DomainContext\r\n {\r\n }\r\n}\r\n"); #line default #line hidden #line 19 "c:\dd\Alex_AppFx\AppFx\RiaServices\Main\OpenRiaServices.DomainServices.Tools\Test\T4DomainServiceCodeGenerator\DomainContext.ttinclude" }
/// <summary> /// Initializes a new instance of the <see cref="DomainOperationEntryProxyGenerator"/> class. /// </summary> /// <param name="clientProxyGenerator">The client proxy generator against which this will generate code. Cannot be null.</param> /// <param name="proxyClass">The class into which to inject the generated code</param> /// <param name="domainServiceDescription">The description for the DomainService we're generating for</param> public DomainOperationEntryProxyGenerator(CodeDomClientCodeGenerator clientProxyGenerator, CodeTypeDeclaration proxyClass, DomainServiceDescription domainServiceDescription) : base(clientProxyGenerator) { this._proxyClass = proxyClass; this._domainServiceDescription = domainServiceDescription; }
/// <summary> /// Factory method used to create <see cref="DomainServiceDescription"/> based on the specified description. /// </summary> /// <param name="baseDescription">The base description.</param> /// <returns>A new description based on the base description.</returns> protected DomainServiceDescription CreateDescription(DomainServiceDescription baseDescription) { if (baseDescription == null) { throw new ArgumentNullException("baseDescription"); } return new DomainServiceDescription(baseDescription); }