public Customer AddCustomer(Customer customer) { lock (writeLock) { string id = (++counter).ToString(); // Set the Uri of the customer and add it to the colleciton UriTemplate itemTemplate = WebOperationContext.Current.GetUriTemplate("GetCustomer"); customer.Uri = itemTemplate.BindByPosition(WebOperationContext.Current.IncomingRequest.UriTemplateMatch.BaseUri, id); customers[id] = customer; // initialize an etag for the newly added customer long newEtag = DateTime.UtcNow.Ticks; customerEtags[id] = newEtag; // set the new etag in the response WebOperationContext.Current.OutgoingResponse.SetETag(newEtag); // update the etag for the customer collection since the list has changed (item added to it) this.customerListEtag = DateTime.UtcNow.Ticks; WebOperationContext.Current.OutgoingResponse.SetStatusAsCreated(customer.Uri); } return customer; }
static void Main(string[] args) { using (WebServiceHost host = new WebServiceHost(typeof(Service), new Uri("http://localhost:8000/Customers"))) { //WebServiceHost will automatically create a default endpoint at the base address using the WebHttpBinding //and the WebHttpBehavior, so there's no need to set it up explicitly host.Open(); Uri baseAddress = new Uri("http://localhost:8000/Customers"); Console.WriteLine("Service is hosted at: " + baseAddress.AbsoluteUri); Console.WriteLine("Service help page is at: " + baseAddress.AbsoluteUri + "/help"); Console.WriteLine(""); Console.WriteLine("Adding some customers with POST:"); Customer alice = new Customer("Alice", "123 Pike Place", null); Uri aliceLocation = PostCustomer(baseAddress, alice); Customer bob = new Customer("Bob", "2323 Lake Shore Drive", null); Uri bobLocation = PostCustomer(baseAddress, bob); Console.WriteLine(""); Console.WriteLine("Using PUT to update a customer without specifying an Etag in the request. This will fail with error PreconditionFailed"); alice.Name = "Charlie"; alice.Uri = aliceLocation; string aliceEtag = null; try { PutCustomer(aliceLocation, alice, aliceEtag); } catch (WebException ex) { HttpWebResponse response = (HttpWebResponse)ex.Response; Console.WriteLine("Request failed with error '{0}'", response.StatusCode); aliceEtag = response.Headers[HttpResponseHeader.ETag]; } Console.WriteLine("Retrying PUT to update a customer after specifying the latest Etag in the request. This will succeed"); PutCustomer(aliceLocation, alice, aliceEtag); Console.WriteLine(""); Console.WriteLine("Using GET to retrieve the list of customers"); string customerListEtag = null; List<Customer> customers = GetCustomers(baseAddress, ref customerListEtag); foreach (Customer c in customers) { Console.WriteLine(c.ToString()); } Console.WriteLine("Doing a conditional GET to retrieve the list of customers again. This will return NotMofified"); try { GetCustomers(baseAddress, ref customerListEtag); } catch (WebException ex) { HttpWebResponse response = (HttpWebResponse)ex.Response; Console.WriteLine("Request failed with error '{0}'", response.StatusCode); } Console.WriteLine(""); Console.WriteLine("Using DELETE to delete a customer without specifying an Etag in the request. This will fail with error PreconditionFailed"); string bobEtag = null; try { DeleteCustomer(bobLocation, bobEtag); } catch (WebException ex) { HttpWebResponse response = (HttpWebResponse)ex.Response; Console.WriteLine("Request failed with error '{0}'", response.StatusCode); bobEtag = response.Headers[HttpResponseHeader.ETag]; } Console.WriteLine("Retrying DELETE with the latest Etag in the request. This will succeed"); DeleteCustomer(bobLocation, bobEtag); Console.WriteLine(""); Console.WriteLine("Doing a conditional GET for final list of customers. This will not return NotModified since the etag for the customer list is stale"); customers = GetCustomers(baseAddress, ref customerListEtag); foreach (Customer c in customers) { Console.WriteLine(c.ToString()); } Console.WriteLine(""); Console.WriteLine("Press any key to terminate"); Console.ReadLine(); } }
static void PutCustomer(Uri uri, Customer customer, string etag) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "PUT"; request.ContentType = "application/xml"; request.Headers[HttpRequestHeader.IfMatch] = etag; using (Stream requestStream = request.GetRequestStream()) { customerSerializer.WriteObject(requestStream, customer); } HttpWebResponse response = (HttpWebResponse)request.GetResponse(); using (Stream responseStream = response.GetResponseStream()) { Customer updatedItem = (Customer)customerSerializer.ReadObject(responseStream); Console.WriteLine(updatedItem.ToString()); } response.Close(); }
static Uri PostCustomer(Uri uri, Customer customer) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "POST"; request.ContentType = "application/xml"; using (Stream requestStream = request.GetRequestStream()) { customerSerializer.WriteObject(requestStream, customer); } HttpWebResponse response = (HttpWebResponse) request.GetResponse(); using (Stream responseStream = response.GetResponseStream()) { Customer createdItem = (Customer) customerSerializer.ReadObject(responseStream); Console.WriteLine(createdItem.ToString()); } response.Close(); return new Uri(response.Headers[HttpResponseHeader.Location]); }
public Customer UpdateCustomer(string id, Customer newCustomer) { lock (writeLock) { // return NotFound if there is no item with the specified id. object itemEtag = customerEtags[id]; if (itemEtag == null) { throw new WebFaultException(HttpStatusCode.NotFound); } // Return PreconditionFailed if the client request does not have an etag or has an old etag for the item WebOperationContext.Current.IncomingRequest.CheckConditionalUpdate((long)itemEtag); customers[id] = newCustomer; // update the etag for the item since it has changed long newEtag = DateTime.UtcNow.Ticks; customerEtags[id] = newEtag; // update the customer list etag since the item in the list has changed this.customerListEtag = DateTime.UtcNow.Ticks; // set the updated etag in the response WebOperationContext.Current.OutgoingResponse.SetETag(newEtag); return newCustomer; } }