Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose additional Preference Headers #85

Closed
wants to merge 5 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions src/Microsoft.OData.Core/ODataPreferenceHeader.cs
Original file line number Diff line number Diff line change
@@ -46,6 +46,21 @@ public sealed class ODataPreferenceHeader
/// </summary>
private const string WaitPreferenceTokenName = "wait";

/// <summary>
/// The odata.continue-on-error preference token.
/// </summary>
private const string ODataContinueOnErrorPreferenceToken = "odata.continue-on-error";

/// <summary>
/// The odata.maxpagesize=# preference token.
/// </summary>
private const string ODataMaxPageSizePreferenceToken = "odata.maxpagesize";

/// <summary>
/// The odata.track-changes preference token.
/// </summary>
private const string ODataTrackChangesPreferenceToken = "odata.track-changes";

/// <summary>
/// The Prefer header name.
/// </summary>
@@ -61,6 +76,11 @@ public sealed class ODataPreferenceHeader
/// </summary>
private static readonly KeyValuePair<string, string>[] EmptyParameters = new KeyValuePair<string, string>[0];

/// <summary>
/// The odata.continue-on-error preference.
/// </summary>
private static readonly HttpHeaderValueElement ContinueOnErrorPreference = new HttpHeaderValueElement(ODataContinueOnErrorPreferenceToken, null, EmptyParameters);

/// <summary>
/// The return=minimal preference.
/// </summary>
@@ -76,6 +96,11 @@ public sealed class ODataPreferenceHeader
/// </summary>
private static readonly HttpHeaderValueElement RespondAsyncPreference = new HttpHeaderValueElement(RespondAsyncPreferenceToken, null, EmptyParameters);

/// <summary>
/// The odata.track-changes preference.
/// </summary>
private static readonly HttpHeaderValueElement TrackChangesPreference = new HttpHeaderValueElement(ODataTrackChangesPreferenceToken, null, EmptyParameters);

/// <summary>
/// The message to set the preference header to and to get the preference header from.
/// </summary>
@@ -288,6 +313,98 @@ private HttpHeaderValue Preferences
get { return this.preferences ?? (this.preferences = this.ParsePreferences()); }
}

/// <summary>
/// Property to get and set the "odata.continue-on-error" preference to the "Prefer" header on the underlying IODataRequestMessage or
/// the "Preference-Applied" header on the underlying IODataResponseMessage.
/// Setting true sets the "odata.continue-on-error" preference.
/// Setting false clears the "odata.continue-on-error" preference.
/// Returns true of the "odata.continue-on-error" preference is on the header. Otherwise returns false if the "odata.continue-on-error" is not on the header.
/// </summary>
public bool ContinueOnError
{
get
{
return this.Get(ODataContinueOnErrorPreferenceToken) != null;
}

set
{
if (value)
{
this.Set(ContinueOnErrorPreference);
}
else
{
this.Clear(ODataContinueOnErrorPreferenceToken);
}
}
}

/// <summary>
/// Property to get and set the "odata.maxpagesize" preference to the "Prefer" header on the underlying IODataRequestMessage or
/// the "Preference-Applied" header on the underlying IODataResponseMessage.
/// Setting N sets the "odata.maxpagesize=N" preference.
/// Setting null clears the "odata.maxpagesize" preference.
/// Returns N if the "odata.maxpagesize=N" preference is on the header.
/// Returning null indicates that "odata.maxpagesize" is not on the header.
/// </summary>
public int? MaxPageSize
{
get
{
var maxPageSizeHttpHeaderValueElement = this.Get(ODataMaxPageSizePreferenceToken);

// Should check maxPageSizeHttpHeaderValueElement.Value != null.
// Should do int.TryParse.
// If either of the above fail, should throw an ODataException for parsing, not a System.Exception (such as FormatException, etc.).
if (maxPageSizeHttpHeaderValueElement != null)
{
return int.Parse(maxPageSizeHttpHeaderValueElement.Value, CultureInfo.InvariantCulture);
}

return null;
}

set
{
if (value.HasValue)
{
this.Set(new HttpHeaderValueElement(ODataMaxPageSizePreferenceToken, string.Format(CultureInfo.InvariantCulture, "{0}", value.Value), EmptyParameters));
}
else
{
this.Clear(ODataMaxPageSizePreferenceToken);
}
}
}

