can adaptive cards in bot framework v3 contain dynamic dropdowns - c#

I'm using BOT Framework v 3 i have an adaptive card that takes input from the user and i want the values in Dropdown to be dynamic is it possible.here is the adaptive card design code as you can see I have entered the choices manually instead it want it to be dynamic from the database
var card = new AdaptiveCard()
{
Body = new List<CardElement>()
{
new TextBlock()
{
Color = TextColor.Attention,
Weight = TextWeight.Bolder,
Size = TextSize.Medium,
Text = "Select a title",
},
new ChoiceSet()
{
Id = "title",
Style = ChoiceInputStyle.Compact,
IsRequired = false,
IsMultiSelect = false,
Value = "1",
Choices = new List<Choice>()
{
new Choice()
{
Title = "Swiss cargo",
Value = "Swiss cargo",
},
new Choice()
{
Title = "ticket booking",
Value = "ticket booking",
},
},
},
},
};

Assuming you can get your data into a list of strings, your Adaptive Card can easily be constructed dynamically using Linq. If you want to keep using the same Adaptive Cards library, it would look like this:
var data = new List<string> { "Swiss cargo", "ticket booking" };
var card = new AdaptiveCard()
{
Body = new List<CardElement>()
{
new TextBlock()
{
Color = TextColor.Attention,
Weight = TextWeight.Bolder,
Size = TextSize.Medium,
Text = "Select a title",
},
new ChoiceSet()
{
Id = "title",
Style = ChoiceInputStyle.Compact,
IsRequired = false,
IsMultiSelect = false,
Value = "1",
Choices = data.Select(item => new Choice { Title = item, Value = item }).ToList(),
},
},
};

Related

Converting JSON code of Facebook's Generic Template to C# in Bot framework

I am having a hard time converting this generic template of facebook to C#. I am not sure if i converted it right. Below is the code i tried but is not rendering on messenger. Thank you.
curl -X POST -H "Content-Type: application/json" -d '{
"recipient":{
"id":"<PSID>"
},
"message":{
"attachment":{
"type":"template",
"payload":{
"template_type":"generic",
"elements":[
{
"title":"Welcome!",
"image_url":"https://petersfancybrownhats.com/company_image.png",
"subtitle":"We have the right hat for everyone.",
"default_action": {
"type": "web_url",
"url": "https://petersfancybrownhats.com/view?item=103",
"webview_height_ratio": "tall",
},
"buttons":[
{
"type":"web_url",
"url":"https://petersfancybrownhats.com",
"title":"View Website"
},{
"type":"postback",
"title":"Start Chatting",
"payload":"DEVELOPER_DEFINED_PAYLOAD"
}
]
}
]
}
}
}
}' "https://graph.facebook.com/v2.6/me/messages?access_token=<PAGE_ACCESS_TOKEN>"
This is what i tried in c# but it is not working. I am not sure if i converted it the proper way. Any help would be appreciated thank you.
Activity previewReply = stepContext.Context.Activity.CreateReply();
previewReply.ChannelData = JObject.FromObject(
new
{
attachment = new
{
type = "template",
payload = new
{
template_type = "generic",
elements = new
{
title = "title",
subtitle = "subtitle",
image_url = "https://thechangreport.com/img/lightning.png",
buttons = new object[]
{
new
{
type = "element_share,",
share_contents = new
{
attachment = new
{
type = "template",
payload = new
{
template_type = "generic",
elements = new
{
title = "x",
subtitle = "xx",
image_url = "https://thechangreport.com/img/lightning.png",
default_action = new
{
type = "web_url",
url = "http://m.me/petershats?ref=invited_by_24601",
},
buttons = new
{
type = "web_url",
url = "http://m.me/petershats?ref=invited_by_24601",
title = "Take Quiz",
},
},
},
},
},
},
},
},
},
},
});
await stepContext.Context.SendActivityAsync(previewReply);
The elements and buttons attributes need to be lists. Take a look at the example template below.
var attachment = new
{
type = "template",
payload = new
{
template_type = "generic",
elements = new []
{
new {
title = "title",
image_url = "https://thechangreport.com/img/lightning.png",
subtitle = "subtitle",
buttons = new object[]
{
new {
type = "element_share",
share_contents = new {
attachment = new {
type = "template",
payload = new
{
template_type = "generic",
elements = new []
{
new {
title = "title 2",
image_url = "https://thechangreport.com/img/lightning.png",
subtitle = "subtitle 2",
buttons = new object[]
{
new {
type = "web_url",
url = "http://m.me/petershats?ref=invited_by_24601",
title = "Take Quiz"
},
},
},
},
},
}
},
},
},
},
},
},
};
reply.ChannelData = JObject.FromObject(new { attachment });
Note, you only need to add a share_contents element to your template if your main template is different from the template you are trying to share. Otherwise, your button can just be new { type = "element_share" }, which makes the template far less complex.
Also, be sure to Whitelist all of your URLs and make sure all of the image URLs work properly - a couple of them weren't working properly. The template won't render if the URLs aren't Whitelisted and image links are broken.
Hope this helps!

