I just started working with the Office 365 OData API and was a little fustrated with the samples because all the strongly typed classes they provide for using the OData APIs contains nowhere near all of properties the odata returns.
So I looked around for some way to generate the strongly typed classes directly from the OData metadata.
The metadata for the exchange odata endpoints can be downloaded from this url https://outlook.office365.com/ews/odata/$metadata.
So I just needed a tool for generating the classes. First I tried with DataSvcUtil.exe, but I had no luck with that. So instead I installed the following Visual Studio extension OData Client Code Generator.
.
The tool is very simple to use it adds a new Item template type called “OData Client” when added to a project you get a new a *.odata.config file and t4 template and that can turn a edmx schema from a OData metadata endpoint into a odata client class with strongly typed classes for types exposed.
You need to edit the *.odata.config to point to your edmx source file or a OData service. In my case with the Exchange odata, I downloaded the edmx file from the https://outlook.office365.com/ews/odata/$metadata and pointed to the file on disk to avoid having to login inside Visual Studio.
Here’s what my config file looks like
[xml]
<?xml version="1.0" encoding="utf-8" ?>
<Parameters>
<!– Value of MetadataDocumentUri must be set to a valid service document uri or a local file path
eg : http://services.odata.org/V4/OData/OData.svc/ or File://C://Odata.edmx –>
<Parameter Name="MetadataDocumentUri" Value="File://C://Users//Simon Pedersen//Documents//Visual Studio 2013//Projects//AccessOfficeAPI//AccessOfficeAPI//ews.edmx" />
<!– Value must be true or false –>
<Parameter Name="UseDataServiceCollection" Value="true" />
<!– Namespace prefix will replace the original namspace, unless the mode has several namespaces.–>
<Parameter Name="NamespacePrefix" Value="ews" />
<!– Value of TargetLanguage must be CSharp or VB –>
<Parameter Name="TargetLanguage" Value="CSharp" />
</Parameters>
[/xml]
And here’s a snippet of what the generated code for the Event data type.
[csharp]
/// <summary>
/// There are no comments for Event in the schema.
/// </summary>
/// <KeyProperties>
/// Id
/// </KeyProperties>
[global::Microsoft.OData.Client.Key("Id")]
public partial class Event : Item
{
/// <summary>
/// Create a new Event object.
/// </summary>
/// <param name="ID">Initial value of Id.</param>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public static Event CreateEvent(string ID)
{
Event @event = new Event();
@event.Id = ID;
return @event;
}
/// <summary>
/// There are no comments for Property Start in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public global::System.Nullable<global::System.DateTimeOffset> Start
{
get
{
return this._Start;
}
set
{
this.OnStartChanging(value);
this._Start = value;
this.OnStartChanged();
this.OnPropertyChanged("Start");
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
private global::System.Nullable<global::System.DateTimeOffset> _Start;
partial void OnStartChanging(global::System.Nullable<global::System.DateTimeOffset> value);
partial void OnStartChanged();
/// <summary>
/// There are no comments for Property End in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public global::System.Nullable<global::System.DateTimeOffset> End
{
get
{
return this._End;
}
set
{
this.OnEndChanging(value);
this._End = value;
this.OnEndChanged();
this.OnPropertyChanged("End");
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
private global::System.Nullable<global::System.DateTimeOffset> _End;
partial void OnEndChanging(global::System.Nullable<global::System.DateTimeOffset> value);
partial void OnEndChanged();
/// <summary>
/// There are no comments for Property Location in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public global::ews.Microsoft.Exchange.Services.OData.Model.Location Location
{
get
{
return this._Location;
}
set
{
this.OnLocationChanging(value);
this._Location = value;
this.OnLocationChanged();
this.OnPropertyChanged("Location");
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
private global::ews.Microsoft.Exchange.Services.OData.Model.Location _Location;
partial void OnLocationChanging(global::ews.Microsoft.Exchange.Services.OData.Model.Location value);
partial void OnLocationChanged();
/// <summary>
/// There are no comments for Property ShowAs in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public global::ews.Microsoft.Exchange.Services.OData.Model.FreeBusyStatus ShowAs
{
get
{
return this._ShowAs;
}
set
{
this.OnShowAsChanging(value);
this._ShowAs = value;
this.OnShowAsChanged();
this.OnPropertyChanged("ShowAs");
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
private global::ews.Microsoft.Exchange.Services.OData.Model.FreeBusyStatus _ShowAs;
partial void OnShowAsChanging(global::ews.Microsoft.Exchange.Services.OData.Model.FreeBusyStatus value);
partial void OnShowAsChanged();
/// <summary>
/// There are no comments for Property IsAllDay in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public global::System.Nullable<bool> IsAllDay
{
get
{
return this._IsAllDay;
}
set
{
this.OnIsAllDayChanging(value);
this._IsAllDay = value;
this.OnIsAllDayChanged();
this.OnPropertyChanged("IsAllDay");
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
private global::System.Nullable<bool> _IsAllDay;
partial void OnIsAllDayChanging(global::System.Nullable<bool> value);
partial void OnIsAllDayChanged();
/// <summary>
/// There are no comments for Property IsCancelled in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public global::System.Nullable<bool> IsCancelled
{
get
{
return this._IsCancelled;
}
set
{
this.OnIsCancelledChanging(value);
this._IsCancelled = value;
this.OnIsCancelledChanged();
this.OnPropertyChanged("IsCancelled");
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
private global::System.Nullable<bool> _IsCancelled;
partial void OnIsCancelledChanging(global::System.Nullable<bool> value);
partial void OnIsCancelledChanged();
/// <summary>
/// There are no comments for Property IsOrganizer in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public global::System.Nullable<bool> IsOrganizer
{
get
{
return this._IsOrganizer;
}
set
{
this.OnIsOrganizerChanging(value);
this._IsOrganizer = value;
this.OnIsOrganizerChanged();
this.OnPropertyChanged("IsOrganizer");
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
private global::System.Nullable<bool> _IsOrganizer;
partial void OnIsOrganizerChanging(global::System.Nullable<bool> value);
partial void OnIsOrganizerChanged();
/// <summary>
/// There are no comments for Property ResponseRequested in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public global::System.Nullable<bool> ResponseRequested
{
get
{
return this._ResponseRequested;
}
set
{
this.OnResponseRequestedChanging(value);
this._ResponseRequested = value;
this.OnResponseRequestedChanged();
this.OnPropertyChanged("ResponseRequested");
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
private global::System.Nullable<bool> _ResponseRequested;
partial void OnResponseRequestedChanging(global::System.Nullable<bool> value);
partial void OnResponseRequestedChanged();
/// <summary>
/// There are no comments for Property Type in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public global::ews.Microsoft.Exchange.Services.OData.Model.EventType Type
{
get
{
return this._Type;
}
set
{
this.OnTypeChanging(value);
this._Type = value;
this.OnTypeChanged();
this.OnPropertyChanged("Type");
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
private global::ews.Microsoft.Exchange.Services.OData.Model.EventType _Type;
partial void OnTypeChanging(global::ews.Microsoft.Exchange.Services.OData.Model.EventType value);
partial void OnTypeChanged();
/// <summary>
/// There are no comments for Property SeriesId in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public string SeriesId
{
get
{
return this._SeriesId;
}
set
{
this.OnSeriesIdChanging(value);
this._SeriesId = value;
this.OnSeriesIdChanged();
this.OnPropertyChanged("SeriesId");
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
private string _SeriesId;
partial void OnSeriesIdChanging(string value);
partial void OnSeriesIdChanged();
/// <summary>
/// There are no comments for Property Attendees in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public global::System.Collections.ObjectModel.ObservableCollection<global::ews.Microsoft.Exchange.Services.OData.Model.Attendee> Attendees
{
get
{
return this._Attendees;
}
set
{
this.OnAttendeesChanging(value);
this._Attendees = value;
this.OnAttendeesChanged();
this.OnPropertyChanged("Attendees");
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
private global::System.Collections.ObjectModel.ObservableCollection<global::ews.Microsoft.Exchange.Services.OData.Model.Attendee> _Attendees = new global::System.Collections.ObjectModel.ObservableCollection<global::ews.Microsoft.Exchange.Services.OData.Model.Attendee>();
partial void OnAttendeesChanging(global::System.Collections.ObjectModel.ObservableCollection<global::ews.Microsoft.Exchange.Services.OData.Model.Attendee> value);
partial void OnAttendeesChanged();
/// <summary>
/// There are no comments for Property Recurrence in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public global::ews.Microsoft.Exchange.Services.OData.Model.PatternedRecurrence Recurrence
{
get
{
return this._Recurrence;
}
set
{
this.OnRecurrenceChanging(value);
this._Recurrence = value;
this.OnRecurrenceChanged();
this.OnPropertyChanged("Recurrence");
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
private global::ews.Microsoft.Exchange.Services.OData.Model.PatternedRecurrence _Recurrence;
partial void OnRecurrenceChanging(global::ews.Microsoft.Exchange.Services.OData.Model.PatternedRecurrence value);
partial void OnRecurrenceChanged();
/// <summary>
/// There are no comments for Property Calendar in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
public global::ews.Microsoft.Exchange.Services.OData.Model.Calendar Calendar
{
get
{
return this._Calendar;
}
set
{
this.OnCalendarChanging(value);
this._Calendar = value;
this.OnCalendarChanged();
this.OnPropertyChanged("Calendar");
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "1.0.0")]
private global::ews.Microsoft.Exchange.Services.OData.Model.Calendar _Calendar;
partial void OnCalendarChanging(global::ews.Microsoft.Exchange.Services.OData.Model.Calendar value);
partial void OnCalendarChanged();
}
[/csharp]