using System.Net.Http.Headers; using System.Text; namespace System.Net.Http { public class HttpResponseMessage : IDisposable { private const HttpStatusCode defaultStatusCode = HttpStatusCode.OK; private const string defaultReasonPhrase = "OK"; private HttpStatusCode statusCode; private HttpResponseHeaders headers; private string reasonPhrase; private HttpRequestMessage requestMessage; private Version version; private HttpContent content; private bool disposed; public Version Version { get { return version; } set { if (value == null) { throw new ArgumentNullException("value"); } CheckDisposed(); version = value; } } public HttpContent Content { get { return content; } set { CheckDisposed(); content = value; } } public HttpStatusCode StatusCode { get { return statusCode; } set { if (((int)statusCode < 0) || ((int)statusCode > 999)) { throw new ArgumentOutOfRangeException("value"); } CheckDisposed(); statusCode = value; } } public string ReasonPhrase { get { return reasonPhrase; } set { if ((value != null) && ContainsNewLineCharacter(value)) { throw new FormatException("The reason phrase must not contain new-line characters."); } CheckDisposed(); reasonPhrase = value; // It's OK to have a 'null' reason phrase } } public HttpResponseHeaders Headers { get { if (headers == null) { headers = new HttpResponseHeaders(); } return headers; } } public HttpRequestMessage RequestMessage { get { return requestMessage; } set { CheckDisposed(); requestMessage = value; } } public bool IsSuccessStatusCode { get { return ((int)statusCode >= 200) && ((int)statusCode <= 299); } } public HttpResponseMessage() : this(defaultStatusCode, defaultReasonPhrase) { } public HttpResponseMessage(HttpStatusCode statusCode, string reasonPhrase) { if (((int)statusCode < 0) || ((int)statusCode > 999)) { throw new ArgumentOutOfRangeException("statusCode"); } this.statusCode = statusCode; this.reasonPhrase = reasonPhrase; this.version = HttpUtilities.DefaultVersion; } public HttpResponseMessage EnsureSuccessStatusCode() { if (!IsSuccessStatusCode) { // Disposing the content should help users: If users call EnsureSuccessStatusCode(), an exception is // thrown if the response status code is != 2xx. I.e. the behavior is similar to a failed request (e.g. // connection failure). Users don't expect to dispose the content in this case: If an exception is // thrown, the object is responsible fore cleaning up its state. if (content != null) { content.Dispose(); } throw new HttpException(string.Format("Response status code does not indicate success: {0} ({1})", (int)statusCode, reasonPhrase)); } return this; } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append("StatusCode: "); sb.Append((int)statusCode); sb.Append(", ReasonPhrase: '"); sb.Append(reasonPhrase == null ? "<null>" : reasonPhrase); sb.Append("', Version: "); sb.Append(version); sb.Append(", Content: "); sb.Append(content == null ? "<null>" : content.GetType().FullName); sb.Append(", Headers:\r\n"); sb.Append(HeaderUtilities.DumpHeaders(headers, content == null ? null : content.Headers)); return sb.ToString(); } private bool ContainsNewLineCharacter(string value) { foreach (char character in value) { if ((character == HttpRuleParser.CR) || (character == HttpRuleParser.LF)) { return true; } } return false; } #region IDisposable Members protected virtual void Dispose(bool disposing) { // The reason for this type to implement IDisposable is that it contains instances of types that implement // IDisposable (content). if (disposing && !disposed) { disposed = true; if (content != null) { content.Dispose(); } } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion private void CheckDisposed() { if (disposed) { throw new ObjectDisposedException(this.GetType().FullName); } } } }