diff --git a/.gitignore b/.gitignore index 9de20b9..5b2e039 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ *.ReSharper* *.user _ReSharper*/* +*.ncrunchsolution diff --git a/DynamicRest.UnitTests/Xml/XmlResponsesTests.cs b/DynamicRest.UnitTests/Xml/XmlResponsesTests.cs index 6860d27..370384e 100644 --- a/DynamicRest.UnitTests/Xml/XmlResponsesTests.cs +++ b/DynamicRest.UnitTests/Xml/XmlResponsesTests.cs @@ -1,108 +1,155 @@ -using System; -using DynamicRest.Xml; -using Machine.Specifications; - -namespace DynamicRest.UnitTests.Xml -{ - [Subject(typeof(StandardResultBuilder))] - public class When_a_response_contains_a_collection { - - static StandardResultBuilder _resultBuilder; - static dynamic _response; - - Establish context = () => - { - _resultBuilder = new StandardResultBuilder(RestService.Xml); - }; - - Because the_response_is_created = () => { _response = _resultBuilder.CreateResult(_xml); }; - - It should_contain_the_media_0_url = () => (_response.item.media[0].url as string).ShouldEqual("http://media0url"); - It should_contain_the_media_1_url = () => (_response.item.media[1].url as string).ShouldEqual("http://media1url"); - It should_contain_the_image_0_url = () => (_response.item.images.image[0].src as string).ShouldEqual("http://image0url"); - It should_contain_the_image_1_url = () => (_response.item.images.image[1].src as string).ShouldEqual("http://image1url"); - It should_contain_the_link_using_array_access = () => (_response.item.link[0].Value as string).ShouldEqual("http://www.bbc.co.uk/go/rss/int/news/-/news/world-africa-12673956"); - It should_contain_the_attachment_title = () => (_response.item.attachments.attachment[0].title.Value as string).ShouldEqual("this is the title"); +using System; +using DynamicRest.Xml; +using Machine.Specifications; +using Machine.Specifications.Model; + +namespace DynamicRest.UnitTests.Xml +{ + [Subject(typeof(StandardResultBuilder))] + public class When_a_response_contains_a_collection { + + static StandardResultBuilder _resultBuilder; + static dynamic _response; + + Establish context = () => + { + _resultBuilder = new StandardResultBuilder(RestService.Xml); + }; + + Because the_response_is_created = () => { _response = _resultBuilder.CreateResult(_xml); }; + + It should_contain_the_media_0_url = () => (_response.item.media[0].url as string).ShouldEqual("http://media0url"); + It should_contain_the_media_1_url = () => (_response.item.media[1].url as string).ShouldEqual("http://media1url"); + It should_contain_the_image_0_url = () => (_response.item.images.image[0].src as string).ShouldEqual("http://image0url"); + It should_contain_the_image_1_url = () => (_response.item.images.image[1].src as string).ShouldEqual("http://image1url"); + It should_contain_the_link_using_array_access = () => (_response.item.link[0].Value as string).ShouldEqual("http://www.bbc.co.uk/go/rss/int/news/-/news/world-africa-12673956"); + It should_contain_the_attachment_title = () => (_response.item.attachments.attachment[0].title.Value as string).ShouldEqual("this is the title"); It should_contain_the_numbers_of_attachments = () => ((int)_response.item.attachments.Count).ShouldEqual(1); It should_contain_the_pubdate = - () => ((DateTime)_response.item.pubDate).ShouldEqual(new DateTime(2011, 3, 8, 11, 21, 16)); - - It should_work_when_a_refence_is_used_as_an_array = () => - { - var linkAsArray = _response.item.link; - ((string)linkAsArray[0].Value).ShouldEqual("http://www.bbc.co.uk/go/rss/int/news/-/news/world-africa-12673956"); - }; - - static string _xml = @" - - - Gaddafi renews attack on rebels - 5 - Forces loyal to Libyan leader Col Muammar Gaddafi launch fresh air strikes on the rebel-held Ras Lanuf, as they try to retake the oil-rich town. - http://www.bbc.co.uk/go/rss/int/news/-/news/world-africa-12673956 - http://www.bbc.co.uk/go/rss/int/news/-/news/world-africa-12673956 - http://www.bbc.co.uk/news/world-africa-12673956 - Tue, 08 Mar 2011 11:21:16 GMT - - - - - - - - - this is the title - - - - "; - } - - [Subject(typeof(XmlNode))] - public class When_accessing_a_non_existing_element { - - static StandardResultBuilder _resultBuilder; - static dynamic _response; - - Establish context = () => - { - _resultBuilder = new StandardResultBuilder(RestService.Xml); - _response = _resultBuilder.CreateResult(_xml); - }; - - private Because the_response_is_created = () => _thrownException = Catch.Exception(() => { var junk = _response.item.desc; }); - - It should_work_when_a_refence_is_used_as_an_array = () => - _thrownException.Message.ShouldEqual("No element or attribute named 'desc' found in the response."); - - static string _xml = @" - - - Gaddafi renews attack on rebels - Forces loyal to Libyan leader Col Muammar Gaddafi launch fresh air strikes on the rebel-held Ras Lanuf, as they try to retake the oil-rich town. - http://www.bbc.co.uk/go/rss/int/news/-/news/world-africa-12673956 - http://www.bbc.co.uk/go/rss/int/news/-/news/world-africa-12673956 - http://www.bbc.co.uk/news/world-africa-12673956 - Tue, 08 Mar 2011 11:21:16 GMT - - - - - - - - - this is the title - - - - "; - - private static Exception _thrownException; + () => ((DateTime)_response.item.pubDate).ShouldEqual(new DateTime(2011, 3, 8, 11, 21, 16)); + + It should_work_when_a_refence_is_used_as_an_array = () => + { + var linkAsArray = _response.item.link; + ((string)linkAsArray[0].Value).ShouldEqual("http://www.bbc.co.uk/go/rss/int/news/-/news/world-africa-12673956"); + }; + + static string _xml = @" + + + Gaddafi renews attack on rebels + 5 + Forces loyal to Libyan leader Col Muammar Gaddafi launch fresh air strikes on the rebel-held Ras Lanuf, as they try to retake the oil-rich town. + http://www.bbc.co.uk/go/rss/int/news/-/news/world-africa-12673956 + http://www.bbc.co.uk/go/rss/int/news/-/news/world-africa-12673956 + http://www.bbc.co.uk/news/world-africa-12673956 + Tue, 08 Mar 2011 11:21:16 GMT + + + + + + + + + this is the title + + + + "; + } + + [Subject(typeof(StandardResultBuilder))] + public class When_a_response_contains_an_empty_collection + { + static StandardResultBuilder _resultBuilder; + static dynamic _response; + + Establish context = () => + { + _resultBuilder = new StandardResultBuilder(RestService.Xml); + }; + + Because the_response_is_created = () => { _response = _resultBuilder.CreateResult(_xml); }; + + It should_count_zero_elements = () => ((int)_response.images.Count).ShouldEqual(0); + + static string _xml = @" + + + "; + } + + [Subject(typeof(StandardResultBuilder))] + public class When_a_parsing_in_a_datetime + { + static StandardResultBuilder _resultBuilder; + static dynamic _response; + + Establish context = () => + { + _resultBuilder = new StandardResultBuilder(RestService.Xml); + }; + + Because the_response_is_created = () => { _response = _resultBuilder.CreateResult(_xml); }; + + + It should_pass = () => ShouldExtensionMethods.ShouldEqual(DateTime.Parse(_response.created), TimeStamp); + + static string _xml = @" + + 2007-10-10T09:02:17Z + "; + + static DateTime TimeStamp = DateTime.Parse("2007-10-10T09:02:17Z"); + } + + [Subject(typeof(XmlNode))] + public class When_accessing_a_non_existing_element { + + static StandardResultBuilder _resultBuilder; + static dynamic _response; + + Establish context = () => + { + _resultBuilder = new StandardResultBuilder(RestService.Xml); + _response = _resultBuilder.CreateResult(_xml); + }; + + private Because the_response_is_created = () => _thrownException = Catch.Exception(() => { var junk = _response.item.desc; }); + + It should_work_when_a_refence_is_used_as_an_array = () => + _thrownException.Message.ShouldEqual("No element or attribute named 'desc' found in the response."); + + static string _xml = @" + + + Gaddafi renews attack on rebels + Forces loyal to Libyan leader Col Muammar Gaddafi launch fresh air strikes on the rebel-held Ras Lanuf, as they try to retake the oil-rich town. + http://www.bbc.co.uk/go/rss/int/news/-/news/world-africa-12673956 + http://www.bbc.co.uk/go/rss/int/news/-/news/world-africa-12673956 + http://www.bbc.co.uk/news/world-africa-12673956 + Tue, 08 Mar 2011 11:21:16 GMT + + + + + + + + + this is the title + + + + "; + + private static Exception _thrownException; } + namespace When_casting_strings_to_datetimes { [Subject(typeof(XmlString))] @@ -217,7 +264,7 @@ public class When_parsing_fails private static Exception The_result; } } - + namespace When_casting_strings_to_bools { public class When_parsing_the_empty_string @@ -289,5 +336,5 @@ public class When_parsing_weird_casing protected static bool Result { get; set; } } - } + } } \ No newline at end of file diff --git a/DynamicRest/Fluent/RestClientBuilder.cs b/DynamicRest/Fluent/RestClientBuilder.cs index da22d90..2dc71b8 100644 --- a/DynamicRest/Fluent/RestClientBuilder.cs +++ b/DynamicRest/Fluent/RestClientBuilder.cs @@ -1,21 +1,21 @@ using System; using System.Collections.Generic; using System.Net; -using DynamicRest.HTTPInterfaces.WebWrappers; - -namespace DynamicRest.Fluent { - - public class RestClientBuilder : IRestClientBuilder { - - IBuildRequests _requestBuilder; - IProcessResponses _responseProcessor; - string _uri; - string _contentType; - string _body; - string _acceptType; - string _token; - bool _noAcceptHeader; - private bool _autoRedirect; +using DynamicRest.HTTPInterfaces.WebWrappers; + +namespace DynamicRest.Fluent { + + public class RestClientBuilder : IRestClientBuilder { + + IBuildRequests _requestBuilder; + IProcessResponses _responseProcessor; + string _uri; + string _contentType; + string _body; + string _acceptType; + string _token; + bool _noAcceptHeader; + private bool _autoRedirect; private string _acceptEncodingType; Dictionary _headers; Dictionary _customHeaders; @@ -27,32 +27,32 @@ public RestClientBuilder() _customHeaders = new Dictionary(); } - public dynamic Build() { - _contentType = _contentType ?? "application/xml"; - _acceptType = _acceptType ?? "application/xml"; - if (_noAcceptHeader){ - _acceptType = string.Empty; - } - - if (_requestBuilder == null) { - _requestBuilder = new HttpVerbRequestBuilder(new RequestFactory()); - } - - if (_responseProcessor == null) { - var serviceType = _acceptType.Contains("xml") ? RestService.Xml : (_acceptType.Contains("json") ? RestService.Json : RestService.Binary); - if (_noAcceptHeader){ - serviceType = RestService.Xml; - } - - this._responseProcessor = new ResponseProcessor(new StandardResultBuilder(serviceType)); - } - - _requestBuilder.Uri = _uri; - _requestBuilder.ContentType = _contentType; - _requestBuilder.AcceptHeader = _acceptType; - _requestBuilder.Body = _body; - _requestBuilder.SetOAuth2AuthorizationHeader(_token); - _requestBuilder.AllowAutoRedirect = _autoRedirect; + public dynamic Build() { + _contentType = _contentType ?? "application/xml"; + _acceptType = _acceptType ?? "application/xml"; + if (_noAcceptHeader){ + _acceptType = string.Empty; + } + + if (_requestBuilder == null) { + _requestBuilder = new HttpVerbRequestBuilder(new RequestFactory()); + } + + if (_responseProcessor == null) { + var serviceType = _acceptType.Contains("xml") ? RestService.Xml : (_acceptType.Contains("json") ? RestService.Json : RestService.Binary); + if (_noAcceptHeader){ + serviceType = RestService.Xml; + } + + this._responseProcessor = new ResponseProcessor(new StandardResultBuilder(serviceType)); + } + + _requestBuilder.Uri = _uri; + _requestBuilder.ContentType = _contentType; + _requestBuilder.AcceptHeader = _acceptType; + _requestBuilder.Body = _body; + _requestBuilder.SetOAuth2AuthorizationHeader(_token); + _requestBuilder.AllowAutoRedirect = _autoRedirect; if(!string.IsNullOrEmpty(_acceptEncodingType)) { _requestBuilder.AddHeader(HttpRequestHeader.AcceptEncoding, _acceptEncodingType); @@ -71,40 +71,40 @@ public dynamic Build() { foreach (var header in _customHeaders) { _requestBuilder.AddCustomHeader(header.Key, header.Value); - } - - return new RestClient(_requestBuilder, _responseProcessor); - } - - public IRestClientBuilder WithContentType(string contentType) { - _contentType = contentType; - return this; - } - - public IRestClientBuilder WithRequestBuilder(IBuildRequests requestBuilder) { - _requestBuilder = requestBuilder; - return this; - } - - public IRestClientBuilder WithUri(string uri) { - _uri = uri; - return this; - } - - public IRestClientBuilder WithBody(string body) { - _body = body; - return this; - } - - public IRestClientBuilder WithAcceptHeader(string acceptType) { - _acceptType = acceptType; - return this; - } - - public IRestClientBuilder WithAcceptEncodingHeader(string acceptEncodingType) - { - _acceptEncodingType = acceptEncodingType; - return this; + } + + return new RestClient(_requestBuilder, _responseProcessor); + } + + public IRestClientBuilder WithContentType(string contentType) { + _contentType = contentType; + return this; + } + + public IRestClientBuilder WithRequestBuilder(IBuildRequests requestBuilder) { + _requestBuilder = requestBuilder; + return this; + } + + public IRestClientBuilder WithUri(string uri) { + _uri = uri; + return this; + } + + public IRestClientBuilder WithBody(string body) { + _body = body; + return this; + } + + public IRestClientBuilder WithAcceptHeader(string acceptType) { + _acceptType = acceptType; + return this; + } + + public IRestClientBuilder WithAcceptEncodingHeader(string acceptEncodingType) + { + _acceptEncodingType = acceptEncodingType; + return this; } public IRestClientBuilder WithIfModifiedSinceDate(DateTime ifModifiedSince) @@ -113,26 +113,26 @@ public IRestClientBuilder WithIfModifiedSinceDate(DateTime ifModifiedSince) return this; } - public IRestClientBuilder WithOAuth2Token(string token) { - _token = token; - return this; - } - - public IRestClientBuilder WithResponseProcessor(IProcessResponses responseProcessor) { - _responseProcessor = responseProcessor; - return this; - } - - public IRestClientBuilder WithNoAcceptHeader() { - _noAcceptHeader = true; - return this; - } - - public IRestClientBuilder WithAutoRedirect(bool autoRedirect) { - _autoRedirect = autoRedirect; - return this; - } - + public IRestClientBuilder WithOAuth2Token(string token) { + _token = token; + return this; + } + + public IRestClientBuilder WithResponseProcessor(IProcessResponses responseProcessor) { + _responseProcessor = responseProcessor; + return this; + } + + public IRestClientBuilder WithNoAcceptHeader() { + _noAcceptHeader = true; + return this; + } + + public IRestClientBuilder WithAutoRedirect(bool autoRedirect) { + _autoRedirect = autoRedirect; + return this; + } + public IRestClientBuilder WithHeaders(Dictionary headers) { foreach (var header in headers) @@ -150,6 +150,6 @@ public IRestClientBuilder WithCustomHeaders(Dictionary headers) } return this; } - - } + + } } \ No newline at end of file diff --git a/DynamicRest/Xml/XmlNode.cs b/DynamicRest/Xml/XmlNode.cs index 8149864..a0e80ee 100644 --- a/DynamicRest/Xml/XmlNode.cs +++ b/DynamicRest/Xml/XmlNode.cs @@ -45,8 +45,8 @@ public override bool TryGetMember(GetMemberBinder binder, out object result) { if (String.CompareOrdinal(name, "Name") == 0) { result = _element.Name.LocalName; return true; - } - else if (String.CompareOrdinal(name, "Parent") == 0) { + } + if (String.CompareOrdinal(name, "Parent") == 0) { XElement parent = _element.Parent; if (parent != null) { result = new XmlNode(parent); @@ -54,58 +54,53 @@ public override bool TryGetMember(GetMemberBinder binder, out object result) { } result = null; return false; - } - else if (String.CompareOrdinal(name, "Value") == 0) { + } + if (String.CompareOrdinal(name, "Value") == 0) { result = _element.Value; return true; - } - else if (String.CompareOrdinal(name, "Count") == 0) { + } + if (String.CompareOrdinal(name, "Count") == 0) { result = _element.Elements().Count(); return true; - } - else if (String.CompareOrdinal(name, "Nodes") == 0) { + } + if (String.CompareOrdinal(name, "Nodes") == 0) { result = new XmlNodeList(_element.Elements()); return true; - } - else if (String.CompareOrdinal(name, "XElement") == 0) + } + if (String.CompareOrdinal(name, "XElement") == 0) { result = _element; return true; - } - else if (String.CompareOrdinal(name, "Xml") == 0) { + } + if (String.CompareOrdinal(name, "Xml") == 0) { StringWriter sw = new StringWriter(); _element.Save(sw, SaveOptions.None); result = sw.ToString(); return true; + } + XAttribute attribute = _element.Attributes().SingleOrDefault(a => a.Name.LocalName == name); + if (attribute != null) { + result = attribute.Value; + return true; } - else { - XAttribute attribute = _element.Attributes().SingleOrDefault(a => a.Name.LocalName == name); - if (attribute != null) { - result = attribute.Value; - return true; - } - try { - XElement childNode = _element.Elements().SingleOrDefault(a => a.Name.LocalName == name); - if (childNode != null) - { - if (childNode.HasElements == false) - { - result = new XmlString(childNode.Value); - return true; - } - result = new XmlNode(childNode); - return true; - } - } - catch (InvalidOperationException) - { - - result = new XmlNodeList(_element.Elements().Where(a => a.Name.LocalName == name)); + try { + XElement requestedElement = _element.Elements().SingleOrDefault(a => a.Name.LocalName == name); + if (requestedElement != null) + { + if (requestedElement.HasElements) + result = new XmlNode(requestedElement); + else + result = new XmlString(requestedElement.Value); return true; } } - + catch (InvalidOperationException) + { + result = new XmlNodeList(_element.Elements().Where(a => a.Name.LocalName == name)); + return true; + } + var memberExists = base.TryGetMember(binder, out result); if (result == null) { throw new XmlException(string.Format("No element or attribute named '{0}' found in the response.", name)); diff --git a/DynamicRest/Xml/XmlString.cs b/DynamicRest/Xml/XmlString.cs index 8f0bdc3..b6a1bba 100644 --- a/DynamicRest/Xml/XmlString.cs +++ b/DynamicRest/Xml/XmlString.cs @@ -1,64 +1,67 @@ using System; using System.Dynamic; -using System.Globalization; namespace DynamicRest.Xml { public class XmlString : DynamicObject { - readonly string value; - private const string isoDateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"; + readonly string _value; public XmlString(string value) { - this.value = value; + _value = value; } public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) { - result = value; + result = _value; return true; } public override bool TryGetMember(GetMemberBinder binder, out object result) { - result = value; + if (String.CompareOrdinal(binder.Name, "Count") == 0) + { + result = 0; + return true; + } + + result = _value; return true; } public override bool TryConvert(ConvertBinder binder, out object result) { - result = value; + result = _value; return true; } public override bool TryCreateInstance(CreateInstanceBinder binder, object[] args, out object result) { - result = value; + result = _value; return true; } public static implicit operator DateTime(XmlString input) { - return DateTime.Parse(input.value); + return DateTime.Parse(input._value); } public static implicit operator long(XmlString input) { - return long.Parse(input.value); + return long.Parse(input._value); } public static implicit operator int(XmlString input) { - return int.Parse(input.value); + return int.Parse(input._value); } public static implicit operator bool(XmlString input) { - if (input.value == "0" || input.value == "-1") return false; - if (input.value == "1") return true; - return bool.Parse(input.value); + if (input._value == "0" || input._value == "-1") return false; + if (input._value == "1") return true; + return bool.Parse(input._value); } public static implicit operator string(XmlString input) { - return input.value; + return input._value; } - } } \ No newline at end of file