Embedded power bi report export to pdf - c#

I am trying to export embedded report as pdf format.I can download the report without pagination now I am trying to download thr first page of the report which is returning Badrequest response from the ExportToFileInGroupAsync() API.
The report which I test one is not have any RLS roles.
public async Task<FileModel> ExportPaginatedReport(string Token, Guid WorkspaceId, Guid ReportId, string ExportName, FileFormat ExportFileFormat, string userName, string OutputFormat = "pdf", List<ParameterValue> Parameters = null)
{
FileModel fileModel = new FileModel();
var embededParams = await GetEmbedParams(WorkspaceId, ReportId, ReportAccessLevel.View, null, null);
using (var pbiClient = await GetPowerBiClient())
{
var report = await pbiClient.Reports.GetReportInGroupAsync(WorkspaceId, ReportId);
var exportRequest = new ExportReportRequest
{
Format = ExportFileFormat,
PaginatedReportConfiguration = new
PaginatedReportExportConfiguration
{
ParameterValues = new List<ParameterValue>() { },
FormatSettings = new Dictionary<string, string>() {
{"StartPage", "1" },
{"EndPage","1"}
},
Identities = new List<EffectiveIdentity>()
{
new EffectiveIdentity
{
//IdentityBlob = new IdentityBlob {
// Value = embededParams.EmbedToken.Token
// },
Username = _embeddedAnalyticsConfig.Username,
Datasets = new List<string> { report.DatasetId },
Roles = null
},
}
}
};
if (Parameters != null)
{
exportRequest.PaginatedReportConfiguration.ParameterValues = Parameters;
}
Export export = await pbiClient.Reports.ExportToFileInGroupAsync(WorkspaceId, ReportId, exportRequest);
///Rest of polling and export codes
}
}
Error: Operation returned an invalid status code 'BadRequest
Note - The same report I can download without the Pagination, at that time I used the PowerBIReportExportConfiguration object in ExportRequest

Related

Is it possible to send AdaptiveTextBlock placeholder value as parameter list to web api call

Within a bot,we have an adaptive card where the user has a choice to select yes or no.
On selecting YES, user is prompted to enter the keywords.
After the user gives input in the textblock in adaptive card, the input has to be captured and sent as input parameter to web api.
The user input will be given in Placeholder of the AdaptiveTextInput block.
public static Attachment GetUserInputForCustomPPT()
{
AdaptiveCard card = new AdaptiveCard()
{
Id = "GetCustomPPT",
Body = new List<AdaptiveElement>()
{
new AdaptiveTextBlock()
{
Text = "Do you want to apply filter and customise the PPT?",
Wrap=true,
Size = AdaptiveTextSize.Small
},
new AdaptiveContainer()
{
Id = "getCustomPPTNo",
SelectAction = new AdaptiveSubmitAction()
{
Id = "getCustomPPTNo",
Title = "No",
DataJson = "{ \"Type\": \"GetCustomPPT\" }",
}
},
new AdaptiveContainer()
{
Id = "getCustomPPTYes",
Items = new List<AdaptiveElement>()
{
new AdaptiveTextBlock()
{
Text = "Please select an option",
Wrap=true,
Size = AdaptiveTextSize.Small
}
}
},
},
Actions = new List<AdaptiveAction>()
{
new AdaptiveShowCardAction()
{
Id = "GetPPTYes",
Title = "Yes",
Card = new AdaptiveCard()
{
Body = new List<AdaptiveElement>()
{
new AdaptiveTextBlock()
{
Text = "Please enter your input",
Wrap = true
},
new AdaptiveTextInput()
{
Id="GetUserInputKeywords",
Placeholder="Please enter the keyword list separated by ',' Ex:RPA,FS ",
MaxLength=490,
IsMultiline=true
}
},
Actions = new List<AdaptiveAction>()
{
new AdaptiveSubmitAction()
{
Id = "contactSubmit",
Title = "Submit",
DataJson = "{ \"Type\": \"GetPPT\" }"
},
new AdaptiveOpenUrlAction()
{
Id="CallApi",
Url=new Uri("https://xyz"+"RPA")
//card.Actions.Card.AdaptiveTextInput.Placeholder
}
}
}
},
new AdaptiveShowCardAction()
{
Id = "GetPPTNo",
Title = "No",
Card = new AdaptiveCard()
{
Body = new List<AdaptiveElement>()
{
},
Actions = new List<AdaptiveAction>()
{
new AdaptiveSubmitAction()
{
Id = "contactSubmit",
Title = "Submit",
DataJson = "{ \"Type\": \"GetPPTNo\" }"
}
}
}
}
}
};
// Create the attachment with adapative card.
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = card
};
return attachment;
}
Yes, you can retrieve the input values from an AdaptiveCard and use them as parameters in an HTTP request to an API. When the user submits an AdaptiveCard, the input fields are sent to the bot through the activity in the Value attribute. You can parse the resulting JSON string with JObject and retrieve the values for your API call. See the example below.
public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
if (turnContext.Activity.Type == ActivityTypes.Message)
{
// Check if user submitted AdaptiveCard input
if (turnContext.Activity.Value != null) {
// Convert String to JObject
String value = turnContext.Activity.Value.ToString();
JObject results = JObject.Parse(value);
// Get type from input field
String name = results.GetValue("Type").ToString();
// Get Keywords from input field
String userInputKeywords = "";
if (name == "GetPPT") {
userInputKeywords = results.GetValue("GetUserInputKeywords").ToString();
}
// Make Http request to api with paramaters
String myUrl = $"http://myurl.com/api/{userInputKeywords}";
...
// Respond to user
await turnContext.SendActivityAsync("Respond to user", cancellationToken: cancellationToken);
} else {
// Send user AdaptiveCard
var cardAttachment = GetUserInputForCustomPPT();
var reply = turnContext.Activity.CreateReply();
reply.Attachments = new List<Attachment>() { cardAttachment };
await turnContext.SendActivityAsync(reply, cancellationToken);
}
}
}
Hope this helps!
Using routing you can pass multiple parameters either on the route itself or pass parameters on the query string, via Model Binding or content value binding. For most common scenarios this actually works very well. As long as you are passing either a single complex type via a POST operation, or multiple simple types via query string or POST buffer, there's no issue. But if you need to pass multiple parameters as was easily done with WCF REST or ASP.NET AJAX things are not so obvious.
RouteTable.Routes.MapHttpRoute(
name: "ApiName",
routeTemplate: "photos/**{action}**/{title}",
defaults: new {
title = RouteParameter.Optional,
controller = "PhotoApi",
**action =** **"GetPhotos"** });

