I have successfully added single appointment using this code now i want to add multiple appointment pro grammatically in a single loop.for example i want to add 5 appointment at a time using loop where dates for every appointment is available in a List.
Thanks in advance :)
SaveAppointmentTask saveAppointmentTask = new SaveAppointmentTask();
saveAppointmentTask.StartTime = nearestDate;
saveAppointmentTask.EndTime = nearestDate.AddMinutes(3) ;
saveAppointmentTask.Subject = "Meet Ali"; // appointment subject
saveAppointmentTask.Location = "In Office"; // appointment location
saveAppointmentTask.Details = "Meet Ali to discuss product launch";//appointment details
saveAppointmentTask.IsAllDayEvent = false;
saveAppointmentTask.Reminder = Microsoft.Phone.Tasks.Reminder.FifteenMinutes;
saveAppointmentTask.AppointmentStatus = Microsoft.Phone.UserData.AppointmentStatus.OutOfOffice;
saveAppointmentTask.Show();
use this code as Navigated To event is all the time called when you land up in the page
private SaveAppointmentTask saveAppointmentTask;
private List<int> listMinutes = new List<int>();
// Constructor
public MainPage()
{
InitializeComponent();
for (int i = 0; i < 10; i++) {
listMinutes.Add(i);
}
}
int countAdded = 0;
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if (countAdded < 10)
{
saveAppointmentTask = new SaveAppointmentTask();
saveAppointmentTask.StartTime = DateTime.Now.AddMinutes(listMinutes[countAdded]);
saveAppointmentTask.EndTime = saveAppointmentTask.StartTime.Value.AddMinutes(2);
saveAppointmentTask.Subject = "Meet Ali"; // appointment subject
saveAppointmentTask.Location = "In Office"; // appointment location
saveAppointmentTask.Details = "Meet Ali to discuss product launch";//appointment details
saveAppointmentTask.IsAllDayEvent = false;
saveAppointmentTask.Reminder = Microsoft.Phone.Tasks.Reminder.FifteenMinutes;
saveAppointmentTask.AppointmentStatus = Microsoft.Phone.UserData.AppointmentStatus.OutOfOffice;
countAdded++;
saveAppointmentTask.Show();
}
else {
// do not add anything
}
}
save i that is the count in some application state or a tokes so that you can know if you have added the events :) Appplication.Current.Resources.Add("token", "number added")
Thanks
You cannot automatically save all appointments. You would have to launch the task in each iteration, and user interaction would be nedded in each.
A possible option is to use the Live Connect API. That would allow you to programatically create apointments in user's Live calendar:
Interacting with calendars (Live Connect API)
This way you don't interact with the phone calendar, but the users's Live calendar, which can be synchronized in the phone. Of course, the user will need to authenticate.
Related
Everything is already setup on the google calendar api (not sure if i configure correctly or i missed something out)
I created a c# console application,that writes an appointment to google calendar.
What i want to achieve is that , i want to get all the user's or subscriber who subscribe to my app, so what i can write
on there calendar if there is an event.
What configuration do i need?
That's actually a multi-domain problem.
Some questions to consider:
What calender is it? A public one?
How do they subscribe with your console?
What happens when the software shuts down, crashes, etc?
Do you need to know the event after it was written to the calendars?
If not, do new subscriber get previously added calender entries?
Other than that, you should have a look at Webclient. Then we have here the reference for the Google Calendar API. The main request method you're searching is this one: Events Insert. With that, we can craft our own inseration variant.
```
private readonly List<string> _calendarIDs;
/* lets assume you imported webrequests and you're going to write a method
* Further we assume, you have a List of calendars as object attribute
*/
public void InsertEntry(DateTime start, DateTime end,
string title, string description) {
using(var client = new WebClient()) {
var epochTicks = new DateTime(1970, 1, 1);
var values = new NameValueCollection();
values["attachements[].fileUrl"] = "";
values["attendees[].email"] = "";
values["end.date"] = end.ToString("yyyy-MM-dd");
values["end.dateTime"] = (end - epoch).Seconds;
values["reminders.overrides[].minutes"] = 0;
values["start.date"] = start.ToString("yyyy-MM-dd");
values["start.dateTime"] = (start - epoch).Seconds;
values["summary"] = title; // This is the calendar entrys title
values["description"] = description;
foreach(string calendarID in _calendarIDs) {
var endpoint = String.Format("https://www.googleapis.com/calendar/v3/calendars/{0}/events", calendarID)
var response = client.UploadValues(endpoint, values);
var responseString = Encoding.Default.GetString(response);
}
}
This is a minimal example and the api has a lot of endpoints and parameter. You should have a deep look into it, maybe you find more useful parameter.
Below is the sample code,
GoogleCalendarUtils utils = new GoogleCalendarUtils();
ArrayList months = /* the list of months*/;
// Update the content window.
foreach( ThistleEventMonth month in months )
{
foreach( ThistleEvent thistleEvent in month.ThistleEvents )
{
utils.InsertEntry( thistleEvent );
}
}
I'm experimenting with the new WinRT Appointments API in Windows 8.1, based on a sample provided on the MSDN website of Microsoft: http://code.msdn.microsoft.com/windowsapps/Appointments-API-sample-2b55c76e
It works great and I can add appointments without a hassle, but there's always a confirmation by the user involved when using the method ShowAddAppointmentAsync from the Windows.ApplicationModel.Appointments.AppointmentManager namespace, which shows the Appointments provider Add Appointment UI.
I'm looking for a solution to add a larger collection of appointments in the default Windows 8 calendar, WITHOUT the confirmation for each individual appointment in the collection. Is there a way to get around this and bulk insert appointments? Maybe the Windows Live SDK?
Its true that the API prompts the user before saving, but there is a provision to achieve this.
var appointment = new Windows.ApplicationModel.Appointments.Appointment();
appointment.details = "This is a dummy appointment";
appointment.reminder = 15000;
appointment.subject = "TEST APPPOINTMENT";
var x = new Windows.ApplicationModel.Appointments.AppointmentManager.requestStoreAsync(Windows.ApplicationModel.Appointments.AppointmentStoreAccessType.appCalendarsReadWrite).done(function (apppointmentStore) {
apppointmentStore.createAppointmentCalendarAsync("TEST CALENDAR").done(function (calendar) {
calendar.saveAppointmentAsync(appointment);
});
})
Here you're an example to do it using C#
private AppointmentCalendar currentAppCalendar;
private AsyncLazy<AppointmentStore> lazyAppointmentStore = new AsyncLazy<AppointmentStore>(async () =>
{
var appStore = await AppointmentManager.RequestStoreAsync(AppointmentStoreAccessType.AppCalendarsReadWrite);
return appStore;
});
private AppointmentStore AppStore { get { return lazyAppointmentStore.Value.Result; } }
public AppointmentService()
{
}
public async Task CreateCalendar()
{
IReadOnlyList<AppointmentCalendar> appCalendars =
await AppStore.FindAppointmentCalendarsAsync(FindAppointmentCalendarsOptions.IncludeHidden);
AppointmentCalendar appCalendar = null;
// Apps can create multiple calendars. Here app creates only one.
if (appCalendars.Count == 0)
{
appCalendar = await AppStore.CreateAppointmentCalendarAsync(Constants.CalendarName);
}
else
{
appCalendar = appCalendars[0];
}
appCalendar.OtherAppReadAccess = AppointmentCalendarOtherAppReadAccess.Full;
appCalendar.OtherAppWriteAccess = AppointmentCalendarOtherAppWriteAccess.SystemOnly;
// This app will show the details for the appointment. Use System to let the system show the details.
appCalendar.SummaryCardView = AppointmentSummaryCardView.App;
await appCalendar.SaveAsync();
currentAppCalendar = appCalendar;
}
public async Task<bool> CreateNewAppointment(Data.Schemas.Task task)
{
if (null == task)
throw new ArgumentNullException("task");
Appointment newAppointment = new Appointment();
this.SaveAppointmentData(task, newAppointment);
try
{
// Show system calendar to the user to be edited
string appointmentId = await AppointmentManager.ShowAddAppointmentAsync(newAppointment, Windows.Foundation.Rect.Empty);
return ! string.IsNullOrWhiteSpace(appointmentId);
// Just save the appointment
// await currentAppCalendar.SaveAppointmentAsync(newAppointment);
// return true;
}
catch
{
return false;
}
}
Check my post, to know more about AsyncLazy.
I hope this help you.
Regards.
Juanlu
This is not possible, by using the WinRT appointments API.
A user interaction is always required. It was a design decision by MS that some actions require user interaction and this is one of it.
As stated by #Ken Tucker, you can use the windows live api to create appointments but this requires the user of your app to sing in to windows live and grat it the required permissions.
I'm developing an outbound call system that shows the user the next company to call with a means to add an appointment for a selected sales rep.
I initially programmed the appointment to be sent in real time as the user saves the current data and move to the next lead. However, there was a significant delay while the appointment was being sent to the email account on Office 365. So I decided to create a small app to send them in batch every 15 minutes.
This works great for the first three appointments, but then I get an error on the 4th appointment:
The Autodiscover service couldn't be located.
I'm suspecting this is something like a hosting company stopping a mailbox from being used for bulk email and there is a limit. Is there something within EWS to allow more than three at a time? Or do I need to amend my code?
Here is my code for sending the appointments:
const string o365Server = "mydomain.co.uk";
var appointmenntList = AppointmentList.GetAppointnmetsToSend();
ExchangeService service = new ExchangeService();
foreach (var appointment in appointmenntList)
{
Console.WriteLine(appointment.IntLeadID);
service.Credentials = new WebCredentials(appointment.StrSalesRepEmail, apointment.StrSalesRepEmailPassword, o365Server);
service.AutodiscoverUrl(appointment.StrSalesRepEmail, RedirectionCallback);
Appointment app = new Appointment(service);
app.Subject = "ASH Waste Appointment with " + appointment.StrLeadAppointmentContact;
app.Body = appointment.StrLeadAppointmentNotes;
app.Start = appointment.DtLeadAppointmentDate;
app.End = app.Start.AddHours(1);
app.Location = appointment.StrLeadAppointmentLocation;
app.RequiredAttendees.Add(appointment.StrSalesRepEmail);
app.ReminderMinutesBeforeStart = 60;
app.Save(SendInvitationsMode.SendOnlyToAll);
Console.WriteLine(appointment);
}
static bool RedirectionCallback(string url)
{
return url.ToLower().StartsWith("https://");
}
I could set the app to do only three at a time and run the app every 2 minutes. Although this would be enough for our sales team, it is limiting the operation.
Any suggestions?
Edit:
Here's the full error:
An unhandled exception of type
Microsoft.Exchange.WebServices.Data.AutodiscoverLocalException'
occurred in Microsoft.Exchange.WebServices.dll
and it occurs on this line of code:
service.AutodiscoverUrl(appointment.StrSalesRepEmail, RedirectionCallback);
I can batch 4 calendar items when using the CreateItems method instead. Have you tried that? Here's some sample code.
public static Collection<ItemId> BatchCreateCalendarItems(ExchangeService service)
{
// These are unsaved local instances of an Appointment object.
// Despite the required parameter of an ExchangeService object (service), no call
// to an Exchange server is made when the objects are instantiated.
// A call to the Exchange server is made when the service.CreateItems() method is called.
Appointment appt1 = new Appointment(service);
Appointment appt2 = new Appointment(service);
Appointment appt3 = new Appointment(service);
Appointment appt4 = new Appointment(service);
// Set the properties for a single instance appointment
appt1.Subject = "Appt1";
appt1.Body = "Appt1";
appt1.Start = DateTime.Now.AddDays(1);
appt1.End = appt1.Start.AddHours(3);
appt1.Location = "My office";
appt1.ReminderMinutesBeforeStart = 30;
// Set the properties for a single instance appointment
appt2.Subject = "Appt2";
appt2.Body = "Appt2";
appt2.Start = DateTime.Now.AddDays(1);
appt2.End = appt1.Start.AddHours(4);
appt2.Location = "My office";
appt2.ReminderMinutesBeforeStart = 30;
// Set the properties for a single instance appointment
appt3.Subject = "Appt3";
appt3.Body = "Appt3";
appt3.Start = DateTime.Now.AddDays(1);
appt3.End = appt1.Start.AddHours(5);
appt3.Location = "My office";
appt3.ReminderMinutesBeforeStart = 30;
// Set the properties for a single instance appointment
appt4.Subject = "Appt4";
appt4.Body = "Appt4";
appt4.Start = DateTime.Now.AddDays(1);
appt4.End = appt1.Start.AddHours(6);
appt4.Location = "My office";
appt4.ReminderMinutesBeforeStart = 30;
// Add the appointment objects to a collection
Collection<Appointment> calendarItems = new Collection<Appointment>() { appt1, appt2, appt3, appt4 };
// Instantiate a collection of item ids to populate from the values that are returned by the Exchange server.
Collection<ItemId> itemIds = new Collection<ItemId>();
// Send the batch of appointment objects.
// Note that multiple calls to the Exchange server may be made when appointment objects have attachments.
// Note also that the item collection passed as the first parameter to CreateItems will have their ids set on return.
ServiceResponseCollection<ServiceResponse> response = service.CreateItems(calendarItems,
WellKnownFolderName.Calendar,
MessageDisposition.SendAndSaveCopy,
SendInvitationsMode.SendToAllAndSaveCopy);
if (response.OverallResult == ServiceResult.Success)
{
Console.WriteLine("All appointments and meetings sucessfully created.");
}
// Collect the item ids from the created calendar items.
foreach (Appointment appt in calendarItems)
{
itemIds.Add(appt.Id);
}
int counter = 1;
// Show the ids and errors for each message
foreach (ServiceResponse resp in response)
{
// Note that since item ids are long, show only 5 characters.
Console.WriteLine("Result (message {0}), id {1}: {2}", counter, itemIds[counter - 1].ToString().Substring(0, 5), resp.Result);
Console.WriteLine("Error Code: {0}", resp.ErrorCode);
Console.WriteLine("ErrorMessage: {0}\r\n", resp.ErrorMessage);
counter++;
}
// Return the collection of item ids
return itemIds;
}
Well, it isn't that you're getting blocked from sending a specific number of appointments, it's that Autodiscover is failing. That error is one that the EWS Managed API likes to return for all kinds of scenarios, so it doesn't tell me for sure why it is failing. It could be a temporary network issue, or it could be that the Autodiscover servers are throttling you. I'm not sure offhand if Autodiscover does any throttling, but it's certainly possible.
To see why it's failing, you could enable tracing with all of the Autodiscover-related trace flags turned on and see what kinds of errors are coming back.
I'm implementing an Outlook plugin and I need to create appointments by code, the appointments I want to model occur in rooms, rooms live in Outlook Exchange. How can I add various rooms to the appointment created by code, consider the following code to create an appointment:
Outlook.AppointmentItem newAppointment =
(Outlook.AppointmentItem)
this.Application.CreateItem(Outlook.OlItemType.olAppointmentItem);
newAppointment.Start = DateTime.Now.AddHours(2);
newAppointment.End = DateTime.Now.AddHours(3);
newAppointment.Location = "SOME_LOCATION";
newAppointment.Body =
"We will discuss progress on the group project.";
newAppointment.AllDayEvent = false;
newAppointment.Subject = "Group Project";
newAppointment.Recipients.Add("Roger Harui");
Outlook.Recipients sentTo = newAppointment.Recipients;
Outlook.Recipient sentInvite = null;
sentInvite = sentTo.Add("Holly Holt");
sentInvite.Type = (int)Outlook.OlMeetingRecipientType
.olRequired;
sentInvite = sentTo.Add("David Junca ");
sentInvite.Type = (int)Outlook.OlMeetingRecipientType
.olOptional;
sentTo.ResolveAll();
newAppointment.Save();
newAppointment.Recipients.ResolveAll();
newAppointment.Display(true);
You add a room the same way you add an attendee - pass the name of the room to Recipients.Add and set the Recipient.Type property to olResource (3).
I created a program a while ago using C# that does some automation for a completely different program, but found that I need to access data from a Lotus Notes database. The only problem is, I can only seem to figure out how to open the database by the server's name (using session.GetDatabase())... I can't figure out how to open it by Replica ID. Does anyone know how I would go about that? (I don't want my program going down every time the server changes.)
public static string[] GetLotusNotesHelpTickets()
{
NotesSession session = new NotesSession();
session.Initialize(Password);
// 85256B45:000EE057 = NTNOTES1A Server Replica ID
NotesDatabase database = session.GetDatabase("NTNOTES1A", "is/gs/gshd.nsf", false);
string SearchFormula = string.Concat("Form = \"Call Ticket\""
, " & GroupAssignedTo = \"Business Systems\""
, " & CallStatus = \"Open\"");
NotesDocumentCollection collection = database.Search(SearchFormula, null, 0);
NotesDocument document = collection.GetFirstDocument();
string[] ticketList = new string[collection.Count];
for (int i = 0; i < collection.Count; ++i)
{
ticketList[i] = ((object[])(document.GetItemValue("TicketNumber")))[0].ToString();
document = collection.GetNextDocument(document);
}
document = null;
collection = null;
database = null;
session = null;
return ticketList;
}
This code is working fine, but if the server changed from NTNOTES1A, then nothing is going to work anymore.
you'll need to use the notesDbDirectory.OpenDatabaseByReplicaID(rid$) method. To get the NotesDbDirectory, you can use the getDbDirectory method of the session
Set notesDbDirectory = notesSession.GetDbDirectory( serverName$ )
So you can use the code below to get a database by replicaID.
public static string[] GetLotusNotesHelpTickets()
{
NotesSession session = new NotesSession();
session.Initialize(Password);
Set notesDBDirectory = session.GetDbDirectory("NTNOTES1A")
// 85256B45:000EE057 = NTNOTES1A Server Replica ID
NotesDatabase database = notesDBDirectory.OpenDatabaseByReplicaID("85256B45:000EE057")
string SearchFormula = string.Concat("Form = \"Call Ticket\""
, " & GroupAssignedTo = \"Business Systems\""
, " & CallStatus = \"Open\"");
NotesDocumentCollection collection = database.Search(SearchFormula, null, 0);
NotesDocument document = collection.GetFirstDocument();
string[] ticketList = new string[collection.Count];
for (int i = 0; i < collection.Count; ++i)
{
ticketList[i] = ((object[])(document.GetItemValue("TicketNumber")))[0].ToString();
document = collection.GetNextDocument(document);
}
document = null;
collection = null;
database = null;
session = null;
return ticketList;
}
Unfortunately, this only solves half of your problem. I know you'd rather just tell Notes to fetch the database with a particular replicaID from the server closest to the client, just like the Notes Client does when you click on a DBLink or Bookmark. However, there is (or appears to be) no way to do that using the Notes APIs.
My suggestion is to either loop through a hard-coded list of potential servers by name, and check to see if the database is found (the OpenDatabaseByReplicaID method returns ERR_SYS_FILE_NOT_FOUND (error 0FA3) if the database is not found). If that's not a good option, perhaps you can easily expose the servername in an admin menu of your app so it can be changed easily if the server name changes at some point.
set database = new NotesDatabase("")
call database.OpenByReplicaID("repid")