/// <summary>
/// Property to get and set the "odata.track-changes" preference to the "Prefer" header on the underlying IODataRequestMessage or
/// the "Preference-Applied" header on the underlying IODataResponseMessage.
/// Setting true sets the "odata.track-changes" preference.
/// Setting false clears the "odata.track-changes" preference.
/// Returns true of the "odata.track-changes" preference is on the header. Otherwise returns false if the "odata.track-changes" is not on the header.
/// </summary>
public bool TrackChanges
{
get
{
return this.Get(ODataTrackChangesPreferenceToken) != null;
}

set
{
if (value)
{
this.Set(TrackChangesPreference);
}
else
{
this.Clear(ODataTrackChangesPreferenceToken);
}
}
}

/// <summary>
/// Adds quotes around the given text value.
/// </summary>
Original file line number Diff line number Diff line change
@@ -30,6 +30,9 @@ public class ODataPreferenceHeaderTests
private const string RespondAyncPreference = "respond-async";
private const string RespondAsyncAndWaitPreference = "respond-async,wait=10";
private const string WaitPreference = "wait=10";
private const string MaxPageSizePreference = "odata.maxpagesize";
private const string TrackChangesPreference = "odata.track-changes";
private const string ContinueOnErrorPreference = "odata.continue-on-error";

[TestInitialize]
public void TestInit()
@@ -250,5 +253,64 @@ public void ReturnWaitOfBadIntergerFormatShouldThrow()
Action test = () => wait = this.preferHeader.Wait;
test.ShouldThrow<FormatException>().WithMessage("Input string was not in a correct format.");
}

[TestMethod]
public void SetContinueOnErrorToTrueShouldAppendHeader()
{
this.preferHeader.ContinueOnError = true;
this.preferHeader.ContinueOnError.Should().BeTrue();
this.requestMessage.GetHeader(PreferHeaderName).Should().Be(ContinueOnErrorPreference);
}

[TestMethod]
public void SetContinueOnErrorToFalseShouldClearHeader()
{
this.preferHeader.ContinueOnError = false;
this.preferHeader.ContinueOnError.Should().BeFalse();
this.requestMessage.GetHeader(PreferHeaderName).Should().BeNull();
}

[TestMethod]
public void SetMaxPageSizeShouldAppendHeader()
{
const int MaxPageSize = 10;
this.preferHeader.MaxPageSize = MaxPageSize;
this.preferHeader.MaxPageSize.Should().Be(MaxPageSize);
this.requestMessage.GetHeader(PreferHeaderName).Should().Be(string.Format("{0}={1}", MaxPageSizePreference, MaxPageSize));
}

[TestMethod]
public void SetMaxPageSizeToNullShouldClearHeader()
{
this.preferHeader.MaxPageSize = null;
this.preferHeader.MaxPageSize.Should().Be(null);
this.requestMessage.GetHeader(PreferHeaderName).Should().BeNull();
}

[TestMethod]
public void ReturnMaxPageSizeOfBadIntergerFormatShouldThrow()
{
this.requestMessage.SetHeader(PreferHeaderName, string.Format("{0}=abc", MaxPageSizePreference));
this.preferHeader = new ODataPreferenceHeader(this.requestMessage);
int? maxPageSize;
Action test = () => maxPageSize = this.preferHeader.MaxPageSize;
test.ShouldThrow<FormatException>().WithMessage("Input string was not in a correct format.");
}

[TestMethod]
public void SetTrackChangesToTrueShouldAppendHeader()
{
this.preferHeader.TrackChanges = true;
this.preferHeader.TrackChanges.Should().BeTrue();
this.requestMessage.GetHeader(PreferHeaderName).Should().Be(TrackChangesPreference);
}

[TestMethod]
public void SetTrackChangesToFalseShouldClearHeader()
{
this.preferHeader.TrackChanges = false;
this.preferHeader.TrackChanges.Should().BeFalse();
this.requestMessage.GetHeader(PreferHeaderName).Should().BeNull();
}
}
}