acumatica import items with image API

Now I have successfully working code (with multiple threads) for items bulk import in IN202500 screen in Acumatica.
The problem is that I am struggling to import an image of an item and actually I don't have an image by itself but only URL link to this image.
So, my question is has anyone done this in c#?
This is my piece of code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ItemImportMultiThreaded
{
public class ItemImporter
{
private IN202500.Screen _itemsScreen;
private static object _itemsSchemaLock = new object();
private static IN202500.Content _itemsSchema;
public void Login(string url, string username, string password, string company)
{
Console.WriteLine("[{0}] Logging in to {1}...", System.Threading.Thread.CurrentThread.ManagedThreadId, url);
_itemsScreen = new IN202500.Screen();
_itemsScreen.Url = url + "/PMSDB/(W(2))/Soap/IN202500.asmx";
_itemsScreen.EnableDecompression = true;
_itemsScreen.CookieContainer = new System.Net.CookieContainer();
_itemsScreen.Timeout = 36000;
_itemsScreen.Login(username, password);
Console.WriteLine("[{0}] Logged in to {1}.", System.Threading.Thread.CurrentThread.ManagedThreadId, url);
lock (_itemsSchemaLock)
{
// Threads can share the same schema.
if (_itemsSchema == null)
{
Console.WriteLine("[{0}] Retrieving IN202500 schema...", System.Threading.Thread.CurrentThread.ManagedThreadId);
_itemsSchema = _itemsScreen.GetSchema();
if (_itemsSchema == null) throw new Exception("IN202500 GetSchema returned null. See AC-73433.");
}
}
}
public void Logout()
{
_itemsScreen.Logout();
}
public void Import(List<Item> items)
{
Console.WriteLine("[{0}] Submitting {1} items to Acumatica...", System.Threading.Thread.CurrentThread.ManagedThreadId, items.Count);
var commands = new IN202500.Command[]
{
_itemsSchema.StockItemSummary.InventoryID,
_itemsSchema.StockItemSummary.Description,
_itemsSchema.GeneralSettingsItemDefaults.ItemClass,
_itemsSchema.VendorDetails.VendorID,
_itemsSchema.VendorDetails.VendorInventoryID,
_itemsSchema.VendorDetails.ServiceCommands.NewRow,
_itemsSchema.VendorDetails.VendorID,
_itemsSchema.VendorDetails.VendorInventoryID,
_itemsSchema.VendorDetails.ServiceCommands.NewRow,
_itemsSchema.VendorDetails.VendorID,
_itemsSchema.VendorDetails.VendorInventoryID,
_itemsSchema.CrossReference.AlternateID,
_itemsSchema.CrossReference.Description,
_itemsSchema.Actions.Save
};
string[][] data = new string[items.Count][];
int count = 0;
foreach(Item item in items)
{
data[count] = new string[11];
data[count][0] = item.InventoryID;
data[count][1] = item.Description.Trim();
data[count][2] = item.ItemClassID;
data[count][3] = item.DigiKey;
data[count][4] = item.DKPN;
data[count][5] = item.Mouser;
data[count][6] = item.MouserID;
data[count][7] = item.Element14;
data[count][8] = item.Element14ID;
data[count][9] = item.AlternateID;
data[count][10] = item.Descr;
count++;
}
_itemsScreen.Import(commands, null, data, false, true, true);
Console.WriteLine("[{0}] Submitted {1} items to Acumatica.", System.Threading.Thread.CurrentThread.ManagedThreadId, items.Count);
}
}
}
I tried to use FileStream but that didn't work.
If by URL link you mean an external http resource, you can download the image and upload it.
The StockItems image field cycle through all the images contained in the Files popup in the order they are displayed:
I uploaded the images from a static external Url using the following code:
const string imageUrl = "https://cdn.acumatica.com/media/2016/03/software-technology-industries-small.jpg";
string path = Path.Combine(Path.GetTempPath(), Path.ChangeExtension(Path.GetTempFileName(), ".jpg"));
// Download Image
using (WebClient client = new WebClient())
{
client.DownloadFile(new Uri(imageUrl), path);
}
// ReadUploadFile function below
byte[] data = ReadUploadFile(path);
_itemsScreen.Import(new IN202500.Command[]
{
// Get Inventory Item
new Value
{
Value = "D1",
LinkedCommand = _itemsSchema.StockItemSummary.InventoryID,
},
_itemsSchema.Actions.Save,
// Upload Inventory Item Image
new Value
{
FieldName = Path.GetFileName(path),
LinkedCommand = _itemsSchema.StockItemSummary.ServiceCommands.Attachment
},
_itemsSchema.Actions.Save
},
null,
new string[][]
{
new string[]
{
// Image data
Convert.ToBase64String(data)
}
},
false,
false,
true);
public byte[] ReadUploadFile(string filePath)
{
byte[] filedata;
using (FileStream file = File.Open(filePath,
FileMode.Open,
FileAccess.ReadWrite,
FileShare.ReadWrite))
{
filedata = new byte[file.Length];
file.Read(filedata, 0, filedata.Length);
}
if (filedata == null || filedata.Length == 0)
{
throw new Exception(string.Concat("Invalid or empty file: ", filePath));
}
return filedata;
}
You can try using the below, Tested Code.
var content = _context.CR306000GetSchema(); _context.CR306000Clear();
var commands = new List();
ReqParameter(content, ref commands);
commands.Add(content.Actions.Save);
commands.Add(content.CaseSummary.CaseID);
var orderResults = _context.CR306000Submit(commands.ToArray());
private static void ReqParameter(CR306000Content content, ref List cmds) { if (cmds == null) throw new ArgumentNullException("cmds");
private static void ReqParameter(CR306000Content content, ref List<Command> cmds)
{
if (cmds == null) throw new ArgumentNullException("cmds");
byte[] filedata= null;
Uri uri = new Uri("https://cdn.acumatica.com/media/2016/03/software-technology-industries-small.jpg"); // change the required url of the data that has to be fetched
if (uri.IsFile)
{
string filename = System.IO.Path.GetFileName(uri.LocalPath);
filedata = System.Text.Encoding.UTF8.GetBytes(uri.LocalPath);
}
if (filedata == null)
{
WebClient wc = new WebClient();
filedata = wc.DownloadData(uri);
}
cmds = new List<Command>
{
//Case Header Details
new Value { Value="<NEW>",LinkedCommand = content.CaseSummary.CaseID},
new Value { Value="L41",LinkedCommand = content.CaseSummary.ClassID},
new Value { Value="ABCSTUDIOS",LinkedCommand = content.CaseSummary.BusinessAccount, Commit = true},
new Value { Value="Test subject created from envelop call 11C",LinkedCommand = content.CaseSummary.Subject},
// body of the case
new Value{Value= "Body of the content for created through envelop call 11B", LinkedCommand = content.Details.Description},
//Attaching a file
new Value
{
Value = Convert.ToBase64String(filedata), // byte data that is passed to through envelop
FieldName = "Test.jpg",
LinkedCommand =
content.CaseSummary.ServiceCommands.Attachment
},
};
}
Let me know if this works for you.
Thanks

How to Upload document in acumatica screen using acumatica web service

I am new to using acumatica web service. is it possible to upload a document/ file in specific screen as attachment like business account attachment.
eg. below screen in which we add manually.
I find the solution and posted to help anyone.
To upload any file we must convert that file into bytes and submit bytes which convert your file.
//Get bytes of file
byte[] filedata;
using(System.IO.FileStream file =
System.IO.File.Open(#"D:\Test.pdf",System.IO.FileMode.Open))
{
filedata = new byte[file.Length];
file.Read(filedata,0,filedata.Length);
}
// Import Data Now to Business Account
BAccount.CR303000ImportResult[] lstObjContent = context.CR303000Import
(
new BAccount.Command[]
{
// Must Pass BusinessAccount in which we want to update or add data
new BAccount.Value { Value="XXXXXX",LinkedCommand=objContent.AccountSummary.BusinessAccount},
new BAccount.Value { Value="TestValue123",LinkedCommand=objContent.AccountSetup.CurrentMethod},
new BAccount.Value { FieldName="NameOfFileWithExtension",LinkedCommand=objContent.AccountSummary.ServiceCommands.Attachment},
objContent.Actions.Save
},null,new string[][] { new string[] { Convert.ToBase64String(filedata) },new string[] { Convert.ToBase64String(filedata) },}
,false,false,true
);
Even the below code works. Verified in version 18R1.
var content = _context.CR306000GetSchema(); _context.CR306000Clear();
var commands = new List();
ReqParameter(content, ref commands);
commands.Add(content.Actions.Save);
commands.Add(content.CaseSummary.CaseID);
var orderResults = _context.CR306000Submit(commands.ToArray());
private static void ReqParameter(CR306000Content content, ref List<Command> cmds)
{
if (cmds == null) throw new ArgumentNullException("cmds");
byte[] filedata= null;
Uri uri = new Uri("https://acmdev.baccahq.com/Icons/login_bg5.jpg"); // change the required url of the data that has to be fetched
if (uri.IsFile)
{
string filename = System.IO.Path.GetFileName(uri.LocalPath);
filedata = System.Text.Encoding.UTF8.GetBytes(uri.LocalPath);
}
if (filedata == null)
{
WebClient wc = new WebClient();
filedata = wc.DownloadData(uri);
}
cmds = new List<Command>
{
//Case Header Details
new Value { Value="<NEW>",LinkedCommand = content.CaseSummary.CaseID},
new Value { Value="L41",LinkedCommand = content.CaseSummary.ClassID},
new Value { Value="ABCSTUDIOS",LinkedCommand = content.CaseSummary.BusinessAccount, Commit = true},
new Value { Value="Test subject created from envelop call 11C",LinkedCommand = content.CaseSummary.Subject},
// body of the case
new Value{Value= "Body of the content for created through envelop call 11B", LinkedCommand = content.Details.Description},
//Attaching a file
new Value
{
Value = Convert.ToBase64String(filedata), // byte data that is passed to through envelop
FieldName = "Test.jpg",
LinkedCommand =
content.CaseSummary.ServiceCommands.Attachment
},
};
}

Webservice error in kentico CMS after upgrade

I have created a web service using Kentico CMS 8.0 I've upgraded the instance to 8.2. When I try to call methods from my web service I get error in screenshot.
This is my method:
[WebMethod(EnableSession = true)]
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
public string ProcessOrderGeneralDonation(Dictionary<string, object> request)
{
Dictionary<string, object> response;
ProcessDonationOrder(request, out response);
return JSONResponse(true, "Data Populated", response);
}
private void ProcessDonationOrder(Dictionary<string, object> request, out Dictionary<string, object> response, bool isChampionOfCare = false)
{
var dictionary = new Dictionary<string, object> { };
#region Customer
var customer = GetNewCustomerInfo(request);
var customerType = ValidationHelper.GetInteger(request["customer_type"], 0);
if (customerType == 2) //company
{
customer.CustomerCompany = ValidationHelper.GetString(request["customer_organization"], String.Empty);
}
CustomerInfoProvider.SetCustomerInfo(customer);
var country = CountryInfoProvider.GetCountryInfo(ValidationHelper.GetString(request["customer_country"], String.Empty).Replace(" ", ""));
//var state = StateInfoProvider.GetStateInfo(ValidationHelper.GetString(request["customer_province"], String.Empty));
// Create new address object
var customerAddress = GetNewCustomerAddressInfo(request, customer);
if (country != null)
customerAddress.AddressCountryID = country.CountryID;
// Create the address
AddressInfoProvider.SetAddressInfo(customerAddress);
customerAddress.SetValue("AddressPhone", ValidationHelper.GetString(request["customer_phone"], String.Empty));
customerAddress.SetValue("AddressStateOthers", ValidationHelper.GetString(request["customer_province"], String.Empty));
customerAddress.Update();
// Create order addresses from customer address
OrderAddressInfo orderBillingAddress = OrderAddressInfoProvider.CreateOrderAddressInfo(customerAddress);
OrderAddressInfo orderShippingAddress = OrderAddressInfoProvider.CreateOrderAddressInfo(customerAddress);
// Set the order addresses
OrderAddressInfoProvider.SetAddressInfo(orderBillingAddress);
OrderAddressInfoProvider.SetAddressInfo(orderShippingAddress);
#endregion
var guid = ValidationHelper.GetGuid(request["guid"], Guid.Empty);
string message;
#region Shopping Cart
//Get Product
var product = GetProductSKUInfo(guid, out message);
if (product == null)
{
response = null;
return;
}
//Get Shopping Cart
var cart = GetShoppingCart();
// Add item to cart object
var param = new ShoppingCartItemParameters(product.SKUID, 1)
{
ProductOptions = new List<ShoppingCartItemParameters>
{
new ShoppingCartItemParameters(ValidationHelper.GetInteger(request["designation_id"], 0), 1),
new ShoppingCartItemParameters(ValidationHelper.GetInteger(request["donation_amount_id"], 0), 1)
}
};
if (isChampionOfCare)
{
//Get Champions Of Care Option Id
var options = OptionCategoryInfoProvider.GetProductOptionCategories(product.SKUID, true, OptionCategoryTypeEnum.Text);
var opt = options.Tables[0].AsEnumerable().SingleOrDefault(x => x["CategoryName"].ToString().ToLower() == "coc");
if (opt != null)
{
var categoryId = ValidationHelper.GetInteger(opt["CategoryID"], 0);
var skuOpt = GetSKUOptions(product.SKUID, categoryId) as DataTable;
if (skuOpt != null)
{
var cocId = ValidationHelper.GetInteger(skuOpt.Rows[0]["SKUID"], 0);
var cocParam = new ShoppingCartItemParameters(cocId, 1)
{
Text = ValidationHelper.GetString(request["coc_text"], string.Empty)
};
param.ProductOptions.Add(cocParam);
}
}
}
ShoppingCartItemInfo cartItem = cart.SetShoppingCartItem(param);
cartItem.CartItemCustomData["other_amount"] = ValidationHelper.GetDouble(request["donation_other_amount"], 0);
cart.ShoppingCartCustomData["donation_type"] = "GEN";
// Save item to database
ShoppingCartItemInfoProvider.SetShoppingCartItemInfo(cartItem);
cart.ShoppingCartBillingAddress = orderBillingAddress;
cart.ShoppingCartShippingAddress = orderShippingAddress;
cart.Customer = customer;
cart.Update();
ShoppingCartInfoProvider.SetOrder(cart);
dictionary.Add("order_id", cart.OrderId);
UpdateDonor(request, cart.OrderId);
if (EnablePurchase)
{
Receipt responseReceipt;
request.Add("product_sku", product.SKUID);
Purchase(request, cart, customer, customerAddress, out responseReceipt);
var paymentSuccessed = !responseReceipt.GetMessage().Contains("DECLINED");
if (paymentSuccessed)
{
//HandleOrderNotification(cart);
SendInvoiceEmail(cart.OrderId);
}
dictionary.Add("moneris_message", responseReceipt.GetMessage());
}
#endregion
response = dictionary;
}
I believe the issue is that JSONResponse() doesn't know how to serialize a Dictionary<string,object> to a valid JSON format.
Take a look at some of these answers to help you solve this problem. Most of them suggest using a JSON library like JSON.NET:
https://stackoverflow.com/a/6620173/2344773
https://stackoverflow.com/a/5597628/2344773
i have already added JSON.NET to my project and JSONResponse() function
private string JSONResponse(bool success, string message, object data = null)
{
var dictionary = new Dictionary<string, object> { { "success", success }, { "message", message }, { "data", data } };
return JsonConvert.SerializeObject(dictionary, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
}

Programmatically setting up a static website using Amazon S3 and Route 53 APIs

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.

Categories

Resources