I'm using the official version 2 of the Constant Contact .net-sdk found here.
I've been unable to find methods for the following:
Creating a Contact List
Adding a contact to a Contact List
Removing a contact from a Contact List
Adding multiple contacts to a Contact List
Creating an Email Campaign
These features clearly exist in v2 of the API found here, but seem missing from the SDK.
Any help in accessing this functionality is appreciated.
Create Contact.
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "<Replace with your oAuth Token>");
ContactObject cont = new ContactObject
{
first_name = "Deepu",
last_name = "Madhusoodanan"
};
var email_addresses = new List<EmailAddress>
{
new EmailAddress{email_address = "deepumi1#gmail.com"}
};
cont.email_addresses = email_addresses;
cont.lists = new List<List>
{
new List {id = "<Replace with your List Id>"}
};
var json = Newtonsoft.Json.JsonConvert.SerializeObject(cont);
string MessageType = "application/json";
using (var request = new HttpRequestMessage(System.Net.Http.HttpMethod.Post, "https://api.constantcontact.com/v2/contacts?api_key=<Replace with your API key>"))
{
request.Headers.Add("Accept", MessageType);
request.Content = new StringContent(json);
request.Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse(MessageType);
using (var response = await client.SendAsync(request).ConfigureAwait(false))
{
string responseXml = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var code = response.StatusCode;
}
request.Content.Dispose();
}
}
}
catch (Exception exp)
{
//log exception here
}
/*Model class*/
public class Address
{
public string address_type { get; set; }
public string city { get; set; }
public string country_code { get; set; }
public string line1 { get; set; }
public string line2 { get; set; }
public string line3 { get; set; }
public string postal_code { get; set; }
public string state_code { get; set; }
public string sub_postal_code { get; set; }
}
public class List
{
public string id { get; set; }
}
public class EmailAddress
{
public string email_address { get; set; }
}
public class ContactObject
{
public List<Address> addresses { get; set; }
public List<List> lists { get; set; }
public string cell_phone { get; set; }
public string company_name { get; set; }
public bool confirmed { get; set; }
public List<EmailAddress> email_addresses { get; set; }
public string fax { get; set; }
public string first_name { get; set; }
public string home_phone { get; set; }
public string job_title { get; set; }
public string last_name { get; set; }
public string middle_name { get; set; }
public string prefix_name { get; set; }
public string work_phone { get; set; }
}
Note : You have to replace oAuth token, API key and List id.
Delete method based on the api document.(http://developer.constantcontact.com/docs/contacts-api/contacts-resource.html?method=DELETE)
Note : I have not tested the delete method yet.
private async Task<string> DeleteContact(string contactId)
{
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "<Replace with your oAuth Token>");
using (var request = new HttpRequestMessage(System.Net.Http.HttpMethod.Delete, "https://api.constantcontact.com/v2/contacts/" + contactId + "?api_key=<Replace with your API key>"))
{
using (var response = await client.SendAsync(request).ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
}
}
}
catch (Exception exp)
{
//log exp here
}
return string.Empty;
}
Here is my solution for adding a contact. What I did was combine the code that Deepu provided with the Constant Contact API v2. I also had to remove async and await references because they are incompatible with VS2010. I have not tried DELETE yet...
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Net.Http;
using CTCT.Components.Contacts;
using System.Net.Http.Headers;
/// <summary>
/// Constant Contact Helper Class for POST, PUT, and DELETE
/// </summary>
public class ConstantContactHelper
{
private string _accessToken = ConfigurationManager.AppSettings["ccAccessToken"];
private Dictionary<string, System.Net.Http.HttpMethod> requestDict = new Dictionary<string, System.Net.Http.HttpMethod> {
{"GET", HttpMethod.Get},
{"POST", HttpMethod.Post},
{"PUT", HttpMethod.Put},
{"DELETE", HttpMethod.Delete}
};
private System.Net.Http.HttpMethod requestMethod = null;
private Dictionary<string, ConstantContactURI> uriDict = new Dictionary<string, ConstantContactURI> {
{"AddContact", new ConstantContactURI("contacts")},
{"AddContactList", new ConstantContactURI("lists")},
{"AddEmailCampaign", new ConstantContactURI("campaigns")},
};
private ConstantContactURI URI_Handler = new ConstantContactURI();
private ContactRequestBody RequestBody = new ContactRequestBody();
private const string messageType = "application/json";
public string jsonRequest = null;
public string responseXml = null;
public string status_code = null;
public ConstantContactHelper() {}
public ConstantContactHelper(string methodKey, string uriKey, string firstName, string lastName, string emailAddress, string listId)
{
this.requestMethod = this.requestDict[methodKey];
this.URI_Handler = this.uriDict[uriKey];
this.RequestBody = new ContactRequestBody(firstName, lastName, emailAddress, listId);
}
// Return Response as a string
public void TryRequest()
{
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", this._accessToken);
var json = Newtonsoft.Json.JsonConvert.SerializeObject(this.RequestBody.contact);
this.jsonRequest = json;
using (var request = new HttpRequestMessage(HttpMethod.Post, this.URI_Handler.fullURI))
{
request.Headers.Add("Accept", messageType);
request.Content = new StringContent(json);
request.Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse(messageType);
using (var response = client.SendAsync(request))
{
this.responseXml = response.Result.Content.ReadAsStreamAsync().ConfigureAwait(false).ToString();
this.status_code = response.Status.ToString();
}
request.Content.Dispose();
}
}
}
catch(Exception exp)
{
// Handle Exception
this.responseXml = "Unhandled exception: " + exp.ToString();
}
}
}
public class ConstantContactURI
{
private const string baseURI = "https://api.constantcontact.com/v2/";
private const string queryPrefix = "?api_key=";
private string _apiKey = ConfigurationManager.AppSettings["ccApiKey"];
public string fullURI = null;
public ConstantContactURI() {}
public ConstantContactURI(string specificPath)
{
this.fullURI = baseURI + specificPath + queryPrefix + _apiKey;
}
}
public class ContactRequestBody
{
public Contact contact = new Contact();
private List<EmailAddress> email_addresses = new List<EmailAddress>()
{
new EmailAddress{
EmailAddr = "",
Status = Status.Active,
ConfirmStatus = ConfirmStatus.NoConfirmationRequired
}
};
private List<ContactList> lists = new List<ContactList>()
{
new ContactList {Id = ""}
};
public ContactRequestBody() { }
public ContactRequestBody(string firstName, string lastName, string emailAddress, string listId)
{
this.contact.FirstName = firstName;
this.contact.LastName = lastName;
this.email_addresses[0].EmailAddr = emailAddress;
this.contact.EmailAddresses = this.email_addresses;
this.lists[0].Id = listId;
this.contact.Lists = this.lists;
}
}
An Example call from an aspx.cs page looks like this:
ConstantContactHelper requestHelper = new ConstantContactHelper("POST", "AddContact", firstName.Text, lastName.Text, emailBox.Text, listId);
requestHelper.TryRequest();
lbTest.Text = requestHelper.jsonRequest + ", status code:" + requestHelper.status_code + ", xml:" + requestHelper.responseXml;
Related
In my ASP.NET Core-6 Web API, I have an external API to consume. I am to validate the account using a parameter, register the user if not in existence, then Login with the same detail.
API:
https://api.thirdpartycompany.com/UserAccount/api/CustomerDetail?userName=
First, it checks if the customer exists in the external API using userName as parameter.
public class GetCustomerDetailDto
{
public class CustomerDetail
{
public string FirstName { get; set; }
public object LastName { get; set; }
public string UserName { get; set; }
public string EmailAddress { get; set; }
}
}
I validated the third party API using this method:
interface:
public interface IDataUtil
{
CustomerDetail GetCustomerDetail(string userName);
}
Implementation:
public class DataUtil : IDataUtil
{
private readonly IConfiguration _config;
private readonly ILogger<DataUtil> _logger;
private readonly HttpClient _myClient;
public DataUtil
(
IConfiguration config,
ILogger<DataUtil> logger,
HttpClient myClient
)
{
_config = config;
_logger = logger;
_myClient = myClient;
}
public CustomerDetail GetCustomerDetail(string userName)
{
var responseResults = new CustomerDetail();
_logger.LogError($"responseResults: " + responseResults);
try
{
string custAccountNoUrl = _config.GetSection("Endpoints").GetValue<string>("custAccountDetailUrl") + userName;
_myClient.DefaultRequestHeaders.Accept.Clear();
_myClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = _myClient.GetAsync(custAccountNoUrl).Result;
if (response.IsSuccessStatusCode)
{
var stringResult = response.Content.ReadAsStringAsync().Result;
responseResults = JsonConvert.DeserializeObject<CustomerDetail>(stringResult);
}
}
catch (Exception ex)
{
_logger.LogError($"An Error occured " + ex.ToString());
}
return responseResults;
}
}
I have these Auth DTOs:
public class UserDto
{
public string Id { get; set; }
public string FirstName { get; set; }
public string Lastname { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
public DateTime LastLogin { get; set; }
}
public class LoginRequestDto
{
[Required(ErrorMessage = "The username is required!")]
public string UserName { get; set; }
[Required(ErrorMessage = "The password is required!")]
public string Password { get; set; }
}
public class LoginResponseDto
{
public string JwtToken { get; set; }
public UserDto User { get; set; }
public DateTime Expires { get; set; }
}
public class RegistrationRequestDto
{
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Model:
public class AppUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime LastLogin { get; set; }
}
And now the AuthService.
IAuthService:
public interface IAuthService
{
Task<GenericResponseDto<object>> LoginUser(LoginRequestDto request);
Task<GenericResponseDto<UserDto>> CreateUserAsync(RegistrationRequestDto requestDto);
}
AuthService:
private async Task<GenericResponseDto<UserDto>> CreateUserAsync(RegistrationRequestDto requestDto)
{
var response = new GenericResponseDto<UserDto>();
var existingUser = await _userManager.FindByNameAsync(requestDto.UserName);
if (existingUser == null)
{
var userDetail = _dataUtil.GetCustomerDetail(requestDto.UserName);
var user = new AppUser()
{
UserName = userDetail.UserName.ToLower().Trim(),
Email = userDetail.EmailAddress.Trim().ToLower(),
FirstName = userDetail.FirstName.Trim(),
LastName = userDetail.LastName.Trim(),
CreatedAt = DateTime.Now
};
user.SecurityStamp = Guid.NewGuid().ToString();
var result = await _userManager.CreateAsync(user, "Adminpass1");
if (!result.Succeeded)
{
var error = string.Join<IdentityError>(", ", result.Errors.ToArray());
response.Error = new ErrorResponseDto { ErrorCode = 500, Message = "Failed to create user because of the following errors: " + error };
}
else
{
response.StatusCode = 200;
response.Result = _mapper.Map<UserDto>(user);
}
} else
{
response.Error = new ErrorResponseDto { ErrorCode = 400, Message = "This email is already registered!" };
response.StatusCode = 400;
}
return response;
}
public async Task<GenericResponseDto<object>> LoginUser(LoginRequestDto request)
{
var user = await _userManager.FindByNameAsync(request.UserName);
var response = new GenericResponseDto<object>();
if (user != null && await _userManager.CheckPasswordAsync(user, request.Password))
{
var roles = await _userManager.GetRolesAsync(user);
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
foreach (var userRole in roles)
{
authClaims.Add(new Claim(ClaimTypes.Role, userRole));
}
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Secret"]));
var token = new JwtSecurityToken(
issuer: _configuration["JWT:ValidIssuer"],
audience: _configuration["JWT:ValidAudience"],
expires: DateTime.Now.AddHours(3),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
response.Result = new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
user = _mapper.Map<UserDto>(user),
expires = token.ValidTo
};
response.StatusCode = 200;
user.LastLogin = DateTime.Now;
try
{
await _context.SaveChangesAsync();
}catch(Exception ex)
{
response.Error = new ErrorResponseDto() { ErrorCode = 500, Message = ex.Message };
}
return response;
}
response.StatusCode = 400;
response.Error = new ErrorResponseDto { ErrorCode = 400, Message = "Invalid email or password!" };
return response;
}
In the application, users are not allowed to register manually.
So far, I have created the LoginUser and CreateUserAsync methods.
What I want to achieve is that, when the user tries to login the application checks if username already exists. If yes, it logs in, if no it checks from the external API using UserName as parameter, gets the user data, register the user using CreateUserAsync. Then automatically re-login the user.
How do I achieve this?
NOTE: I am using IdentityDB and EntityFramework
Thanks
I'm having an error in Xamarin Forms I tried to deserialize the object does anyone know What did I do wrong here?
This is my method
private async void GetEmployee()
{
var _token = await GetAccessToken();
//List<D365Employee> Employee = null;
using (var _clientD365 = new HttpClient())
{
var _uri = "domain here";
_client.BaseAddress = new Uri(_uri);
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token);
var _response = await _clientD365.GetAsync("my endpoint here");
var Emp = JsonConvert.DeserializeObject<List<Employee>>(_response.Content.ReadAsStringAsync().Result);
Employee = new ObservableCollection<Employee>(Emp);
}
}
This is my Model
public class Employee
{
[JsonProperty("#odata.etag")]
public string Context { get; set; }
public IList<EmployeeDetails> Value { get; set; }
}
public class EmployeeDetails
{
public string PersonnelNumber { get; set; }
public string EmploymentLegalEntityId { get; set; }
public string DimensionDisplayValue { get; set; }
}
This is the JSON I try to parse
{
"#odata.context": "https://employee.dynamics.com/data/$metadata#Employees(PersonnelNumber,EmploymentLegalEntityId,DimensionDisplayValue)",
"value": [
{
"#odata.etag": "W/\"JzEsNTYzNzE0NDYwMzsxNDg2NTk2NzY0LDU2MzcxNDc2OTM7MSw1NjM3MTQ0NjAzOzEsNTYzNzE0NDYwMzsxLDU2MzcxNDczNzE7MCwwOzAsMDsyNTY0OTEwODksNTYzwJw==\"",
"PersonnelNumber": "ID111028",
"EmploymentLegalEntityId": "OOP",
"DimensionDisplayValue": "----",
}
]
}
That JSON is a single object, not a list, so you need to deserialize it as a single object.
var Emp = JsonConvert.DeserializeObject<Employee>(await _response.Content.ReadAsStringAsync());
I'm writing a code to read values from a table storage. The code is similar to printing nodes in a tree level by level.
eg:
root
Level1child1 -> Level1child2 -> Level1child3
string tablename = "<table-name">;
string storageAccountName = "<storage-account-name";
var baseurl = #$"https://{storageAccountName}.table.core.windows.net/{tableName}()";
var sastoken = getAccountSASToken();
string filter = #"&$filter=PartitionKey%20eq%20'123'%20and%20RowKey%20eq%20'abc'";
baseurl = $"{baseurl}{sastoken}{filter}";
var data = HttpHelper.GetForOData(baseurl);
var responseData = data.Data.Replace(".", "_");
var odata = JsonConvert.DeserializeObject<ODataResponse>(responseData);
Queue<int> strQ = new Queue<int>();
Console.WriteLine(odata.value[0].Email);
strQ.Enqueue(odata.value[0].TreeNodeID);
while (strQ.Any())
{
var url = #$"https://{storageAccountName}.table.core.windows.net/{tableName}()";
var token = _tableStorageRepository.GetAccountSASToken();
filter = #"&$filter=ParentNodeId%20eq%20" + strQ.Peek();
url = $"{url}{token}{filter}";
data = HttpHelper.GetForOData(url);
responseData = data.Data.Replace(".", "_");
odata = JsonConvert.DeserializeObject<ODataResponse>(responseData);
foreach (var m in odata?.value)
{
Console.WriteLine(m.Email);
strQ.Enqueue(m.TreeNodeID);
}
strQ.Dequeue();
}
public class ODataResponse
{
public string odata_metadata { get; set; }
public List<ODatavalue> value { get; set; }
}
public class ODatavalue
{
public string odata_type { get; set; }
public string odata_id { get; set; }
public string odata_etag { get; set; }
public string odata_editLink { get; set; }
public string RowKey { get; set; }
public string Email { get; set; }
public int ParentNodeID { get; set; }
public int TreeNodeID { get; set; }
}
Code for HttpHelper class: https://github.com/xyz92/httphelper/blob/master/HttpHelper.cs
The first time when I ran this code, it only printed root node.
The second time when I ran this code, it printed root node and Level1child1 node.
For the next runs, it printed root node, Level1child1 node & Level1child2 node.
The last node Level1child3 node is getting printed very rarely on some runs.
What am I missing in this code?
UPDATE:
Sample responseData:
{
"odata_metadata": "https://<storage-account-name>_table_core_windows_net/$metadata#<table-name>",
"value": [{
"odata_type": "<storage-account-name>_<table-name>",
"odata_id": "https://<storage-account-name>_table_core_windows_net/<table-name>(PartitionKey='123',RowKey='abc')",
"odata_etag": "W/\"datetime'2020-09-01T16%3A34%3A21_3342187Z'\"",
"odata_editLink": "<table-name>(PartitionKey='123',RowKey='abc')",
"PartitionKey": "123",
"RowKey": "abc",
"Timestamp#odata_type": "Edm_DateTime",
"Timestamp": "2020-09-01T16:34:21_3342187Z",
"Email": "email",
"ParentNodeID": 1,
"TreeNodeID": 2
}
]
}
Table columns:
Sample data in Table:
Sample outputs while running code:
According to my test, I cannot reproduce your issue in my environment. My test is as below
Table columns:
Sample data in table
Code I use your HttpHelper class to send request
class Program
{
static async Task Main(string[] args)
{
string storageAccountName = "andyprivate" ;
string tableName = "test";
var baseurl = #$"https://{storageAccountName}.table.core.windows.net/{tableName}()";
var sastoken = "";
string filter = #"&$filter=PartitionKey%20eq%20'123'%20and%20RowKey%20eq%20'abc'";
baseurl = $"{baseurl}{sastoken}{filter}";
var data = HttpHelper.GetForOData(baseurl);
var responseData = data.Data.Replace(".", "_");
var odata = JsonConvert.DeserializeObject<ODataResponse>(responseData);
Queue<int> strQ = new Queue<int>();
Console.WriteLine("----root----");
Console.WriteLine(odata.value[0].Email);
strQ.Enqueue(odata.value[0].TreeNodeID);
while (strQ.Any())
{
int i = 0;
var url = #$"https://{storageAccountName}.table.core.windows.net/{tableName}()";
var token = "";
filter = #$"&$filter=ParentNodeID eq {strQ.Peek()}";
url = $"{ url}{token}{filter}";
data = HttpHelper.GetForOData(url);
responseData = data.Data.Replace(".", "_");
odata = JsonConvert.DeserializeObject<ODataResponse>(responseData);
Console.WriteLine($"----TreeNode{strQ.Peek()}----");
foreach (var m in odata?.value)
{
if (i == 0) {
strQ.Enqueue(m.TreeNodeID);
i = 1;
}
Console.WriteLine(m.Email);
}
strQ.Dequeue();
}
Console.ReadLine();
}
}
public class ODataResponse
{
public string odata_metadata { get; set; }
public List<ODatavalue> value { get; set; }
}
public class ODatavalue
{
public string odata_type { get; set; }
public string odata_id { get; set; }
public string odata_etag { get; set; }
public string odata_editLink { get; set; }
public string RowKey { get; set; }
public string Email { get; set; }
public int ParentNodeID { get; set; }
public int TreeNodeID { get; set; }
}
Update
My test code
Rest API (I use your HttpHelper class to send request)
class Program
{
static async Task Main(string[] args)
{
string storageAccountName = "andyprivate" ;
string tableName = "test";
var baseurl = #$"https://{storageAccountName}.table.core.windows.net/{tableName}()";
var sastoken = "";
string filter = #"&$filter=PartitionKey%20eq%20'123'%20and%20RowKey%20eq%20'abc'";
baseurl = $"{baseurl}{sastoken}{filter}";
var data = HttpHelper.GetForOData(baseurl);
var responseData = data.Data.Replace(".", "_");
var odata = JsonConvert.DeserializeObject<ODataResponse>(responseData);
Queue<int> strQ = new Queue<int>();
Console.WriteLine("----root----");
Console.WriteLine(odata.value[0].Email);
strQ.Enqueue(odata.value[0].TreeNodeID);
while (strQ.Any())
{
int i = 0;
var url = #$"https://{storageAccountName}.table.core.windows.net/{tableName}()";
var token = "";
filter = #$"&$filter=ParentNodeID eq {strQ.Peek()}";
url = $"{ url}{token}{filter}";
data = HttpHelper.GetForOData(url);
responseData = data.Data.Replace(".", "_");
odata = JsonConvert.DeserializeObject<ODataResponse>(responseData);
Console.WriteLine($"----TreeNode{strQ.Peek()}----");
foreach (var m in odata?.value)
{
if (i == 0) {
strQ.Enqueue(m.TreeNodeID);
i = 1;
}
Console.WriteLine(m.Email);
}
strQ.Dequeue();
}
Console.ReadLine();
}
}
public class ODataResponse
{
public string odata_metadata { get; set; }
public List<ODatavalue> value { get; set; }
}
public class ODatavalue
{
public string odata_type { get; set; }
public string odata_id { get; set; }
public string odata_etag { get; set; }
public string odata_editLink { get; set; }
public string RowKey { get; set; }
public string Email { get; set; }
public int ParentNodeID { get; set; }
public int TreeNodeID { get; set; }
}
SDK. I use the package Microsoft.Azure.Cosmos.Table
string storageAccountName = "andyprivate";
string accountKey ="";
string tableName = "test";
CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(storageAccountName, accountKey), true);
CloudTableClient tableClient = storageAccount.CreateCloudTableClient(new TableClientConfiguration());
CloudTable table = tableClient.GetTableReference(tableName);
TableOperation retrieveOperation = TableOperation.Retrieve<CustomEntity>("123", "abc");
TableResult result = await table.ExecuteAsync(retrieveOperation);
CustomEntity entity = result.Result as CustomEntity;
Queue<int> strQ = new Queue<int>();
Console.WriteLine("----root----");
Console.WriteLine(entity.Email);
strQ.Enqueue(entity.TreeNodeID);
while (strQ.Any()) {
int i = 0;
TableQuery<CustomEntity> query = new TableQuery<CustomEntity>()
.Where(
TableQuery.GenerateFilterConditionForInt("ParentNodeID", QueryComparisons.Equal,strQ.Peek())
);
Console.WriteLine($"----TreeNode{strQ.Peek()}----");
foreach (CustomEntity m in table.ExecuteQuery(query) ) {
Console.WriteLine(m.Email);
if (i == 0) {
strQ.Enqueue(m.TreeNodeID);
i = 1;
}
}
strQ.Dequeue();
}
I am calling the API for creating a meeting on a fixed date & time. I am using Microsoft Graph API for this. Here is the URL
var url = "https://graph.microsoft.com/v1.0/me/events";
I have taken care of the Authentication part and my code does the following thing to send the JSON response to the API
private async void sendInvites_Click(object sender, RoutedEventArgs e)
{
var httpClient = new System.Net.Http.HttpClient();
System.Net.Http.HttpResponseMessage response;
var url = "https://graph.microsoft.com/v1.0/me/events";
CIBC.Models.SendMeetingInvites.RootObject obj = new CIBC.Models.SendMeetingInvites.RootObject();
CIBC.Models.SendMeetingInvites.Location loc = new CIBC.Models.SendMeetingInvites.Location();
loc.displayName = GlobalVariables.MeetingRoomName;
//loc.RoomEmailAddress = GlobalVariables.meetingRoomEmailID.ToString();
obj.subject = "Maths";
CIBC.Models.SendMeetingInvites.Body body = new CIBC.Models.SendMeetingInvites.Body();
body.content = "Its a booking for follow up meeting";
body.contentType = "HTML";
obj.body = body;
List<CIBC.Models.SendMeetingInvites.Attendee> attens = new List<Models.SendMeetingInvites.Attendee>();
for(int i=0;i<GlobalVariables.NumberOfParticipant.Count;i++)
{
CIBC.Models.SendMeetingInvites.EmailAddress email = new CIBC.Models.SendMeetingInvites.EmailAddress();
CIBC.Models.SendMeetingInvites.Attendee atten = new CIBC.Models.SendMeetingInvites.Attendee();
email.address = GlobalVariables.NumberOfParticipant[i].ParticipantADdress;
atten.emailAddress = email;
atten.type = "Required";
attens.Add(atten);
}
CIBC.Models.SendMeetingInvites.Start start = new CIBC.Models.SendMeetingInvites.Start();
start.dateTime = GlobalVariables.sendMeetingInviteStartDate;
start.timeZone = "UTC";
obj.start = start;
CIBC.Models.SendMeetingInvites.End end = new CIBC.Models.SendMeetingInvites.End();
end.dateTime = GlobalVariables.sendMeetingInviteEndTime;
end.timeZone = "UTC";
obj.end = end;
obj.attendees = attens;
obj.location = loc;
string postBody = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
// var postBody1 = "{'Subject':'Testing Organizer - 12','Location':{'DisplayName':'Some place'}," +
//"'Start': {'DateTime': '2016-07-15T15:00:00.0000000', 'TimeZone':'UTC'}," +
//"'End': {'DateTime': '2016-07-15T15:30:00.0000000', 'TimeZone':'UTC'}," +
//"'Body':{'Content': 'This is a test of Grap API.', 'ContentType':'Text'}," +
//"'IsOrganizer':'False','Organizer':{'EmailAddress': " + "{'Address':'organizer#some.com'} }}";
// var requestString = #"{"subject":"My event","start":{"dateTime":"2017-09-25T07:44:27.448Z","timeZone":"UTC"},"end":{"dateTime":"2017-10-02T07:44:27.448Z","timeZone":"UTC"}}"";
var request = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Post, url);
//Add the token in Authorization header
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer",GlobalVariables.Token);
request.Content = new StringContent(postBody, UTF8Encoding.UTF8, "application/json");
response = await httpClient.SendAsync(request);
if (response.IsSuccessStatusCode)
{ }
// return await response.Content.ReadAsStringAsync();
else
{
}
//return "";
}
Here is the class file that I am using to pass to the HTTPResponse Message
namespace CIBC.Models.SendMeetingInvites
{
public class Body
{
public string contentType { get; set; }
public string content { get; set; }
}
public class Start
{
public DateTime dateTime { get; set; }
public string timeZone { get; set; }
}
public class End
{
public DateTime dateTime { get; set; }
public string timeZone { get; set; }
}
public class Location
{
public string displayName { get; set; }
//public string RoomEmailAddress { get; set; }
}
public class EmailAddress
{
public string address { get; set; }
public string name { get; set; }
}
public class Attendee
{
public EmailAddress emailAddress { get; set; }
public string type { get; set; }
}
public class RootObject
{
public string subject { get; set; }
public Body body { get; set; }
public Start start { get; set; }
public End end { get; set; }
public Location location { get; set; }
public List<Attendee> attendees { get; set; }
}
}
My requirement is to send a meeting invite to all the users and also mentioning the Room Details like Name& Email ID of the room.
I tried adding a RoomEmail address in the Request as under The Location class
public string RoomEmailAddress { get; set; }
When I tested this using Microsoft Graph Explorer website , i got the error message
{
"error": {
"code": "RequestBodyRead",
"message": "The property 'RoomEmailAddress' does not exist on type 'Microsoft.OutlookServices.Location'. Make sure to only use
property names that are defined by the type or mark the type as open
type.",
"innerError": {
"request-id": "1883d87d-a5d6-4357-a699-7c112da0e56b",
"date": "2017-09-26T12:03:50"
}
} }
How do I make sure that whenever I create a meeting request , I can assign a room to it?
Currently I am just able to pass DisplayName while sending the Request to the URL.
Once I remove the Email Address property (I added myself ), the code returns Success.
Any workarounds so that I can send the room email address also so that the room also receives a copy of the meeting invite ?
Add the room as an attendee with "type": "Resource". Then add the room's display name in the location property.
I have successfully deployed on model on Cloud ML Engine and verified it is working with gcloud ml-engine models predict by following the instructions, now I want to send predictions to it from my C# app. How do I do that?
The online prediction API is a REST API, so you can use any library for sending HTTPS requests, although you will need to use Google's OAuth library to get your credentials.
The format of the request is JSON, as described in the docs.
To exemplify, consider the Census example. A client for that might look like:
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Google.Apis.Auth.OAuth2;
using Newtonsoft.Json;
namespace prediction_client
{
class Person
{
public int age { get; set; }
public String workclass { get; set; }
public String education { get; set; }
public int education_num { get; set; }
public string marital_status { get; set; }
public string occupation { get; set; }
public string relationship { get; set; }
public string race { get; set; }
public string gender { get; set; }
public int capital_gain { get; set; }
public int capital_loss { get; set; }
public int hours_per_week { get; set; }
public string native_country { get; set; }
}
class Prediction
{
public List<Double> probabilities { get; set; }
public List<Double> logits { get; set; }
public Int32 classes { get; set; }
public List<Double> logistic { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
class MainClass
{
static PredictClient client = new PredictClient();
static String project = "MY_PROJECT";
static String model = "census"; // Whatever you deployed your model as
public static void Main(string[] args)
{
RunAsync().Wait();
}
static async Task RunAsync()
{
try
{
Person person = new Person
{
age = 25,
workclass = " Private",
education = " 11th",
education_num = 7,
marital_status = " Never - married",
occupation = " Machine - op - inspct",
relationship = " Own - child",
race = " Black",
gender = " Male",
capital_gain = 0,
capital_loss = 0,
hours_per_week = 40,
native_country = " United - Stats"
};
var instances = new List<Person> { person };
List<Prediction> predictions = await client.Predict<Person, Prediction>(project, model, instances);
Console.WriteLine(String.Join("\n", predictions));
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
class PredictClient {
private HttpClient client;
public PredictClient()
{
this.client = new HttpClient();
client.BaseAddress = new Uri("https://ml.googleapis.com/v1/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<List<O>> Predict<I, O>(String project, String model, List<I> instances, String version = null)
{
var version_suffix = version == null ? "" : $"/version/{version}";
var model_uri = $"projects/{project}/models/{model}{version_suffix}";
var predict_uri = $"{model_uri}:predict";
GoogleCredential credential = await GoogleCredential.GetApplicationDefaultAsync();
var bearer_token = await credential.UnderlyingCredential.GetAccessTokenForRequestAsync();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearer_token);
var request = new { instances = instances };
var content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var responseMessage = await client.PostAsync(predict_uri, content);
responseMessage.EnsureSuccessStatusCode();
var responseBody = await responseMessage.Content.ReadAsStringAsync();
dynamic response = JsonConvert.DeserializeObject(responseBody);
return response.predictions.ToObject<List<O>>();
}
}
}
You may have to run gcloud auth login to initialize your credentials before running locally, if you haven't already.