/// <summary> /// Updates the updatedResource and version if values have changed /// </summary> /// <param name="update"> /// The updatedResource you are comparing to /// </param> /// <returns> /// The updated resource /// </returns> internal Sample UpdateFrom(Sample update) { if (this.IsSameVersionAs(update)) { if (update.IsValid() && this.DataChanged(update)) { // Update only the fields you allow // the caller to update this.Data = update.Data; this.UpdateVersion(); } } // Ignore fields you don't want to allow the caller to change // Ignore updatedResource.ReadOnlyValue // Ignore updatedResource.Version return this; }
/// <summary> /// The data changed. /// </summary> /// <param name="update"> /// The update. /// </param> /// <returns> /// true if the data is changed /// </returns> internal bool DataChanged(Sample update) { return this.Data != update.Data; }
/// <summary> /// The is same version as. /// </summary> /// <param name="update"> /// The update. /// </param> /// <returns> /// true if the version is the same /// </returns> internal bool IsSameVersionAs(Sample update) { return this.Tag == update.Tag; }
/// <summary> /// The put resource. /// </summary> /// <param name="key"> /// The key. /// </param> /// <param name="putResource"> /// The resource to put /// </param> /// <param name="baseUri"> /// The base uri. /// </param> /// <param name="contentType"> /// The content type. /// </param> /// <returns> /// The test result /// </returns> private static TestResult PutResource( int key, Sample putResource, string baseUri = null, string contentType = XmlContentType) { using (var client = CreateHttpClient(contentType)) { var request = new HttpRequestMessage(HttpMethod.Put, GetResourceKeyUri(key, baseUri)) { Content = new ObjectContent(typeof(Sample), putResource, contentType) }; if (putResource != null && !string.IsNullOrWhiteSpace(putResource.Tag)) { request.Headers.IfMatch.Add(new EntityTagHeaderValue((QuotedString)putResource.Tag)); } var response = client.Send(request); return new TestResult(response); } }
/// <summary> /// Creates a sanitized updatedResource based on one supplied by the caller /// </summary> /// <param name="id"> /// The id of the updatedResource to create /// </param> /// <param name="untrusted"> /// The resource supplied by the caller /// </param> /// <param name="versionOption"> /// The version option /// </param> /// <returns> /// A new resource based on the untrusted resource /// </returns> /// <remarks> /// Sanitizing a resource means converting an untrusted resource /// into something you can trust. /// </remarks> internal static Sample CreateSanitizedResource( int id, Sample untrusted, SampleResourceVersionOption versionOption) { // Return a new sanitized updatedResource with only the changes allowed return new Sample { Key = id, Data = untrusted.Data, Tag = (versionOption == SampleResourceVersionOption.New) ? Guid.NewGuid().ToString() : untrusted.Tag, // ReadOnlyData is not initialized because we don't allow the caller to update it }; }
/// <summary> /// The put may add a new entity using the key provided in the uri. /// </summary> /// <param name="contentType"> /// The content type. /// </param> private static void PutMayAddANewEntityUsingTheKeyProvidedInTheUri(string contentType) { // Arrange const int ResourceKey = 333; var expectedData = "Sample" + ResourceKey; var putResource = new Sample { Data = expectedData }; var expectedUri = new Uri(GetResourceKeyUri(ResourceKey, AddOrUpdateServiceUri)); // Act var result = PutResource(ResourceKey, putResource, AddOrUpdateServiceUri, contentType); // Assert Assert.AreEqual(HttpStatusCode.Created, result.Response.StatusCode, "Resource should be added"); Assert.AreEqual(expectedData, result.Sample.Data, "Added Resource was not returned correctly"); Assert.AreEqual( expectedUri.PathAndQuery, result.Response.Headers.Location.PathAndQuery, "Location header was not set correctly"); Assert.IsNotNull(result.Response.Headers.ETag, "Response should include etag"); }
/// <summary> /// The post must return 409 conflict if the entity conflicts with another entity. /// </summary> /// <param name="contentType"> /// The content type. /// </param> private static void PostMustReturn409ConflictIfTheEntityConflictsWithAnotherEntity(string contentType) { // Arrange const string ExpectedData = "Post Data"; var expectedResource = new Sample { Data = ExpectedData }; // Act var result1 = Post(expectedResource, contentType); var result2 = Post(expectedResource, contentType); // Assert Assert.AreEqual(HttpStatusCode.Created, result1.Response.StatusCode); Assert.AreEqual(HttpStatusCode.Conflict, result2.Response.StatusCode); }
/// <summary> /// The post must ignore writes to entity fields the server considers read only. /// </summary> /// <param name="contentType"> /// The content type. /// </param> private static void PostMustIgnoreWritesToEntityFieldsTheServerConsidersReadOnly(string contentType) { // Arrange const string ExpectedData = "Post Data"; const string NotExpectedData = "Updated read only data"; var expectedResource = new Sample { Data = ExpectedData, ReadOnlyData = NotExpectedData }; // Act var result = Post(expectedResource, contentType); // Assert Assert.AreEqual(HttpStatusCode.Created, result.Response.StatusCode); Assert.AreNotEqual(NotExpectedData, result.Sample.ReadOnlyData); }
/// <summary> /// The post must append a valid resource to the resource collection. /// </summary> /// <param name="contentType"> /// The content type. /// </param> private static void PostMustAppendAValidResourceToTheResourceCollection(string contentType) { // Arrange const string ExpectedData = "Post Data"; var expectedResource = new Sample { Data = ExpectedData }; var result = Post(expectedResource, contentType); // Assert Assert.AreEqual(HttpStatusCode.Created, result.Response.StatusCode); // Check entity Assert.AreEqual(ExpectedData, result.Sample.Data); // Check headers Assert.IsNotNull(result.Response.Headers.ETag, "Null etag"); Assert.IsNotNull(result.Response.Headers.Location, "Null location"); // Check server generated key and location header Assert.AreEqual( result.Sample.Key, ParseKeyFromLocation(result.Response.Headers.Location.PathAndQuery), "Location header key should match entity key"); Assert.IsTrue(result.Sample.Key > 5, "Server generated key should be > 5 on test data set"); }
/// <summary> /// The post. /// </summary> /// <param name="sample"> /// The sample. /// </param> /// <param name="contentType"> /// The content type. /// </param> /// <returns> /// The TestResult /// </returns> private static TestResult Post(Sample sample, string contentType = XmlContentType) { using (var client = CreateHttpClient(contentType)) { return new TestResult( client.Post(ServiceUri, new ObjectContent(typeof(Sample), sample, Sample.XmlMediaType))); } }