NetSuite Web API - How to return/populate customFieldList array for Sales Order from a joined search?

I am currently performing a SuiteTalk search via C# that joins multiple tables, one of which is for Sales Orders. When performing a typical GET on a SalesOrder record, the property customFieldList gets populated with an array of transaction custom fields/etc. I am curious how to get the same when doing a search like:
SearchResult searchResult = Client.Service.search(new TransactionSearchAdvanced()
{
criteria = new TransactionSearch()
{
basic = new TransactionSearchBasic()
{
type = new SearchEnumMultiSelectField()
{
#operator = SearchEnumMultiSelectFieldOperator.anyOf,
operatorSpecified = true,
searchValue = new String[] { "_salesOrder" },
},
lastModifiedDate = new SearchDateField()
{
#operator = SearchDateFieldOperator.after,
operatorSpecified = true,
searchValue = fromLastModifiedDateTime.ToUniversalTime(),
searchValueSpecified = true
}
},
},
columns = new TransactionSearchRow()
{
basic = new TransactionSearchRowBasic()
{
internalId = new SearchColumnSelectField[] { new SearchColumnSelectField() },
tranId = new SearchColumnStringField[] { new SearchColumnStringField() },
tranDate = new SearchColumnDateField[] { new SearchColumnDateField() },
dateCreated = new SearchColumnDateField[] { new SearchColumnDateField() },
item = new SearchColumnSelectField[] { new SearchColumnSelectField() },
quantity = new SearchColumnDoubleField[] { new SearchColumnDoubleField() },
lastModifiedDate = new SearchColumnDateField[] { new SearchColumnDateField() },
email = new SearchColumnStringField[] { new SearchColumnStringField() },
//customFieldList = new SearchColumnCustomField[] { },
},
itemJoin = new ItemSearchRowBasic()
{
itemId = new SearchColumnStringField[] { new SearchColumnStringField() },
type = new SearchColumnEnumSelectField[] { new SearchColumnEnumSelectField() },
},
customerJoin = new CustomerSearchRowBasic()
{
internalId = new SearchColumnSelectField[] { new SearchColumnSelectField() },
billAddress = new SearchColumnStringField[] { new SearchColumnStringField() },
companyName = new SearchColumnStringField[] { new SearchColumnStringField() },
phone = new SearchColumnStringField[] { new SearchColumnStringField() },
email = new SearchColumnStringField[] { new SearchColumnStringField() },
},
customSearchJoin = new CustomSearchRowBasic[]
{
},
}
});
The property I want populated is commented out within the TransactionSearchRowBasic object:
//customFieldList = new SearchColumnCustomField[] { },
Any ideas? Thank you in advance!
The search operation doesn't return as much information as a GET operation does on the SuiteTalk Web Services.
For each record that is returned in your SearchResult, use the internalId or document number to GET that record. This should then include your custom fields.
NetSuiteService _service = new NetSuiteService();
ReadResponse res = _service.get(new RecordRef { internalId = internalID, type = RecordType.salesOrder, typeSpecified = true });

How can I send carbon copies to the same recipient in every step of the signing process?

