According to the DocuSign Documentation, it is possible to send an envelope where each signer in the envelope receives a "Private Message". I have reviewed the DocuSign REST API documentation and was unable to find any reference to a private message, or details on how to create one.
Could someone provide details on the REST API implementation of the "private message" feature? Additionally an example the DocuSign .Net SDK would be great.
You can specify the emailNotification property for each recipient. Documentation here
Here is a sample createEnvelope request.
POST /v2/accounts/{accountId}/envelopes
{
"status": "sent",
"recipients": {
"signers": [
{
"email": "janedoe#acme.com",
"name": "jane doe",
"recipientId": 1,
"emailNotification": {
"emailSubject": "Please sign the document(s) (jane doe)",
"emailBody": "Hello Jane Doe,\r\n\r\nYour have a new document to view and sign. Please click on the View Documents link below, review the content, and sign the document. ",
"supportedLanguage": "en"
},
"tabs": {"signHereTabs": [ { "documentId": "1", "pageNumber": "1", "xPosition": "80", "yPosition": "80"}]}
},
{
"email": "johnsmith#acme.com",
"name": "john smith",
"recipientId": 2,
"emailNotification": {
"emailSubject": "Please sign the document(s) (john smith)",
"emailBody": "Hello john smith,\r\n\r\nYour have a new document to view and sign. Please click on the View Documents link below, review the content, and sign the document. ",
"supportedLanguage": "en"
},
"tabs": {"signHereTabs": [ { "documentId": "1", "pageNumber": "1", "xPosition": "80", "yPosition": "180"}]}
}
]
},
"documents": [
{
"documentId": "1", "name": "Contract", "fileExtension": "txt", "documentBase64": "RG9jIFRXTyBUV08gVFdP"
}
]
}
Using the C# SDK
Complete code here
public void CreateEnvelopeSeparateEmailNotificationForRecipients()
{
string accountID = Init();
byte[] fileBytes = System.IO.File.ReadAllBytes(#"C:\temp\test.pdf");
var envDef = new EnvelopeDefinition()
{
Status = "sent",
Recipients = new Recipients()
{
Signers = new List<Signer>()
{
new Signer()
{
Email = "janedoe#acme.com",
Name = "jane doe",
RecipientId = "1",
RoutingOrder = "1",
EmailNotification = new RecipientEmailNotification()
{
EmailSubject = "Please sign the document(s) (jane doe)",
EmailBody = "This is email body for Jane Doe"
},
Tabs = new Tabs() { SignHereTabs = new List<SignHere>(){ new SignHere() { DocumentId = "1", XPosition = "100",YPosition = "300", PageNumber = "1" } } }
},
new Signer()
{
Email = "johnsmith#acme.com",
Name = "JohnSmith",
RecipientId = "2",
RoutingOrder = "1",
EmailNotification = new RecipientEmailNotification()
{
EmailSubject = "Please sign the document(s) (John Smith)",
EmailBody = "This is email body for John Smith"
},
Tabs = new Tabs() { SignHereTabs = new List<SignHere>(){ new SignHere() { DocumentId = "1", XPosition = "200",YPosition = "300", PageNumber = "1" } } }
}
}
},
Documents = new List<Document>()
{
new Document()
{
DocumentBase64 = System.Convert.ToBase64String(fileBytes),
Name = "Contract",
DocumentId = "1"
}
}
};
EnvelopesApi envelopesApi = new EnvelopesApi();
EnvelopeSummary envelopeSummary = envelopesApi.CreateEnvelope(accountID, envDef);
}
Related
I already have the radio button in DocuSign template, I want to select one of correct option from True and False programmatically. With the help of radioGroup.Radios.Add(, I am getting overwrite button on template button. Can you please suggest the solution how i can select radio button through c# code.
RadioGroup radioGroup = new RadioGroup { GroupName =
templateField.DocuSignFieldName, DocumentId = "1",
Radios = new List<Radio>() };
radioGroup.Radios.Add(
new Radio { PageNumber = "3", Value = "Radio 1",
XPosition = "52", YPosition = "344", Selected = "true",
TabId = templateField.DocuSignFieldName });
radioGroup.Radios.Add(
new Radio { PageNumber = "3", Value = "Radio 2",
XPosition = "85", YPosition = "344", Selected = "false",
TabId = templateField.DocuSignFieldName });
radioTabs.Add(radioGroup);
Your template has a radio group
When you use the API to send the envelope, you want to choose the initial value of the radio group. (If you want the radio buttons to be read-only, then use the locked attribute.)
You will need the tabId and value for the radio button you want to set.
Here is the request object that uses a template on the server, and then sets the name/email of the signer, and sets which radio button is selected.
{
"envelopeDefinition": {
"status": "sent",
"compositeTemplates": [
{
"compositeTemplateId": "1",
"serverTemplates": [
{
"sequence": "1",
"templateId": "12345-678-91023"
}
],
"inlineTemplates": [
{
"sequence": "1",
"recipients": {
"signers": [
{
"email": "larry#example.com",
"name": "Larry K",
"roleName": "Signer1",
"recipientId": "1",
"tabs": {
"radioGroupTabs": [
{
"groupName": "Radio Group 1",
"radios": [
{
"selected": "true",
"tabId": "615d0f54-8754-459e-9f79-e72ad427557c",
"value": "Radio3"
}
]
}
]
}
}
]
}
}
]
}
]
}
}
Here is the same JSON when it is created with the C# SDK
ServerTemplate serverTemplate1 = new ServerTemplate
{
Sequence = "1",
TemplateId = "12345-678-91023"
};
List<ServerTemplate> serverTemplates1 = new List<ServerTemplate> {serverTemplate1};
Radio radio1 = new Radio
{
Selected = "true",
TabId = "615d0f54-8754-459e-9f79-e72ad427557c",
Value = "Radio3"
};
List<Radio> radios1 = new List<Radio> {radio1};
RadioGroup radioGroupTab1 = new RadioGroup
{
GroupName = "Radio Group 1",
Radios = radios1
};
List<RadioGroup> radioGroupTabs1 = new List<RadioGroup> {radioGroupTab1};
Tabs tabs1 = new Tabs
{
RadioGroupTabs = radioGroupTabs1
};
Signer signer1 = new Signer
{
Email = "larry#example.com",
Name = "Larry K",
RecipientId = "1",
RoleName = "Signer1",
Tabs = tabs1
};
List<Signer> signers1 = new List<Signer> {signer1};
Recipients recipients1 = new Recipients
{
Signers = signers1
};
InlineTemplate inlineTemplate1 = new InlineTemplate
{
Recipients = recipients1,
Sequence = "1"
};
List<InlineTemplate> inlineTemplates1 = new List<InlineTemplate> {inlineTemplate1};
CompositeTemplate compositeTemplate1 = new CompositeTemplate
{
CompositeTemplateId = "1",
InlineTemplates = inlineTemplates1,
ServerTemplates = serverTemplates1
};
List<CompositeTemplate> compositeTemplates1 = new List<CompositeTemplate> {compositeTemplate1};
EnvelopeDefinition envelopeDefinition = new EnvelopeDefinition
{
CompositeTemplates = compositeTemplates1,
Status = "sent"
};
ApiClient apiClient = new ApiClient(basePath);
apiClient.Configuration.AddDefaultHeader("Authorization", "Bearer " + accessToken);
EnvelopesApi envelopesApi = new EnvelopesApi(apiClient);
try
{
EnvelopeSummary results = envelopesApi.CreateEnvelope(accountId, envelopeDefinition);
Console.WriteLine($"Envelope status: {results.Status}. Envelope ID: {results.EnvelopeId}");
return results.EnvelopeId;
}
catch (ApiException e)
{
Console.WriteLine("Exception while creating envelope!");
Console.WriteLine($"Code: {e.ErrorCode}\nContent: {e.ErrorContent}");
//Console.WriteLine(e.Message);
return "";
}
}
Please find the correct answer .
RadioGroup radioGroup = new RadioGroup
{
GroupName = templateField.DocuSignFieldName,
Radios = new List<Radio>()
};
if (_applicationAnswerMapService.GetRadioboxFieldValue(templateField, application) == "true")
{
radioGroup.Radios.Add(new Radio { Value = "Radio1", Selected = "true" });
}
else
{
radioGroup.Radios.Add(new Radio { Value = "Radio2", Selected = "false" });
}
We have an adaptive card which is displayed after getting an answer from QnA. Within the card, we have choiceset displayed to let the user select the category he is interested in. Upon clicking select, the second level of options are given. However, we are planning to have the suboptions in the same card at first level. Is it possible to have checkboxes side by side in an adaptive card?
Code:
public List<Attachment> EmbedAdaptiveCategoryOptions()
{
#region populate choiceLists
List<AdaptiveChoice> OGChoice = new List<AdaptiveChoice>();
List<AdaptiveChoice> GeoChoice = new List<AdaptiveChoice>();
List<AdaptiveChoice> TechChoice = new List<AdaptiveChoice>();
List<AdaptiveChoice> ThemeChoice = new List<AdaptiveChoice>();
List<AdaptiveChoice> OKChoice = new List<AdaptiveChoice>();
List<string> OGids = new List<string>();
List<string> Geoids = new List<string>();
List<string> Techids = new List<string>();
List<string> themeids = new List<string>();
List<string> feedbackids = new List<string> { "I am good with the link already shared with me above!" };
List<CardAction> OGButtons = CreateOGButtons(out OGids);
foreach (var item in OGButtons)
{
OGChoice.Add(new AdaptiveChoice() { Title = item.Title, Value = item.Value.ToString() });
}
List<CardAction> GeoButtons = CreateGeoButtons(out Geoids);
foreach (var item in GeoButtons)
{
GeoChoice.Add(new AdaptiveChoice() { Title = item.Title, Value = item.Value.ToString() });
}
List<CardAction> techcardButtons = CreateTechButtons(out Techids);
foreach (var item in techcardButtons)
{
TechChoice.Add(new AdaptiveChoice() { Title = item.Title, Value = item.Value.ToString() });
}
List<CardAction> themecardButtons = CreateThemeButtons(out themeids);
foreach (var item in themecardButtons)
{
ThemeChoice.Add(new AdaptiveChoice() { Title = item.Title, Value = item.Value.ToString() });
}
List<CardAction> feedbackcardButtons = new List<CardAction>();
CardAction feedbackButton = new CardAction()
{
Value = "feedback",
Type = "imBack",
Title = "I am good with the link already shared with me above!"
};
feedbackcardButtons.Add(feedbackButton);
foreach (var item in feedbackcardButtons)
{
OKChoice.Add(new AdaptiveChoice() { Title = item.Title, Value = item.Value.ToString() });
}
#endregion
AdaptiveCard card = new AdaptiveCard();
List<Attachment> attachments = new List<Attachment>();
AdaptiveColumnSet Title = new AdaptiveColumnSet();
AdaptiveColumn titletext = new AdaptiveColumn();
titletext.Width = AdaptiveColumnWidth.Auto;
titletext.Items.Add(new AdaptiveTextBlock()
{
Weight = AdaptiveTextWeight.Bolder,
Wrap = true,
Text = "Are you interested in searching through the file? Please select the Category you would like to refine Credentials for:",
Size = AdaptiveTextSize.Medium
});
Title.Columns.Add(titletext);
card.Body.Add(Title);
AdaptiveColumnSet abc = new AdaptiveColumnSet();
AdaptiveColumn col1 = new AdaptiveColumn();
col1.Width = AdaptiveColumnWidth.Auto;
col1.Type = "TextBlock";
col1.Items.Add(new AdaptiveChoiceSetInput()
{
Choices = OGChoice,
Separator = true,
IsMultiSelect = true,
Type = "Input.ChoiceSet"
});
AdaptiveColumn col2 = new AdaptiveColumn();
col2.Width = AdaptiveColumnWidth.Auto;
col2.Type = "TextBlock";
//col2.Type = AdaptiveTextBlock.TYPE;
col2.Items.Add(new AdaptiveChoiceSetInput()
{
Choices = GeoChoice,
Separator = true,
IsMultiSelect = true,
Type = "Input.ChoiceSet"
});
AdaptiveColumn col3 = new AdaptiveColumn();
col3.Width = AdaptiveColumnWidth.Auto;
col3.Type = "TextBlock";
//col2.Type = AdaptiveTextBlock.TYPE;
col3.Items.Add(new AdaptiveChoiceSetInput()
{
Choices = TechChoice,
Separator = true,
IsMultiSelect = true,
Type = "Input.ChoiceSet"
});
AdaptiveColumn col4 = new AdaptiveColumn();
col4.Width = AdaptiveColumnWidth.Auto;
col4.Type = "TextBlock";
//col2.Type = AdaptiveTextBlock.TYPE;
col4.Items.Add(new AdaptiveChoiceSetInput()
{
Choices = ThemeChoice,
Separator = true,
IsMultiSelect = true,
Type = "Input.ChoiceSet"
});
AdaptiveColumn col5 = new AdaptiveColumn();
col5.Width = AdaptiveColumnWidth.Auto;
col5.Type = "TextBlock";
//col2.Type = AdaptiveTextBlock.TYPE;
col5.Items.Add(new AdaptiveChoiceSetInput()
{
Choices = OKChoice,
Separator = true,
IsMultiSelect = true,
Type = "Input.ChoiceSet"
});
abc.Columns.Add(col1);
abc.Columns.Add(col2);
abc.Columns.Add(col3);
abc.Columns.Add(col4);
abc.Columns.Add(col5);
card.Body.Add(abc);
List<AdaptiveAction> Actions = new List<AdaptiveAction>()
{
new AdaptiveSubmitAction()
{
Id = "selectBtn",
Title = "Select",
Speak = "<s>Search</s>",
DataJson = "{ \"Type\": \"SubmitQuestion\" }"
}
};
card.Actions.Add(Actions[0]);
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = card
};
attachments.Add(attachment);
return attachments;
}
You can align check boxes side-by-side in an AdaptiveCard by placing them in columns. Take a look at the AdaptiveCards documentation on columns and see the example below.
Screenshot
AdaptiveCard JSON
{
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"horizontalAlignment": "Center",
"size": "Medium",
"text": "Horizontal Checkboxes",
"maxLines": 3
},
{
"type": "ColumnSet",
"separator": true,
"columns": [
{
"type": "Column",
"items": [
{
"type": "Input.Toggle",
"id": "option1",
"title": "Option 1",
"value": "true"
}
],
"width": "auto"
},
{
"type": "Column",
"items": [
{
"type": "Input.Toggle",
"id": "option2",
"title": "Option 2",
"value": "false"
}
],
"width": "auto"
},
{
"type": "Column",
"items": [
{
"type": "Input.Toggle",
"id": "option3",
"title": "Option 3",
"value": "true"
}
],
"width": "auto"
},
{
"type": "Column",
"items": [
{
"type": "Input.Toggle",
"id": "option4",
"title": "Option 4",
"value": "false"
}
],
"width": "auto"
}
]
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Submit"
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0"
}
Also, I would recommend using the AdaptiveCard Designer to help format and create your cards.
Hope this helps!
I have a Json file as shown below. I want to convert only the option node in the JSON file into a C# ListItemCollection object
ASP.net File:
var path = Server.MapPath(#"~/json.json");
using (StreamReader r = new StreamReader(path,false))
{
string json = r.ReadToEnd();
dynamic arr = JsonConvert.DeserializeObject(json);
ListItemCollection licRB = new ListItemCollection();
licRB = arr.AnswerRadioButton.option;<<-- run time error is produced here
}
JSON File:
{ "FormTitle": "This is Form Title from JSON",
"TitleQuestion1": "This is the Title of Question 1",
"TextQuestion1": "1- This is the text of Quextion Number 1",
"AnswerRadioButton": {
"visible": "true",
"title": "Radio Button Title",
"FieldsetRBStyle": { "border": "1px" },
"option" : [
{
"text": "text1",
"value": "v1",
"checked": "false"
},
{
"text": "text2",
"value": "v2",
"checked": "true"
},
{
"text": "text3",
"value": "v3",
"checked": "false"
},
{
"text": "text4",
"value": "v4",
"checked": "true"
}
] }}
Assuming that you have the required classes (e.g. using this tool) you can access the options like this:
var test = JsonConvert.DeserializeObject<RootObject>(json);
var options = test.AnswerRadioButton.option;
I'm in process of trying to learn JWT and ouath. I have came across form of JWT which would help me in development of my authorization server.
The format I came across is following :
{
iat: 1416929061,
jti: "802057ff9b5b4eb7fbb8856b6eb2cc5b",
scopes: {
users: {
actions: ['read', 'create']
},
users_app_metadata: {
actions: ['read', 'create']
}
}
}
However since in adding claims we can only add simple string how something like this can be achieved ?
The only way I have seen till now was to use JSON.serialization - coming from https://stackoverflow.com/a/27279400/2476347
new Claim(someClass,JsonConvert.SerializeObject(result)
any guidelines would be much appreciated! Thanks!
Code used for testing
Class I would like to use in JWT
public class MyTes
{
public string area { get; set; }
public List<string> areapermissions { get; set; }
}
And then I use the following code for token generation
var identity = new ClaimsIdentity("JWT");
var cos = new List<string>();
cos.Add("aaa");
cos.Add("bbb");
MyTes vario = new MyTes()
{
area = "someregion",
areapermissions = cos
};
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim(ClaimTypes.Role, "Manager"));
identity.AddClaim(new Claim(ClaimTypes.Role, "Supervisor"));
identity.AddClaim(new Claim("scope", "xyz1"));
identity.AddClaim(new Claim("scope", "xyz2"));
identity.AddClaim(new Claim("scope", "xyz3"));
identity.AddClaim(new Claim("APIs", JsonConvert.SerializeObject(cos)));
identity.AddClaim(new Claim("APIs2", JsonConvert.SerializeObject(vario)));
This gives no errors and when I decode the ticket I get now :
{
"unique_name": "Rafski",
"sub": "Rafski",
"role": [
"Manager",
"Supervisor"
],
"scope": [
"xyz1",
"xyz2",
"xyz3"
],
"APIs": "[\"aaa\",\"bbb\"]",
"APIs2": "{\"area\":\"someregion\",\"areapermissions\":[\"aaa\",\"bbb\"]}",
"iss": "http://kurwa.mac",
"aud": "7aaa70ed8f0b4807a01596e2abfbd44d",
"exp": 1429351056,
"nbf": 1429349256
}
Here's how to create a JWT token with complex JSON claims using .Net.
Use Nuget to get the Library: System.IdentityModel.Tokens.Jwt
Then use the following code to create a JWT token.
var keybytes = Convert.FromBase64String(YOUR_CLIENT_SECRET);
var signingCredentials = new SigningCredentials(
new InMemorySymmetricSecurityKey(keybytes),
SecurityAlgorithms.HmacSha256Signature,
SecurityAlgorithms.Sha256Digest);
var nbf = DateTime.UtcNow.AddSeconds(-1);
var exp = DateTime.UtcNow.AddSeconds(120);
var payload = new JwtPayload(null, "", new List<Claim>(), nbf, exp);
var users = new Dictionary<string, object>();
users.Add("actions", new List<string>() { "read", "create" });
var scopes = new Dictionary<string, object>();
scopes.Add("users", users);
payload.Add("scopes", scopes);
var jwtToken = new JwtSecurityToken(new JwtHeader(signingCredentials), payload);
var jwtTokenHandler = new JwtSecurityTokenHandler();
return jwtTokenHandler.WriteToken(jwtToken);
Which would produce a token such as
{
"typ": "JWT",
"alg": "HS256"
}
{
"exp": 1433254394,
"nbf": 1433254273,
"scopes": {
"users": {
"actions": [
"read", "create"
]
}
}
}
This has been never an issue these days. It can be solved using the
Payload section of the token.
**using System.IdentityModel.Tokens.Jwt;** //Vesrion 5.5.0
Sample code
public static string Generate()
{
IList<User> users = new List<User> {
new User { Id = 1, Name = "User One" },
new User { Id = 2, Name = "User Two" },
new User { Id = 3, Name = "User Three" }
};
IList<Company> companies = new List<Company>
{
new Company{ Id = 1, Code = "C01", Name = "Company I", Users = users },
new Company{ Id = 2, Code = "C03", Name = "Company II", Users = null },
new Company{ Id = 3, Code = "C03", Name = "Company III", Users = users }
};
IList<Branch> branches = new List<Branch>
{
new Branch{Id = 1, CompanyId = 1, Code="B01", Name = "Branch 1.1"},
new Branch{Id = 2, CompanyId = 1, Code="B02", Name = "Branch 1.2"},
new Branch{Id = 3, CompanyId = 1, Code="B03", Name = "Branch 1.3"},
new Branch{Id = 4, CompanyId = 2, Code="B04", Name = "Branch 2.1"},
new Branch{Id = 5, CompanyId = 2, Code="B05", Name = "Branch 2.2"},
};
var payload = new JwtPayload {
{ "companies", companies },
{ "branches", branches }
};
string key = "eyJjb21wYW5pZXMiOlt7IklkIjoxLCJDb2RlIjoiQzAxIiwiTmFtZSI6IkNvbXBhbnkgSSIsIkJyYW5jaGVzIjpudWxsLCJVc2VycyI6W3siSWQiOjEsIk5hbWUiOiJV";
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
var header = new JwtHeader(credentials);
var secToken = new JwtSecurityToken(header, payload);
var handler = new JwtSecurityTokenHandler();
var tokenString = handler.WriteToken(secToken);
Console.WriteLine(secToken);
Console.WriteLine(tokenString);
return tokenString;
}
Output
{
"companies": [
{
"Id": 1,
"Code": "C01",
"Name": "Company I",
"Branches": null,
"Users": [
{
"Id": 1,
"Name": "User One"
},
{
"Id": 2,
"Name": "User Two"
},
{
"Id": 3,
"Name": "User Three"
}
]
},
{
"Id": 2,
"Code": "C03",
"Name": "Company II",
"Branches": null,
"Users": null
},
{
"Id": 3,
"Code": "C03",
"Name": "Company III",
"Branches": null,
"Users": [
{
"Id": 1,
"Name": "User One"
},
{
"Id": 2,
"Name": "User Two"
},
{
"Id": 3,
"Name": "User Three"
}
]
}
],
"branches": [
{
"Id": 1,
"CompanyId": 1,
"Code": "B01",
"Name": "Branch 1.1"
},
{
"Id": 2,
"CompanyId": 1,
"Code": "B02",
"Name": "Branch 1.2"
},
{
"Id": 3,
"CompanyId": 1,
"Code": "B03",
"Name": "Branch 1.3"
},
{
"Id": 4,
"CompanyId": 2,
"Code": "B04",
"Name": "Branch 2.1"
},
{
"Id": 5,
"CompanyId": 2,
"Code": "B05",
"Name": "Branch 2.2"
}
]
}
Token
eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJjb21wYW5pZXMiOlt7IklkIjoxLCJDb2RlIjoiQzAxIiwiTmFtZSI6IkNvbXBhbnkgSSIsIkJyYW5jaGVzIjpudWxsLCJVc2VycyI6W3siSWQiOjEsIk5hbWUiOiJVc2VyIE9uZSJ9LHsiSWQiOjIsIk5hbWUiOiJVc2VyIFR3byJ9LHsiSWQiOjMsIk5hbWUiOiJVc2VyIFRocmVlIn1dfSx7IklkIjoyLCJDb2RlIjoiQzAzIiwiTmFtZSI6IkNvbXBhbnkgSUkiLCJCcmFuY2hlcyI6bnVsbCwiVXNlcnMiOm51bGx9LHsiSWQiOjMsIkNvZGUiOiJDMDMiLCJOYW1lIjoiQ29tcGFueSBJSUkiLCJCcmFuY2hlcyI6bnVsbCwiVXNlcnMiOlt7IklkIjoxLCJOYW1lIjoiVXNlciBPbmUifSx7IklkIjoyLCJOYW1lIjoiVXNlciBUd28ifSx7IklkIjozLCJOYW1lIjoiVXNlciBUaHJlZSJ9XX1dLCJicmFuY2hlcyI6W3siSWQiOjEsIkNvbXBhbnlJZCI6MSwiQ29kZSI6IkIwMSIsIk5hbWUiOiJCcmFuY2ggMS4xIn0seyJJZCI6MiwiQ29tcGFueUlkIjoxLCJDb2RlIjoiQjAyIiwiTmFtZSI6IkJyYW5jaCAxLjIifSx7IklkIjozLCJDb21wYW55SWQiOjEsIkNvZGUiOiJCMDMiLCJOYW1lIjoiQnJhbmNoIDEuMyJ9LHsiSWQiOjQsIkNvbXBhbnlJZCI6MiwiQ29kZSI6IkIwNCIsIk5hbWUiOiJCcmFuY2ggMi4xIn0seyJJZCI6NSwiQ29tcGFueUlkIjoyLCJDb2RlIjoiQjA1IiwiTmFtZSI6IkJyYW5jaCAyLjIifV19.ysjwBa3YeYNmVB0fVEh95wL0zt8Krb-T4VRpWKWIfbU
So the key to this problem is understanding :) Firs what should be noted is the following escape characters .
That basically made me understand that all I need is proper serialization/deserialization of custom array objects.
So I have created the following as base of each scope
Dictionary<string, List<string>> xx3 = new Dictionary<string, List<string>>()
{
{
"s3",new List<string>()
{
"access1" , "access2"
}
}
};
Then simply serialized this object and added as claim
var cos3 = JsonConvert.SerializeObject(xx3, Formatting.Indented);
identity.AddClaim(new Claim("scopes", cos1));
Now what has left as challenge was appropriate authorization on my resources.So I have added customized AuthorizationFilterAttribute
Within there I have deserialized claims using code from here
For those who would be looking for some more of code this is snippet from my custom filter:
// Check if we have scopes
var AllScopes = principal.Claims.Where(p => p.Type == "scopes");
// Check if we have desired scope
foreach (var singlescope in AllScopes)
{
Dictionary<string, List<string>> userscopes = JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(singlescope.Value);
if (userscopes.Single(kvp => kvp.Key == ScopeName).Value.Contains(ScopeAccess))
{
//User is Authorized, complete execution
return Task.FromResult<object>(null);
}
}
I hope this will help someone!
Here is how I created my complex token:
var securityKey = new InMemorySymmetricSecurityKey(Encoding.Default.GetBytes("401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429090fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1"));
var signingCredentials = new SigningCredentials(securityKey,
SecurityAlgorithms.HmacSha256Signature,
SecurityAlgorithms.Sha256Digest);
var header = new JwtHeader(signingCredentials);
var payload = new JwtPayload();
payload.AddClaims(claims);
payload.Add("tags", _tags.ToArray()); // this guy accepts object!
var token = new JwtSecurityToken(header, payload);
var tokenString = securityTokenHandler.WriteToken(token);
I am trying to create JSON array using Newtonsoft JSON API but its giving me error. I want to achieve structure like
[
{
"id":"26",
"appsurvey":"1",
"fk_curriculumid":"70",
"status":"Completed",
"lastaccessedon":"2014-06-20 09:18:54",
"questions":[
{
"feedback":"6",
"questionid":"1"
},
{
"feedback":"8",
"questionid":"2"
},
{
"feedback":"1",
"questionid":"3"
}
],
"fk_clientid":"24",
"learnerid":"260"
}
]
I want ot add questions array for multiple time but it is giving me error
Can not add property questions to Newtonsoft.Json.Linq.JObject. Property with the same name already exists on object.
Here is my code:
JArray surveytrackingA = new JArray();
/*code to add
[
{"id":"26",
"appsurvey":"1",
"fk_curriculumid":"70",
"status":"Completed",
"lastaccessedon":"2014-06-20 09:18:54"}]
*/
for (int i = 0; i < surveytrackingA.Count; i++)
{
JObject surveytrackD = (JObject)surveytrackingA[i];
string queryOne = "select * from table101 where fk_curriculumid='"
+ surveytrackD["fk_curriculumid"].ToString()
+ "' and fk_surveyid='"
+ surveytrackD["appsurvey"].ToString() + "'";
JArray questionsA = new JArray();
using (var stmt = await App.localDB.PrepareStatementAsync(queryOne))
{
while (await stmt.StepAsync())
{
JObject questionD = new JObject();
questionD.Add("questionid", stmt.GetTextAt(5));
questionD.Add("feedback", stmt.GetTextAt(6));
questionsA.Add(questionD);
}
}
surveytrackD.Add("questions", questionsA); /*error occurred here when second question array is getting inserted in surveyTrackD*/
surveytrackingA.Add(surveytrackD);
}
Can anyone please correct me. Thanks in advance.
Update:
surveytrackD have the json data,
{
"fk_clientid": "24",
"learnerid": "260",
"appsurvey": "1",
"id": "26",
"fk_curriculumid": "70",
"status": "completed",
"lastaccessedon": "2014-06-20 09:18:54"
}
You can achieve the same result (JArray in JArray) using regular C# classes and at the end serialize to JSon.
I posted a sample in Github; here a fragment of the code that produces your expected output:
var Surveys = new List<SurveytrackD>();
Surveys.Add( new SurveytrackD { id = "26", appsurvey = "1", fk_curriculumid = "70", status = "Completed", learnerid = "240" } );
Surveys.Add( new SurveytrackD { id = "27", appsurvey = "1", fk_curriculumid = "71", status = "Completed", learnerid = "241" });
foreach (var survey in Surveys)
{
survey.questions = new List<Question>();
survey.questions.Add(new Question { questionid = "1", feedback = "0" });
survey.questions.Add(new Question { questionid = "2", feedback = "1" });
}
var json = JsonConvert.SerializeObject(Surveys, Formatting.Indented);
Console.WriteLine(json);
The output is:
[
{
"fk_clientid": null,
"learnerid": "240",
"appsurvey": "1",
"id": "26",
"fk_curriculumid": "70",
"status": "Completed",
"lastaccessedon": null,
"questions": [
{
"feedback": "0",
"questionid": "1"
},
{
"feedback": "1",
"questionid": "2"
}
]
},
{
"fk_clientid": null,
"learnerid": "241",
"appsurvey": "1",
"id": "27",
"fk_curriculumid": "71",
"status": "Completed",
"lastaccessedon": null,
"questions": [
{
"feedback": "0",
"questionid": "1"
},
{
"feedback": "1",
"questionid": "2"
}
]
}
]