I am creating a web host that uses SOAPCore for the middleware. Once I build the web host, I am unsure if it is possible to add in new SOAPCore endpoints for specific paths.
Here is how I build the web host:
var webHost = new WebHostBuilder().UseKestrel(x => x.AllowSynchronousIO = true).UseUrls($"http://*:8381").UseStartup<StartupClass>().ConfigureLogging(x =>
{
x.SetMinimumLevel(LogLevel.Trace);
x.AddDebug();
x.AddConsole();
}).Build()
Here is the configure method in the StartupClass
public void Configure(IApplicationBuilder app)
{
app.UseSoapEndpoint<SoapInterface1>(options =>
{
options.Path = "/path1";
options.UseBasicAuthentication = false;
options.EncoderOptions = new[]
{
new SoapEncoderOptions
{
MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None),
WriteEncoding = Encoding.UTF8,
ReaderQuotas = XmlDictionaryReaderQuotas.Max,
}
};
options.SoapSerializer = SoapSerializer.XmlSerializer;
options.CaseInsensitivePath = true;
options.IndentXml = false;
options.OmitXmlDeclaration = true;
});
}
I have found https://gist.github.com/Tratcher/ae23d9a7b4c8c7c37d7a769ad68bd228 that shows how to add and remove ports using the kestrel config. I am wondering if there is something similar (or better) that will allow me to programmatically add in the SOAP endpoints?
Specifically, adding in something like this after the web host is built (they may or may not use the same interface):
app.UseSoapEndpoint<SoapInterface2>(options =>
{
options.Path = "/path2";
options.UseBasicAuthentication = false;
options.EncoderOptions = new[]
{
new SoapEncoderOptions
{
MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None),
WriteEncoding = Encoding.UTF8,
ReaderQuotas = XmlDictionaryReaderQuotas.Max,
}
};
options.SoapSerializer = SoapSerializer.XmlSerializer;
options.CaseInsensitivePath = true;
options.IndentXml = false;
options.OmitXmlDeclaration = true;
});
Any help would be greatly appreciated.
Related
I'm trying to extract the JWT within requests we have in our system.
When I'm running locally it works great, the code intercepting all requests...
When code runs by Azure Pipeline, no requests were intercepted, empty.
private static void GetJwtFromRequest(WebDriver driver)
{
string jwt = "";
FetchAdapter fetchAdapter = null;
if (!Requests.Any())
Requests = new List<Request>();
fetchAdapter = GetBreezeNetworkRequests(driver);
var isRequestExist = driver.GetWebDriverWait(30)
.Until(x =>
{
var temp = Requests;
return temp.Any(x => x.Headers.Any(y => y.Key == "Authorization"));
});
if (isRequestExist)
{
Request wantedRequest = Requests.First(x => x.Headers.Any(y => y.Key == "Authorization"));
jwt = wantedRequest.Headers["Authorization"].Replace("Bearer ", "");
}
UserFactory.CurrentUser.Jwt = jwt;
}
Network interception by Selenium:
public static List<Request> Requests = new List<Request>();
private static FetchAdapter GetBreezeNetworkRequests(WebDriver driver)
{
IDevTools devTools = driver.OriginDriver as IDevTools;
DevToolsSession session = devTools.GetDevToolsSession();
FetchAdapter fetchAdapter = session.GetVersionSpecificDomains<OpenQA.Selenium.DevTools.V95.DevToolsSessionDomains>().Fetch;
var enableCommandSettings = new OpenQA.Selenium.DevTools.V95.Fetch.EnableCommandSettings();
var requestPattern = new OpenQA.Selenium.DevTools.V95.Fetch.RequestPattern();
requestPattern.RequestStage = RequestStage.Request;
requestPattern.ResourceType = ResourceType.XHR;
enableCommandSettings.Patterns = new OpenQA.Selenium.DevTools.V95.Fetch.RequestPattern[] { requestPattern };
fetchAdapter.Enable(enableCommandSettings);
EventHandler<OpenQA.Selenium.DevTools.V95.Fetch.RequestPausedEventArgs> requestIntercepted = (sender, e) =>
{
Requests.Add(e.Request);
fetchAdapter.ContinueRequest(new OpenQA.Selenium.DevTools.V95.Fetch.ContinueRequestCommandSettings()
{
RequestId = e.RequestId
});
};
fetchAdapter.RequestPaused += requestIntercepted;
return fetchAdapter;
}
.netcore 3.1
chrome/edge V95
Selenium 4.0.1
Any insights?
Thanks.
I'm using grpc code-first for my blazor-wasm app and I can't understand how I should handle token expiration.
As I understand it, I need an client side interceptor that will check the expiration time and make a request to the server to update.
public static WebAssemblyHostBuilder AddGrpc(this WebAssemblyHostBuilder builder)
{
builder.Services
.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory>()
.CreateClient(BaseClient));
builder.Services.AddScoped(services =>
{
var baseAddressMessageHandler = services.GetRequiredService<AuthenticationHeaderHandler>(); // <= adds the authorization header
baseAddressMessageHandler.InnerHandler = new HttpClientHandler(); // <= I tried adding a custom handler, but it didn't work either
var grpcWebHandler = new GrpcWebHandler(GrpcWebMode.GrpcWeb, baseAddressMessageHandler);
var channel = GrpcChannel.ForAddress(builder.HostEnvironment.BaseAddress, new GrpcChannelOptions { HttpHandler = grpcWebHandler });
return channel;
});
return builder;
}
How to solve this problem correctly?
Solution:
builder.Services.AddScoped(services =>
{
var authManager = services.GetRequiredService<IAuthenticationManager>();
var navManager = services.GetRequiredService<NavigationManager>();
var credentials = CallCredentials.FromInterceptor(async (context, metadata) =>
{
try
{
await authManager.TryRefreshToken();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
navManager.NavigateTo("/login");
}
});
var baseAddressMessageHandler = services.GetRequiredService<AuthenticationHeaderHandler>();
baseAddressMessageHandler.InnerHandler = new HttpClientHandler();
var grpcWebHandler = new GrpcWebHandler(GrpcWebMode.GrpcWeb, baseAddressMessageHandler);
var channel = GrpcChannel.ForAddress(builder.HostEnvironment.BaseAddress, new GrpcChannelOptions
{
HttpHandler = grpcWebHandler,
Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
});
return channel;
});
In CallCredentials.FromInterceptor we can check token and update it.
I'm using the Saucelabs Selenium implementation to automate my testing across multiple devices and platforms.
Using the demo code from SauceLabs (below) doesn't work behind a proxy.
I've tried adding the proxy details to the DesiredCapibilities but this doesn't seem to do anything
[TestMethod]
public void TestSauceLabs()
{
DesiredCapabilities caps = new DesiredCapabilities();
caps.SetCapability("browserName", "Safari");
caps.SetCapability("platform", "macOS 10.13");
caps.SetCapability("version", "11.1");
caps.SetCapability("username", _sauceUserName);
caps.SetCapability("accessKey", _sauceAccessKey);
caps.SetCapability("name", _name);
var tags = new List<string> {"demoTest", "sauceDemo"};
caps.SetCapability("tags", tags);
caps.SetCapability("maxDuration", 3600);
caps.SetCapability("commandTimeout", 600);
caps.SetCapability("idleTimeout", 1000);
caps.SetCapability("build", "SauceDemo");
/****************************************
* Edited demo code here
* Added proxy config to DesiredCapabilities **
*/
var proxy = new Proxy
{
IsAutoDetect = false,
HttpProxy = $"{_proxyScheme}://{_proxyHost}:{_proxyPort}",
SslProxy = $"{_proxyScheme}://{_proxyHost}:{_proxyPort}",
FtpProxy = $"{_proxyScheme}://{_proxyHost}:{_proxyPort}"
};
caps.SetCapability(CapabilityType.Proxy, proxy);
/*
*****************************************/
var uri = new Uri("https://ondemand.eu-central-1.saucelabs.com/wd/hub");
_driver = new RemoteWebDriver(uri,
caps, TimeSpan.FromSeconds(600));
_javascriptExecutor = ((IJavaScriptExecutor) _driver);
_javascriptExecutor.ExecuteScript("sauce:context=Open SauceDemo.com");
_driver.Navigate().GoToUrl(_url);
_javascriptExecutor.ExecuteScript("sauce:context=Sleep for 10000ms");
Thread.Sleep(10000);
Assert.IsTrue(true);
var passed = true;
_javascriptExecutor.ExecuteScript("sauce:job-result=" + (passed ? "passed" : "failed"));
_driver?.Quit();
}
Found the solution was to use the HttpCommandExecutor when using the RemoteWebDriver behind a proxy.
Here is my example code:
[TestMethod]
public void TestSauceLabs_Chrome()
{
var remoteOptions = new Dictionary<string, object>
{
{ "username", _sauceUserName },
{ "accessKey", _sauceAccessKey },
{ "name", _name },
{ "maxDuration", 3600 },
{ "commandTimeout", 600 },
{ "idleTimeout", 1000 }
};
var options = new ChromeOptions()
{
PlatformName = "Windows 10",
BrowserVersion = "latest"
};
//Remote options need to be global
options.AddAdditionalCapability("sauce:options", remoteOptions, true);
var caps = options.ToCapabilities();
/*
Using the HttpCommandExecutor persists the proxy details
and allows you to pass in credentials if required
*/
var executor = new HttpCommandExecutor(
new Uri("https://ondemand.eu-central-1.saucelabs.com/wd/hub"),
TimeSpan.FromSeconds(600))
{
Proxy = GenerateProxy()
};
_driver = new RemoteWebDriver(executor, caps);
_javascriptExecutor = ((IJavaScriptExecutor)_driver);
_javascriptExecutor.ExecuteScript($"sauce:context=Open {_url}");
_driver.Navigate().GoToUrl(_url);
_javascriptExecutor.ExecuteScript("sauce:context=Sleep for 10000ms");
Thread.Sleep(10000);
Assert.IsTrue(true);
var passed = true;
_javascriptExecutor.ExecuteScript("sauce:job-result=" + (passed ? "passed" : "failed"));
_driver?.Quit();
}
public WebProxy GenerateProxy()
{
var proxy = new WebProxy
{
Address = new Uri($"{_proxyScheme}://{_proxyHost}:{_proxyPort}"),
BypassProxyOnLocal = false,
UseDefaultCredentials = _networkCredential != null,
Credentials = _networkCredential
};
return proxy;
}
I'm new in Ignite.net technology and trying to implement it with data persistence feature (using EF core 2.1 for my cache store classes).
I configure Ignite Configuration in this way
var cfg = new IgniteConfiguration
{
JvmDllPath = #"C:\Program Files\Java\jdk-11.0.1\bin\server\jvm.dll",
IsActiveOnStart = true,
ClientMode = false,
IgniteInstanceName = FirstValues.IgniteInstanceName,
WorkDirectory = #"C:\IGNITE_HOME\workspace",
GridName = Guid.NewGuid().ToString(),
DataStorageConfiguration = new DataStorageConfiguration()
{
DefaultDataRegionConfiguration = new DataRegionConfiguration()
{
PersistenceEnabled = true,
Name = "inMemoryRegion",
CheckpointPageBufferSize = 1024,
},
WriteThrottlingEnabled = true
},
BinaryConfiguration = new BinaryConfiguration()
{
CompactFooter = true,
KeepDeserialized = false
}
};
cfg = FirstValues.cacheConfigAll(cfg);
cfg = FirstValues.setupDiscoveryConfig(cfg);
Environment.SetEnvironmentVariable("IGNITE_H2_DEBUG_CONSOLE", "true");
var ignite = Ignition.TryGetIgnite() ?? Ignition.Start(cfg);
ignite.SetActive(true);
var s = ignite.GetCluster().ForServers().GetNodes();
ignite.GetCluster().SetBaselineTopology(s);
these two classes implemented in this way
public static IgniteConfiguration cacheConfigAll(IgniteConfiguration config)
{
CacheConfiguration cacheConfigVehicle = VehicleCacheCfgReader();
CacheConfiguration cacheConfigDevice = DeviceCacheCfgReader();
CacheConfiguration cacheConfigZone = ZoneCacheCfgReader();
CacheConfiguration cacheConfigGeoPoint = GeoPointCacheCfgReader();
List<CacheConfiguration> list = new List<CacheConfiguration>();
list.Add(cacheConfigVehicle);
list.Add(cacheConfigDevice);
list.Add(cacheConfigZone);
list.Add(cacheConfigGeoPoint);
config.CacheConfiguration = list;
return config;
}
public static IgniteConfiguration setupDiscoveryConfig(IgniteConfiguration config)
{
TcpDiscoverySpi spi = new TcpDiscoverySpi();
var ipFinder = new TcpDiscoveryMulticastIpFinder();
((TcpDiscoveryMulticastIpFinder)ipFinder).MulticastGroup = "228.10.10.157";
ipFinder.LocalAddress = "127.0.0.1";
spi.IpFinder = ipFinder;
config.DiscoverySpi = spi;
return config;
}
and here it is one of my cache stores (All of them are similar to each other)
public static CacheConfiguration VehicleCacheCfgReader()
{
return new CacheConfiguration(FmsCacheName)
{
Name = VehicleCacheName,
SqlSchema = "PUBLIC",
Backups = 1,
CacheMode = CacheMode.Partitioned,
WriteSynchronizationMode = CacheWriteSynchronizationMode.FullSync,
AtomicityMode = CacheAtomicityMode.Atomic,
WriteBehindEnabled = true,
CacheStoreFactory = new VehicleCacheStoreFactory(),
ReadThrough = true,
WriteThrough = true,
KeepBinaryInStore = false,
DataRegionName = "inMemoryRegion",
QueryEntities = new List<QueryEntity>()
{
new QueryEntity()
{
TableName = VehicleCacheName,
KeyType = typeof(string),
KeyFieldName = "Id",
ValueType = typeof(Vehicle),
Fields = new List<QueryField>() {
new QueryField("Id", typeof(string)) { IsKeyField = true },
new QueryField("Name", typeof(string)),
new QueryField("ZoneId", typeof(string))
}
}
}
};
}
and now when i'm starting my ignite I have this error
class org.apache.ignite.IgniteException: An error occurred during cache configuration loading from file [file=C:\IGNITE_HOME\workspace\db\node00-f9d2cd52-ad3e-4304-92ce-92f6585cb0a6\cache-DeviceCache1212201883355PM\cache_data.dat]
at org.
apache.ignite.internal.util.IgniteUtils.convertException(IgniteUtils.java:1025)
at org.apache.ignite.internal.processors.platform.PlatformAbstractBootstrap.start(PlatformAbstractBootstrap.java:48)
at org.apache.ignite.internal.processors.platform.PlatformIgnition.start(PlatformIgnition.java:75)
Caused by: class org.apache.ignite.IgniteCheckedException: An error occurred during cache configuration loading from file [file=C:\IGNITE_HOME\workspace\db\node00-f9d2cd52-ad3e-4304-92ce-92f6585cb0a6\cache-DeviceCache1212201883355PM\cache_data.dat]
at org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.readCacheData(FilePageStoreManager.java:843)
at org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.readCacheConfigurations(FilePageStoreManager.java:785)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.addCacheOnJoinFromConfig(GridCacheProcessor.java:888)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.startCachesOnStart(GridCacheProcessor.java:753)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.onReadyForRead(GridCacheProcessor.java:737)
at org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager.notifyMetastorageReadyForRead(GridCacheDatabaseSharedManager.java:396)
at org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager.readMetastore(GridCacheDatabaseSharedManager.java:662)
at org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager.notifyMetaStorageSubscribersOnReadyForRead(GridCacheDatabaseSharedManager.java:4610)
at org.apache.ignite.internal.IgniteKernal.start(IgniteKernal.java:1048)
at org.apache.ignite.internal.IgnitionEx$IgniteNamedInstance.start0(IgnitionEx.java:2038)
at org.apache.ignite.internal.IgnitionEx$IgniteNamedInstance.start(IgnitionEx.java:1730)
at org.apache.ignite.internal.IgnitionEx.start0(IgnitionEx.java:1158)
at org.apache.ignite.internal.IgnitionEx.start(IgnitionEx.java:656)
at org.apache.ignite.internal.processors.platform.PlatformAbstractBootstrap.start(PlatformAbstractBootstrap.java:43)
... 1 more
Caused by: class org.apache.ignite.IgniteCheckedException: Failed to deserialize object with given class loader: jdk.internal.loader.ClassLoaders$AppClassLoader#14514713
at org.apache.ignite.marshaller.jdk.JdkMarshaller.unmarshal0(JdkMarshaller.java:147)
at org.apache.ignite.marshaller.AbstractNodeNameAwareMarshaller.unmarshal(AbstractNodeNameAwareMarshaller.java:94)
at org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.readCacheData(FilePageStoreManager.java:839)
... 14 more
Caused by: java.lang.IllegalArgumentException: Ignite instance name thread local must be set or this method should be accessed under org.apache.ignite.thread.IgniteThread
at org.apache.ignite.internal.IgnitionEx.localIgnite(IgnitionEx.java:1411)
at org.apache.ignite.internal.binary.GridBinaryMarshaller.threadLocalContext(GridBinaryMarshaller.java:398)
at org.apache.ignite.internal.binary.BinaryObjectImpl.readExternal(BinaryObjectImpl.java:695)
at java.base/java.io.ObjectInputStream.readExternalData(ObjectInputStream.java:2136)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2085)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1594)
at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2355)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2249)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2087)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1594)
at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2355)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2249)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2087)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1594)
at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2355)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2249)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2087)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1594)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:430)
at org.apache.ignite.marshaller.jdk.JdkMarshaller.unmarshal0(JdkMarshaller.java:139)
My previous guess was wrong, as it seems.
There is an issue IGNITE-10451, I'm afraid it will mean you will not be able to use Cache Store together with Persistence when using Ignite.Net.
If you remove CacheStore definition on all caches and remove work dir, it will start without errors.
After some search I've decided to implement cache store mechanism by myself.
As you can see In Ignite architecture we should access to storage database when we do not have data on cache, thus I write some codes in my get functions to read data and write them on cache when its cache does not have asked data.
Assume I already have purchased a domain example.com with IP address 203.0.113.2. Using C# and the The Amazon Web Services SDK for .NET 2.0.2.2, I'd like to create a static website using a custom domain using Amazon S3 and Route 53. The manual process is described in the Amazon documentation.
When trying to create an alias, I get an exception with the message:
Invalid XML ; cvc-complex-type.2.4.a: Invalid content was found starting with element 'AliasTarget'.
One of '{"https://route53.amazonaws.com/doc/2012-12-12/":ResourceRecords}' is expected.
First, I created or updated a bucket (e.g. "example.com") in Amazon S3. If it already existed, content is deleted.
using (var client = AWSClientFactory.CreateAmazonS3Client(RegionEndpoint.USWest1))
{
if (!S3BucketExists(name, client))
{
client.PutBucket(new PutBucketRequest
{
BucketName = name,
BucketRegion = S3Region.USW1,
CannedACL = S3CannedACL.PublicRead
});
}
else
{
var request = new ListObjectsRequest
{
BucketName = name
};
var objects = client.ListObjects(request).S3Objects;
foreach (var o in objects)
{
client.DeleteObject(new DeleteObjectRequest
{
BucketName = name,
Key = o.Key
});
}
client.PutACL(new PutACLRequest
{
CannedACL = S3CannedACL.PublicRead,
BucketName = name
});
}
client.PutBucketWebsite(new PutBucketWebsiteRequest
{
BucketName = name,
WebsiteConfiguration = new WebsiteConfiguration
{
ErrorDocument = "404.html",
IndexDocumentSuffix = "index.html"
}
});
CreateObject(name, client, "index.html", "text/html", "<p>The site is under maintenance</p>");
CreateObject(name, client, "404.html", "text/html", "<p>Not Found</p>");
}
S3BucketExists returns whether a bucket exist or not, and CreateObject creates a simple page and uploads it to the bucket. Its omitted for brevity sake. I'm able to connect to the S3 hosted site without any problems.
Then I use the Route 53 API to update an existing hosted zone or create one for "example.com". All resources, except for the SOA and NS entries are deleted.
using (var client = AWSClientFactory.CreateAmazonRoute53Client())
{
var hostedZone = FindHostedZoneByName(client, domainName);
if (hostedZone != null)
{
var resourceRecordSets = client.ListResourceRecordSets(new ListResourceRecordSetsRequest
{
HostedZoneId = hostedZone.Id,
});
bool hasElements = false;
var request1 = new ChangeResourceRecordSetsRequest
{
HostedZoneId = hostedZone.Id,
ChangeBatch = new ChangeBatch
{
Changes = new List<Change>()
}
};
foreach (var resourceRecordSet in resourceRecordSets.ResourceRecordSets)
{
switch (resourceRecordSet.Type)
{
case "SOA":
case "NS":
continue;
}
var change = new Change
{
Action = "DELETE",
ResourceRecordSet = resourceRecordSet
};
request1.ChangeBatch.Changes.Add(change);
hasElements = true;
}
if (hasElements)
{
var response = client.ChangeResourceRecordSets(request1);
}
}
else
{
hostedZone = CreateHostedZone(client, domainName);
}
var hostedZoneId = hostedZone.Id;
var request = new ChangeResourceRecordSetsRequest
{
HostedZoneId = hostedZoneId,
ChangeBatch = new ChangeBatch
{
Changes = new List<Change>
{
new Change
{
Action = ChangeAction.CREATE,
ResourceRecordSet = new ResourceRecordSet
{
Name = GetQualifiedName(domainName),
Type = RRType.A,
TTL = 300,
AliasTarget = new AliasTarget()
{
HostedZoneId = "Z2F56UZL2M1ACD",
DNSName = "s3-website-us-west-1.amazonaws.com.",
},
},
},
}
}
};
client.ChangeResourceRecordSets(request);
}
The hosted zone id ("Z2F56UZL2M1ACD") and DNS names ("s3-website-us-west-1.amazonaws.com.") are public knowledge and documented on Amazon's website.
The call to ChangeResourceRecordSets throws the exception. I created an empty ResourceRecords list, with a A record of "203.0.113.2", but have not had any luck creating an alias.
That said, I can manually create the alias to the Amazon S3 site afterwards using the "Route 53 Management Console". I'm sure it's something small I'm missing.
After re-reading the documentation, it turns out that one cannot specify the TTL when specifying an alias. The following change works. Replace the code that creates an instance of ChangeResourceRecordSetsRequest to the following:
var request = new ChangeResourceRecordSetsRequest
{
HostedZoneId = hostedZoneId,
ChangeBatch = new ChangeBatch
{
Changes = new List<Change>
{
new Change
{
Action = ChangeAction.CREATE,
ResourceRecordSet = new ResourceRecordSet
{
Name = GetQualifiedName(domainName),
Type = RRType.A,
AliasTarget = new AliasTarget
{
HostedZoneId = "Z2F56UZL2M1ACD",
DNSName = "s3-website-us-west-1.amazonaws.com.",
EvaluateTargetHealth = false,
},
},
},
}
}
};
The difference was evident when the output produced by System.Net tracing was compared to the request specified in the Amazon example.