We require two signers and one carbon copy recipient which receives a carbon copy for every status change of the signing process.
Using DocuSign.eSign Nuget package 2.1.4, I tried:
adding the carbon copy recipient (RecipientId=1)
adding the first signer (RecipientId=2)
adding the same carbon copy recipient as in step 1 (RecipientId=1)
adding the second signer (RecipientId=3)
adding the same carbon copy recipient as in step 1 (RecipientId=1)
I'm increasing RoutingOrder along the way (from 1 to 5)
A recipient simply contains values for: Email, Name, RecipientId and RoutingOrder, nothing more.
This, however causes the API to return
ENVELOPE_HAS_DUPLICATE_RECIPIENTS.
I tried to find a solution for this in the documentation, but can't seem to find the correct paragraph.
If you are using the DocuSign c# SDK, then the following code should accomplish what you are trying. See full example here.
The envelope has the recipients in the following order
CC Recipient (janecc#acme.com)
Signer (janedoe#acme.com)
CC Recipient (janecc#acme.com)
Signer (bobbydoe#acme.com)
CC Recipient (janecc#acme.com)
public void CreateEnvelopeDuplicateRecipients()
{
string accountID = "";//Initialization code here.
byte[] fileBytes = System.IO.File.ReadAllBytes(#"C:\temp\test.pdf");
var envDef = new EnvelopeDefinition()
{
EmailSubject = "Envelope with CC & Signers",
Status = "Sent",
Documents = new List<Document>()
{
new Document()
{
DocumentBase64 = System.Convert.ToBase64String(fileBytes),
Name = "Dummy",
DocumentId = "1"
}
},
Recipients = new Recipients()
{
CarbonCopies = new List<CarbonCopy>()
{
new CarbonCopy()
{
Email = "janecc#acme.com",
Name = "jane cc",
RecipientId = "1",
RoutingOrder = "1"
},
new CarbonCopy()
{
Email = "janecc#acme.com",
Name = "jane cc",
RecipientId = "3",
RoutingOrder = "3"
},
new CarbonCopy()
{
Email = "janecc#acme.com",
Name = "jane cc",
RecipientId = "5",
RoutingOrder = "5"
}
},
Signers = new List<Signer>()
{
new Signer()
{
Email = "janedoe#acme.com",
Name = "jane doe",
RecipientId = "2",
RoutingOrder = "2",
Tabs = new Tabs()
{
SignHereTabs = new List<SignHere>()
{
new SignHere()
{
DocumentId = "1", XPosition = "100", YPosition = "200", PageNumber = "1",
}
}
}
},
new Signer()
{
Email = "bobbydoe#acme.com",
Name = "bobbydoe Demo",
RecipientId = "4",
RoutingOrder = "4",
Tabs = new Tabs()
{
SignHereTabs = new List<SignHere>()
{
new SignHere()
{
DocumentId = "1", XPosition = "100", YPosition = "300", PageNumber = "1",
}
}
}
}
}
}
};
var envelopesApi = new EnvelopesApi();
EnvelopeSummary envelopeSummary = envelopesApi.CreateEnvelope(accountID, envDef);
Console.WriteLine(envelopeSummary);
}

Initialize array with a mix of with hard-coded and generated values

This code which initializes an array with two hard-coded values is working perfectly fine:
var db = new GoogleGraph {
cols = new ColInfo[] {
new ColInfo { id = "", label = "Date", pattern ="", type = "string" },
new ColInfo { id = "", label = "Attendees", pattern ="", type = "number" }
}.ToList(),
rows = new List<DataPointSet>()
};
db.cols.AddRange(listOfValues.Select(p => new ColInfo { id = "", label = p, type = "number" }));
This code which attempts to add some dynamically generated values is not working:
var db = new GoogleGraph {
cols = new ColInfo[] {
new ColInfo { id = "", label = "Date", pattern ="", type = "string" },
new ColInfo { id = "", label = "Attendees", pattern ="", type = "number" },
listOfValues.Select(p => new ColInfo { id = "", label = p, type = "number" })
}.ToList(),
rows = new List<DataPointSet>()
};
How can I correctly implement the above snippet?
You can't pass an IEnumerable<T> to an initializer of T[] like that.
You can do what you want by putting the hard-coded objects in their own collection, then concatenating the dynamic ones:
var db = new GoogleGraph {
cols =
new ColInfo[] {
new ColInfo { id = "", label = "Date", pattern ="", type = "string" },
new ColInfo { id = "", label = "Attendees", pattern ="", type = "number" }
}
.Concat(listOfValues.Select(p =>
new ColInfo { id = "", label = p, type = "number" }))
.ToList(),
rows = new List<DataPointSet>()
};

MVC 4 DateTime? on model removal on edit

I have model which as a nullable Date field. Everything works as expected except in the circumstance where I am editing the model and I want to remove the date. Then validation is triggered:
How do I allow removal while also keeping validation on a partially filled in date? Is worth mentioning that are using a custom EditorTemplate:
Here is the code for the editor template:
#model DateTime?
#{
var months = new[] {
new { Value = "", Display="" },
new { Value = "1", Display = "01-Jan" },
new { Value = "2", Display = "02-Feb" },
new { Value = "3", Display = "03-Mar" },
new { Value = "4", Display = "04-Apr" },
new { Value = "5", Display = "05-May" },
new { Value = "6", Display = "06-Jun" },
new { Value = "7", Display = "07-Jul" },
new { Value = "8", Display = "08-Aug" },
new { Value = "9", Display = "09-Sep" },
new { Value = "10", Display = "10-Oct" },
new { Value = "11", Display = "11-Nov" },
new { Value = "12", Display = "12-Dec" }
};
var monthSelect = new SelectList(months, "Value", "Display", Model.HasValue ? Model.Value.Month.ToString() : "");
var days = new List<String>();
days.Add("");
days.AddRange(Enumerable.Range(1, 31).Select(s => s.ToString()));
var daySelect = new SelectList(days.Select(x => new KeyValuePair<string, string>(x, x)), "Key", "Value", Model.HasValue ? Model.Value.Day.ToString() : "");
}
#Html.DropDownList("Month", monthSelect)
#Html.DropDownList("Day", daySelect)
#Html.TextBox("Year", (Model.HasValue ? Model.Value.ToString("yyyy") : string.Empty), new { style="width:75px;" })
The code on the edit view is dead simple:
#Html.EditorFor(model => model.MyDate)

Categories