<#@ template language="C#" inherits="Generators.BaseGenerator" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.Globalization" #> <#+ // Adds the neccesary namespaces for the marshaller protected void AddCommonUsingStatements() { #> using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; using System.Xml.Serialization; using <#=this.Config.Namespace #>.Model; using Amazon.Runtime; using Amazon.Runtime.Internal; using Amazon.Runtime.Internal.Transform; using Amazon.Runtime.Internal.Util; <#+ } #> <#+ // Only applicable for rest-json and rest-xml // Generates code to add members to the header of the request // If it's a custom marshaller then it calls the custom marshaller first protected void ProcessHeaderMembers(string variableName, IEnumerable members) { foreach(var member in members) { #> if (<#=variableName#>.IsSet<#=member.PropertyName#>()) { <#+ if (member.CustomMarshallerTransformation != null) { #> request.Headers["<#=member.MarshallLocationName#>"] = <#=member.CustomMarshallerTransformation#>(<#=variableName#>.<#=member.PropertyName#>); <#+ } else if (member.IsJsonValue) { #> request.Headers["<#=member.MarshallLocationName#>"] = Convert.ToBase64String(Encoding.UTF8.GetBytes(<#=variableName#>.<#=member.PropertyName#>)); <#+ } else { if (member.IsList) { if (member.ModelShape.ModelListShape.IsString || member.ModelShape.ModelListShape.IsEnum) { #> request.Headers["<#=member.MarshallLocationName#>"] = StringUtils.FromList(<#=variableName#>.<#=member.PropertyName#>); <#+ } else { throw new InvalidDataException("[{member.ModelName}]: Marshalling lists as header values is only support for lists of strings or list of enums."); } } else if (member.IsMap) { #> //Map of headers with prefix "<#=member.MarshallLocationName#>". foreach (var kvp<#=member.PropertyName#> in <#=variableName#>.<#=member.PropertyName#>) { <#+ // Dictionary if (member.ModelShape.ValueShape.IsString) { #> request.Headers[$"<#=member.MarshallLocationName#>{kvp<#=member.PropertyName#>.Key}"] = kvp<#=member.PropertyName#>.Value; <#+ } // Dictionary> else if (member.ModelShape.ValueShape?.ListShape?.IsString == true) { #> request.Headers[$"<#=member.MarshallLocationName#>{kvp<#=member.PropertyName#>.Key}"] = string.Join(",", kvp<#=member.PropertyName#>.Value.ToArray()); <#+ } else { throw new InvalidDataException("[{member.ModelName}]: Invalid header map shapes. Header Maps must have a value of either a string or a list of strings: {member.ModelShape.ValueShape.Name}"); } #> } <#+ } else if(member.Shape.IsString) { #> request.Headers["<#=member.MarshallLocationName#>"] = <#=variableName#>.<#=member.PropertyName#>; <#+ } else { #> request.Headers["<#=member.MarshallLocationName#>"] = <#=member.PrimitiveMarshaller#>(<#=variableName#>.<#=member.PropertyName#>); <#+ } } #> } <#+ } } // Only applicable for rest-json and rest-xml // Generates code to add the operation's requestURIMembers to the PathResources request dictionary protected void ProcessUriMembers(string variableName, Operation operation) { foreach(var member in operation.RequestUriMembers) { bool isGreedy = false; var marshallLocationName = operation.GetUriResourcePathTarget(member, out isGreedy); if (member.model.Customizations.SkipUriPropertyValidations.Contains(member.PropertyName)) { if(isGreedy) { #> request.AddPathResource("<#=marshallLocationName#>", <#=variableName#>.IsSet<#=member.PropertyName#>() ? <#=member.PrimitiveMarshaller#>(<#=variableName#>.<#=member.PropertyName#>.TrimStart('/')) : string.Empty); <#+ } else { #> request.AddPathResource("<#=marshallLocationName#>", <#=variableName#>.IsSet<#=member.PropertyName#>() ? <#=member.PrimitiveMarshaller#>(<#=variableName#>.<#=member.PropertyName#>) : string.Empty); <#+ } } else { #> if (!<#=variableName#>.IsSet<#=member.PropertyName#>()) throw new <#=this.Config.BaseException#>("Request object does not have required field <#=member.PropertyName#> set"); <#+ if(isGreedy) { #> request.AddPathResource("<#=marshallLocationName#>", <#=member.PrimitiveMarshaller#>(<#=variableName#>.<#=member.PropertyName#>.TrimStart('/'))); <#+ } else { #> request.AddPathResource("<#=marshallLocationName#>", <#=member.PrimitiveMarshaller#>(<#=variableName#>.<#=member.PropertyName#>)); <#+ } } } } protected void ProcessRequestUri(Operation operation) { foreach(var staticQueryParam in operation.StaticQueryParameters) { if(staticQueryParam.Value != null) { #> request.AddSubResource("<#=staticQueryParam.Key#>", "<#=staticQueryParam.Value#>"); <#+ } else { #> request.AddSubResource("<#=staticQueryParam.Key#>"); <#+ } } } // Only applicable for rest-json and rest-xml // Generates code to add any operation query members to the query string for the request // If the marshaller is customized, it marshalls the value before changing it to a string protected void ProcessQueryStringMembers(string variableName, Operation operation) { if(operation.RequestHasQueryStringMembers) { foreach(var member in operation.RequestQueryStringMembers) { #> if (<#=variableName#>.IsSet<#=member.PropertyName#>()) <#+ if (member.CustomMarshallerTransformation != null) { #> request.Parameters.Add("<#=member.MarshallLocationName#>", <#=member.CustomMarshallerTransformation#>(<#=variableName#>.<#=member.PropertyName#>)); <#+ } else if (member.IsMap) { if(!member.Shape.ValueShape.IsString) { throw new NotImplementedException(string.Format(CultureInfo.InvariantCulture, "Marshalling map with value type of {0} as query string param is not implemented.", member.Shape.ValueShape.Type)); } #> { foreach(var kvp in <#=variableName#>.<#=member.PropertyName#>) { request.Parameters.Add(kvp.Key, kvp.Value); } } <#+ } else if (member.IsList) { if(!member.Shape.ListShape.IsString && !member.Shape.ListShape.IsDouble) { throw new NotImplementedException(string.Format(CultureInfo.InvariantCulture, "Marshalling list of {0} as query string param is not implemented.", member.Shape.ListShape.Type)); } #> request.ParameterCollection.Add("<#=member.MarshallLocationName#>", <#=variableName#>.<#=member.PropertyName#>); <#+ } else { #> request.Parameters.Add("<#=member.MarshallLocationName#>", <#=member.PrimitiveMarshaller#>(<#=variableName#>.<#=member.PropertyName#>)); <#+ } if(member.IsIdempotent) { #> else request.Parameters.Add("<#=member.MarshallLocationName#>", System.Guid.NewGuid().ToString()); <#+ } } } } // Only applicable for rest-json and rest-xml // Generates code to add the operation's hostPrefixMembers to the request's HostPrefix protected void ProcessEndpointHostPrefixMembers(string variableName, Operation operation) { if(operation.RequestHostPrefixMembers.Count() > 0) { #> var hostPrefixLabels = new { <#+ foreach(var member in operation.RequestHostPrefixMembers) { #> <#=member.PropertyName#> = <#=member.PrimitiveMarshaller#>(<#=variableName#>.<#=member.PropertyName#>), <#+ } #> }; <#+ foreach(var member in operation.RequestHostPrefixMembers) { #> if (!HostPrefixUtils.IsValidLabelValue(hostPrefixLabels.<#=member.PropertyName#>)) throw new <#=this.Config.BaseException#>("<#=member.PropertyName#> can only contain alphanumeric characters and dashes and must be between 1 and 63 characters long."); <#+ } } #> request.HostPrefix = $"<#=operation.EndpointHostPrefix.Replace("{", "{hostPrefixLabels.")#>"; <#+ } protected void GenerateRequestChecksumHandling(Operation operation, string requestContent) { // If the request has a Content-MD5 property and it's set by the user, copy the value to the header. // Otherwise the checksum handling in Core will calculate and set MD5 later. if (operation.HttpChecksumRequired) { var member = operation.RequestStructure.Members.FirstOrDefault(m => string.Equals(m.LocationName, "Content-MD5")); if (member != default(Member)) { #> if (publicRequest.IsSet<#=member.PropertyName#>()) request.Headers[Amazon.Util.HeaderKeys.ContentMD5Header] = publicRequest.<#=member.PropertyName#>; <#+ } } if (operation.RequiresChecksumDuringMarshalling) { if (!string.IsNullOrEmpty(operation.ChecksumConfiguration?.RequestAlgorithmMember)) { #> ChecksumUtils.SetRequestChecksum(request, request.<#=operation.ChecksumConfiguration.RequestAlgorithmMember#>, fallbackToMD5: <#=operation.HttpChecksumRequired.ToString().ToLower()#>); <#+ } else if (operation.HttpChecksumRequired) // no flexible checksum, just MD5 { #> ChecksumUtils.SetRequestChecksumMD5(request); <#+ } } } #>