I've searched around looking for a way to load a calendar/contacts item from the public folder. Through Outlook it's simple, you go to the public folders and just drag-n-drop it in. I've gotten to the point accessing the calendar, but I'm not sure how to load it into Outlook through C#.
private void AddCalendar()
{
Outlook._NameSpace session = null;
Outlook.MAPIFolder publicFolders = null;
OUtlook.MAPIFolder allPublicFolders = null;
Outlook.MAPIFolder seCalendar = null;
try
{
session = _thisApp.GetNamespace("MAPI");
publicFolders = session.Folders["Public Folders"];
allPublicFolders = publicFolders.Folders["All Public Folders"];
seCalendar = allPublicFolders.Folders["SE Calendar"];
// ????
// profit
}
finally
{
//Release Items
}
}
Below is a picture of what I'm trying to do. You normally just start with your own calendar, I'm trying to load a company calendar that is in the public folders.
Loop through the items in the MAPIFolder.Items collection. In your particular case, the items will be AppointmentItem, ContactItem, and DistListItem.
Outlook.Items items = seCalendar.Items;
for (int i = 1; i <= items.Count; i++)
{
object item = items[i];
Outlook.AppointmentItem appt = item as Outlook.AppointmentItem;
if (apt != null)
{
MessageBox.Show(appt.Subject);
Marshal.ReleaseComObject(appt);
}
Marshal.ReleaseComObject(item);
}
Related
New to programming and trying to create this project for work. I have a text file inputted that has a list of usernames. I want the code to take the usernames from the text file and look them up in Outlook to give me a "true" or "false" if there is a match for the user in the system. How do I connect Outlook to the code with MAPI or an API? The code I have so far is below.
namespace QC_OUTLOOK
{
internal class Program
{
private static object MessageBox;
private static object objFile;
private static int i;
private static object Strings;
private static object response;
static int Main(string[] args)
{
string filePath = #"C:\Users\Documents\QC\User_list.txt";
// string[] lines = File.ReadAllLines(filePath);
List<string> lines = new List<string>();
lines = File.ReadAllLines(filePath).ToList();
using (StreamWriter streamWriter = File.CreateText(filePath));
foreach (String line in lines)
{
Console.WriteLine(line);
}
Console.ReadLine();
{
Outlook._Application oApp = new OutLook.Application();
//Get MAPI namespace
Outlook.AddressLists oNS = oNS.AddressLists;
Outlook.AddressList oGal = oALs.Item("Global Address List");
//Get all entries
Outlook.AddressEntries oEntries = oGal.AddressEntries;
// Get first user found
Outlook.AddressEntry oEntry = oEntries.GetFirst();
Outlook_UserName_Output = "";
response = sa.GetAllUsers;
Console.WriteLine(response);
//
UserCount = 0;
UsersFound = 0;
LastNameMatches = 0;
InactiveUser_Count = 0;
Inconsistent_EmailAddrs = 0;
GIS_UserCount = 0;
TodaysDate = DateTime.Today;
object value = objFile.WriteLine("Date:" + TodaysDate);
object value1 = objFile.WriteLine("QC_UserID, QC_FullName, OutLook_Last_Name, OutLook_First_Name");
for (i = 1; i <= Strings.Len(response) ; i++);
Outlook.Application oApp = new Outlook.Application();
// Get the MAPI namespace.
Outlook.NameSpace oNS = oApp.GetNamespace("mapi");
oNS.Logon(Missing.Value, Missing.Value, false, true);
Outlook.MAPIFolder oInbox = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
}
DataTable dt = new DataTable();
dt.Columns.Add("FirstName");
dt.Columns.Add("LastName");
Microsoft.Office.Interop.Outlook.Items OutlookItems;
Microsoft.Office.Interop.Outlook.Application outlookObj = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.MAPIFolder Folder_Contacts = (MAPIFolder)outlookObj.Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts);
OutlookItems = Folder_Contacts.Items;
foreach (var item in OutlookItems)
{
var contact = item as ContactItem;
if (contact != null)
{
DataRow dr = dt.NewRow();
dr["FirstName"] = contact.FirstName;
dr["LastName"] = contact.LastName;
dt.Rows.Add(dr);
}
First of all, creating a new Outlook Application instance multiple times in the code is not the best way to go:
Microsoft.Office.Interop.Outlook.Application outlookObj = new Microsoft.Office.Interop.Outlook.Application();
Outlook is a singleton. You can't run two instances of Outlook on the system at the same time. So, I'd suggest keeping the application object and re-use it where possible.
Iterating over all items in the Outlook folder is not really a good idea. Instead, use the Find/FindNext or Restrict methods of the Items class. Read more about these methods in the following articles:
How To: Retrieve Outlook Contact items using Restrict method
How To: Use Find and FindNext to retrieve Outlook Contact items
But better is to use the NameSpace.CreateRecipient method which creates a Recipient object and can be used to verify a given name against an address book. The Recipient.Resolve method attempts to resolve a created Recipient object against the Address Book. That's exactly what you are looking for!
I have implemented an SSIS Package getting all appoinments from a particular shared outlook calendar.
What I noticed is that the recurring ones are NOT returned because they are a kind of virtual. Only the Master of them will give me the ability to get also the recurring ones.
Looking at my code, do you have any suggestions how I can retrieve also the recurring ones?
I'm just a little stuck and any hint is highly appreciated!
#region Namespaces
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using Microsoft.Exchange.WebServices.Data;
#endregion
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
string sharedCalendarID;
static FolderId FindPublicFolder(ExchangeService myService, FolderId baseFolderId, string folderName)
{
// search using paging.
FolderView folderView = new FolderView(10, 0);
folderView.OffsetBasePoint = OffsetBasePoint.Beginning;
// need only DisplayName and Id of every folder
// reduce the property set to the properties
folderView.PropertySet = new PropertySet(FolderSchema.DisplayName, FolderSchema.Id);
FindFoldersResults folderResults;
do
{
folderResults = myService.FindFolders(baseFolderId, folderView);
foreach (Folder folder in folderResults)
if (String.Compare(folder.DisplayName, folderName, StringComparison.OrdinalIgnoreCase) == 0)
return folder.Id;
if (folderResults.NextPageOffset.HasValue)
// go to the next page
folderView.Offset = folderResults.NextPageOffset.Value;
}
while (folderResults.MoreAvailable);
return null;
}
public override void CreateNewOutputRows()
{
// IMPORTANT: ExchangeService is NOT thread safe, so one should create an instance of
// ExchangeService whenever one needs it.
ExchangeService myService = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
myService.Credentials = new NetworkCredential("username", "password");
myService.Url = new Uri("https://......Exchange.asmx");
// next line is very practical during development phase or for debugging
myService.TraceEnabled = true;
Folder myPublicFoldersRoot = Folder.Bind(myService, WellKnownFolderName.PublicFoldersRoot);
string myPublicFolderPath = #"CHI\WIED PFL Agenda";
string[] folderPath = myPublicFolderPath.Split('\\');
FolderId fId = myPublicFoldersRoot.Id;
foreach (string subFolderName in folderPath)
{
fId = FindPublicFolder(myService, fId, subFolderName);
if (fId == null)
{
// No Calendar found
return;
}
}
// verify
Folder folderFound = Folder.Bind(myService, fId);
if (String.Compare(folderFound.FolderClass, "IPF.Appointment", StringComparison.Ordinal) == 0)
{
sharedCalendarID = fId.ToString(); ;
}
else
return;
CalendarFolder myPublicFolder = CalendarFolder.Bind(myService,
//WellKnownFolderName.Calendar,
fId,
PropertySet.FirstClassProperties);
// search using paging. page size 10
ItemView viewCalendar = new ItemView(10);
// include all properties which we need in the view
// comment the next line then ALL properties will be read from the server.
//viewCalendar.PropertySet = new PropertySet(ItemSchema.Subject, ItemSchema.Id);
viewCalendar.Offset = 0;
viewCalendar.OffsetBasePoint = OffsetBasePoint.Beginning;
viewCalendar.OrderBy.Add(ContactSchema.DateTimeCreated, SortDirection.Descending);
FindItemsResults<Item> findResultsCalendar;
do
{
//SearchFilter searchFilter = new SearchFilter.IsGreaterThan(AppointmentSchema.Start, DateTime.Today);
var searchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And,
new SearchFilter.IsEqualTo(ItemSchema.ItemClass, "IPM.Appointment"),
new SearchFilter.IsGreaterThanOrEqualTo(AppointmentSchema.Start, DateTime.Now),
new SearchFilter.IsLessThan(AppointmentSchema.Start, DateTime.Now.AddDays(4)));
findResultsCalendar = myPublicFolder.FindItems(searchFilter, viewCalendar);
//get additional properties for each item returned by view, do this as view cannot return a lot of useful stuff like attendees
ServiceResponseCollection<ServiceResponse> addProperties =
myService.LoadPropertiesForItems(from Item item in findResultsCalendar select item,
new PropertySet(
BasePropertySet.IdOnly,
AppointmentSchema.Body,
AppointmentSchema.Subject,
AppointmentSchema.Start,
AppointmentSchema.End,
AppointmentSchema.IsRecurring,
AppointmentSchema.AppointmentType
));
List<Appointment> additionalProperties = new List<Appointment>(addProperties.Count);
if (addProperties != null)
{
foreach (ServiceResponse currentResponce in addProperties)
{
additionalProperties.Add(((Appointment)((GetItemResponse)currentResponce).Item));
}
}
foreach (Item item in findResultsCalendar)
{
Appointment appt = item as Appointment;
if (item is Appointment || appt.AppointmentType == AppointmentType.RecurringMaster)
{
Appointment currentAppointmentAddProps = null;
currentAppointmentAddProps = additionalProperties.Find(
delegate(Appointment arg)
{
return arg.Id == item.Id;
}
);
//convert to int wether the Appointment is recurring or not
int isRecurring = currentAppointmentAddProps.IsRecurring ? 1 : 0;
Appointment appoint = item as Appointment;
OutputRecordSetBuffer.AddRow();
OutputRecordSetBuffer.ActualEndDate = currentAppointmentAddProps.End;
OutputRecordSetBuffer.ActualStartDate = currentAppointmentAddProps.Start;
OutputRecordSetBuffer.Subject = appoint.Subject;
OutputRecordSetBuffer.EntryID = Guid.NewGuid();
//OutputRecordSetBuffer.Detail = appoint.Body.ToString();
//OutputRecordSetBuffer.CalendarID = fId.ToString();
//OutputRecordSetBuffer.AppointmentID = appoint.Id.ToString();
OutputRecordSetBuffer.CalendarID = sharedCalendarID;
OutputRecordSetBuffer.AppointmentID = Guid.NewGuid();
OutputRecordSetBuffer.IsRecurring = isRecurring;
}
}
if (findResultsCalendar.NextPageOffset.HasValue)
// go to the next page
viewCalendar.Offset = findResultsCalendar.NextPageOffset.Value;
}
while (findResultsCalendar.MoreAvailable);
}
}
I have solved my issue on my own :)
Instead of using the ItemView class, I used the CalendarView class.
CalendarView expands also the recurring appointments, thats it :)
Created a Windows Store App using some info found on this post: How do I use the Bing Search API in Windows Phone?
Goal
Textbox - Type any term
Search Button - Searches that term and populates a GridView of pictures retrieved with the Bing API
Problem
I get the pictures, and they are received via my "OnQueryComplete" callback, but I can't figure out what the correct way to populate the collection would be. Since I can't figure out how to await this call, I (just to see if I could get it working, which it does) added a while loop (which you can probably see the issues with). What would be the correct way to do this? How do you handle callbacks for populating the GridView and having it wait until it's finished?
Current ViewModel Code
public bool itemsFinished = false;
private ObservableCollection<SearchResult> _ImageResults;
public ObservableCollection<SearchResult> ImageResults {
get {
if (_ImageResults == null) {
while (!itemsFinished) {
int i = 0;
i++;
}
}
return _ImageResults;
}
set {
_ImageResults = value;
}
}
public SearchResultViewModel() {
GetPictures("dogs");
}
public void GetPictures(string searchTerm) {
// This is the query - or you could get it from args.
string query = searchTerm;
// Create a Bing container.
string rootUri = "https://api.datamarket.azure.com/Bing/Search";
var bingContainer = new Bing.BingSearchContainer(new Uri(rootUri));
// Replace this value with your account key.
var accountKey = "myaccountkey";
// Configure bingContainer to use your credentials.
bingContainer.Credentials = new NetworkCredential(accountKey, accountKey);
// Build the query.
var imageQuery = bingContainer.Image(query, null, null, null, null, null, null);
imageQuery.BeginExecute(OnQueryComplete, imageQuery);
// var imageResults = imageQuery.Execute();
}
private void OnQueryComplete(IAsyncResult result) {
// ImageResults.Clear();
_ImageResults = new ObservableCollection<SearchResult>();
var query = (DataServiceQuery<ImageResult>)result.AsyncState;
var enumerableResults = query.EndExecute(result);
int i = 0;
foreach (var item in enumerableResults) {
SearchResult myResult = new SearchResult();
myResult.Title = item.Title;
myResult.ImageUri = new Uri(item.MediaUrl);
ImageResults.Add(myResult);
i++;
if (i >= 14) {
break;
}
}
itemsFinished = true;
}
Please excuse any syntax errors, I'm without a Visual Studio instance right now.
The problem I see is that you reset your ObservableCollection when you receive content.
Try it as follows:
private ObservableCollection<SearchResult> _ImageResults;
public ObservableCollection<SearchResult> ImageResults {
get
{
return _ImageResults;
}
set {
_ImageResults = value;
}
}
public SearchResultViewModel() {
_ImageResults = new ObservableCollection<SearchResult>(); // Just create it once.
GetPictures("dogs");
}
private void OnQueryComplete(IAsyncResult result) {
_ImageResults.Clear(); // Clear isn't bad, that way you keep your reference to your original collection!
//_ImageResults = new ObservableCollection<SearchResult>(); // We already have one. ObservableCollection works best if you keep on working with the collection you have.
var query = (DataServiceQuery<ImageResult>)result.AsyncState;
var enumerableResults = query.EndExecute(result);
int i = 0;
foreach (var item in enumerableResults) {
SearchResult myResult = new SearchResult();
myResult.Title = item.Title;
myResult.ImageUri = new Uri(item.MediaUrl);
ImageResults.Add(myResult);
i++;
if (i >= 14) {
break;
}
}
}
As far as I see (can't test sadly) this should work, provided you have bound your ObservableCollection the right way in your xaml.
I have datalist. Each item consists of FileUpload control.
How can I check the uploaded file after each upload?
Because I didn't know that, I tried to do something else - the check will be implemented after button click.
Note: this datalist is child of other datalist. This is nested datalist. The datasource of the parent is arraylist of orders, and the child's datasource is the products list in each order.
private void UploadProduct(DataListItem dli, ArrayList pl) // pl = productsList
{
int i = 0;
DataList DataList2 = (DataList)dli.FindControl("DataList2");
foreach (DataListItem item in DataList2.Items)
{
Product p = pl[i] as Product;
FileUpload FileUpload1 = (FileUpload)item.FindControl("FileUpload1");
if (FileUpload1.PostedFile.FileName != "" && FileUpload1.PostedFile.ContentType.Contains("jpg") && FileUpload1.PostedFile.ContentLength <= 2097151)
{
p.UploadedProduct = FileUpload1.FileBytes; // pc.UploadedProduct is byte[]
}
i++;
}
}
In the Item_Command:
if (e.CommandName == "finishOrder")
{
ArrayList ordersList = (ArrayList)Session["OrdersList"]; // the datasource of the outer datalist
int orderID = Convert.ToInt32(e.CommandArgument);
ProductsCart pc = null;
foreach (ProductsCart productsCart in ordersList) // to get the object which the button refers to
{
if (productsCart.OrderID == orderID)
pc = productsCart;
}
DataListItem item = ((DataListItem)((Button)e.CommandSource).NamingContainer); // to get the datalist item of the clicked button
FileUpload FileUpload1 = (FileUpload)(item.FindControl("FileUpload1"));
// Label errorMsg = (Label)(item.FindControl("errorMsg"));
bool flag = true;
// string imagePath;
UploadProduct(item, pc.ProductsList);
foreach (Product p in pc.ProductsList) // the check if the uploads were uploaded according to my conditions
{
if (p.UploadedProduct==null)
{
flag = false;
}
}
if (flag)
{
// do something
}
else // error
{
Page.ClientScript.RegisterStartupScript(this.GetType(), "alert", "alert('error');", true);
}
FillDataListOuter(DataList1); // datasource and databind
}
This is not working, thats why I ask for help. When I try to upload docx file it tries to execute the code if flag is true. So I guess this is not a good way to do it.
I need help, because I tried to read a lot and I couldn't find the answer.
I have created an asp.net application using Entity Framework. In this I want to add the records into a list. For this I have to use the foreach loop but it always adding only last record data for all records, meaning it's showing same data. Here I have pasted my code. Please verify it once and guide where I can change.
public List<CategoryItems> ListMenuCategory(int MenuId)
{
string str = string.Empty;
string strJSON = string.Empty;
List<CategoryItems> resultmenu;
resultmenu = new List<CategoryItems>();
List<CategoryItems> Result;
Result = new List<CategoryItems>();
bool check = true;
var objmenuCategory = from cat in objEntity.menucategories where cat.MenuId == MenuId && cat.Active == check select cat;
CategoryItems Categorylist = new CategoryItems();
foreach (menucategory category in objmenuCategory)
{
Categorylist.CategoryName = category.CategoryName;
Categorylist.Description = category.Description;
int menuid = category.MenuCategoryId;
List<menuitem> menuitems = GetMenucategories(menuid);
foreach (var items in menuitems)
{
Categorylist.ItemName = items.ItemName;
Categorylist.Description = items.Description;
Categorylist.Price = (float)items.Price;
string Image = items.Picture;
Categorylist.Picture = "http://restaurantmanager.testshell.net/Images/" + Image;
Categorylist.Thumbnail = "http://restaurantmanager.testshell.net/Images/" + items.Thumbnail;
if (items.CreatedDate != null)
{
Categorylist.CreatedDate = (DateTime)items.CreatedDate;
}
if (items.ModifiedDate != null)
{
Categorylist.ModifiedDate = (DateTime)items.ModifiedDate;
}
Result.Add(Categorylist);
}
// Result.AddRange(menus);
}
return Result;
}
private List<menuitem> GetMenucategories(int p)
{
restaurantEntities objEntity1 = new restaurantEntities();
var menuitems = from items in objEntity1.menuitems where items.MenuCategoryId == p select items;
return menuitems.ToList();
}
You are creating the Categorylist item outside of the loops, so you are only using one single item, filling it with different data and adding it over and over to the result.
You have to create the item inside the innermost loop, so that each iteration gets its own object.
Note: ChrisF also spotted that you call AddRange inside the loop, which has the result that you will add the same set of items over and over. You don't need to call AddRange at all, you can just skip the Result list entirely and just return resultmenu instead.