MissingManifestResourceException when using Portable Class Libraries within WinRT
Our team recently ran into a strange issue. Our Windows Phone application targets Silverlight 8.1 but we have several WinRT 8.1 based background tasks. Recen...
When your LINQ-to-DASL queries do not return the results you expect, how do you determine where the problem is? The issue could be that the query simply doesn't do what you expect. For example, you could be querying the wrong DASL properties and therefore Outlook returns no (or unexpected) items. (This is easy to do, as DASL property names can be difficult to identify and map to the equivalent Outlook object model property.) It could also be that the DASL query syntax itself is incorrect or the LINQ-to-DASL provider did not manage the query results property.
Fortunately, the LINQ-to-DASL provider offers a way to gain a little insight into what it is actually doing. You can attach a logger to the provider that will be passed the exact DASL string passed to Outlook when the query is executed.
Let's say we want to find all appointments that have been modified in the last week. That is, where the LastModifiedTime is within the last seven days. First, we'll define a custom class on which to perform the query. (We do this because the built-in Appointment query class does not have LastModifiedTime.)
public class MyAppointment : Appointment { [OutlookItemProperty("DAV:getlastmodified")] public DateTime LastModifiedTime { get { return Item.LastModificationTime; } } }
Next, we'll create a method that generates the query.
private IEnumerable<Outlook.AppointmentItem> CreateQueryWithoutDebuggingInformation(Outlook.Items items, DateTime oldestDate) { var query = from item in items.AsQueryable<MyAppointment>() where item.LastModifiedTime > oldestDate.ToUniversalTime() select item.Item; return query; }
The method takes the items collection on which the query is to be performed and the date we wish to filter by. Note that there is nothing special about this LINQ-to-DASL query at this point.
Finally, we'll write the method to execute the query and show the results.
private void ThisAddIn_Startup(object sender, System.EventArgs e) { Outlook.Folder folder = (Outlook.Folder)Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar); DateTime oldestDate = DateTime.Now.AddDays(-7); var query = CreateQueryWithoutDebuggingInformation(folder.Items, oldestDate); foreach (var appt in query) { if (MessageBox.Show(appt.Subject, "Appointment Found!", MessageBoxButtons.OKCancel) == DialogResult.Cancel) { break; } } }
The method simply retrieves the Calendar folder, calls the query creation method, and then iterates over the results. If the query doesn't return any items, or returns items that you do not expect, what do we do next? The answer is to modify our query by attaching a logger so that we can see the generated DASL.
First, we'll create a simple logger that writes to the debugger output window.
internal class DebuggerWriter : TextWriter { public override Encoding Encoding { get { throw new NotImplementedException(); } } public override void WriteLine(string value) { Debug.WriteLine(value); } }
The logger can be any TextWriter-derived class. Note that the Encoding property must be overridden, but need not actually be implemented.
Next, we'll create a new query generation method.
private IEnumerable<Outlook.AppointmentItem> CreateQueryWithDebuggingInformation(Outlook.Items items, DateTime oldestDate) { var source = new ItemsSource<MyAppointment>(items) { Log = new DebuggerWriter() }; var query = from item in source where item.LastModifiedTime > oldestDate.ToUniversalTime() select item.Item; return query; }
Notice that the query itself (the from, where, and select) is virtually identical to the previous query. The only difference is that we explicitly create a ItemsSource. (This is what AsQueryable() did implicitly in the previous query.) We then attach an instance of our logger.
Finally, we update our query execution method.
private void ThisAddIn_Startup(object sender, System.EventArgs e) { Outlook.Folder folder = (Outlook.Folder)Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar); DateTime oldestDate = DateTime.Now.AddDays(-7); //var query = CreateQueryWithoutDebuggingInformation(folder.Items, oldestDate); var query = CreateQueryWithDebuggingInformation(folder.Items, oldestDate); foreach (var appt in query) { if (MessageBox.Show(appt.Subject, "Appointment Found!", MessageBoxButtons.OKCancel) == DialogResult.Cancel) { break; } } }
The only change here was to call the new query generation method. Now when we run the code in the debugger, we'll see the following in our output window:
You can see the exact DASL filter string sent to Outlook when the query was executed. You can use this to verify that the DASL property names, syntax, and values all look correct. You can also compare this filter string to the string built using the advanced filtration dialog in Outlook.
This post was migrated from my MSDN blog, Visual Studio Tools and Anything Else I Can Think Of, and written as a Microsoft employee.
Our team recently ran into a strange issue. Our Windows Phone application targets Silverlight 8.1 but we have several WinRT 8.1 based background tasks. Recen...
In a previous post I introduced the concept of Role Content Folders and how they can be used to deploy additional content (e.g. configuration files, runtime ...
The latest versions of the Windows Azure Tools for Visual Studio have the ability to maintain multiple versions of the Service Configuration (.cscfg) file.&n...
When a package fails to deploy to Windows Azure (or deploys but its roles fail to start properly) it can be difficult to determine what went wrong. In many c...
Windows Azure applications often need to package and deploy additional content. This could be advanced configuration files such as the diagnostics.wadcfg for...
The LINQ-to-DASL provider of the Office Interop API Extensions provides a very limited set of mappings between its query types and their associated DASL prop...
When your LINQ-to-DASL queries do not return the results you expect, how do you determine where the problem is? The issue could be that the query simpl...
I received an email over the weekend asking why the following LINQ to DASL query threw an exception: Outlook.Folder folder = (Outlook.Folder)Application.Se...
Now that the Office Interop API Extensions have been released, I thought I would post a complete walkthrough of a simple LINQ to DASL application. Let's star...
One of the disadvantages of C# compared with VB is its lack of support for parameterized properties. Instead, parameterized properties in C# are exposed as ...
As announced in Andrew Whitechapel’s post, version 1.0 of the VSTO Power Tools have been released! One of those tools is the Office Interop API Extensions, a...
In an earlier post I discussed LINQ to DASL, part of the Office Interop API Extensions, which is one of the forthcoming VSTO Power Tools. LINQ to DASL ...
In my last post I talked about LINQ to DASL, a LINQ provider that converts query expressions into their DASL equivalent in order to efficiently filter item c...
Quick, tell me what the following code does:
I like VSTO. I like C#. What I don’t like is having to write VSTO code in C# like:
Yesterday I gave a presentation on VSTO at the third annual Portland Code Camp. I demonstrated an Outlook 2007 add-in that used Outlook Form Regions, WCF, an...