public TRS SendRequest <TRS>(ProtoRequest protoRequest)
        {
            if (protoRequest == null)
            {
                throw new ArgumentNullException("protoRequest");
            }

            var requestPayload = protoRequest.Request == null ? null : SerializeToJson(protoRequest.Request);

            var requestHeaders = protoRequest.RequestHeaders ?? new Dictionary <string, string>();

            string existingAcceptTypes;

            requestHeaders.TryGetValue("accept", out existingAcceptTypes);

            requestHeaders["accept"] = RestfulServiceConstants.ProtoContentType +
                                       (string.IsNullOrEmpty(existingAcceptTypes)
                                            ? string.Empty
                                            : "," + existingAcceptTypes);

            requestHeaders["content-type"] = RestfulServiceConstants.JsonContentType;

            byte[] response;
            WebHeaderCollection responseHeaders;

            using (var client = new ExtendedWebClient(protoRequest.Timeout))
            {
                foreach (var requestHeader in requestHeaders)
                {
                    client.Headers.Add(requestHeader.Key, requestHeader.Value);
                }

                var method = protoRequest.Method ?? "GET";

                if (string.Equals(method, "GET", StringComparison.OrdinalIgnoreCase))
                {
                    response = client.DownloadData(protoRequest.ServiceUri);
                }
                else
                {
                    byte[] requestPayloadBytes;

                    if (string.IsNullOrEmpty(requestPayload))
                    {
                        requestPayloadBytes = new byte[0];
                    }
                    else
                    {
                        requestPayloadBytes = Encoding.UTF8.GetBytes(requestPayload);
                    }
                    response = client.UploadData(protoRequest.ServiceUri, method, requestPayloadBytes);
                }

                responseHeaders = client.ResponseHeaders;
            }

            ResponseHeaders = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
            foreach (var responseHeaderKey in responseHeaders.AllKeys)
            {
                ResponseHeaders.Add(responseHeaderKey, responseHeaders.Get(responseHeaderKey));
            }

            var responseContentType = ResponseHeaders["content-type"];

            if (responseContentType.Equals(RestfulServiceConstants.ProtoContentType, StringComparison.OrdinalIgnoreCase))
            {
                string modelKey;
                if (!ResponseHeaders.TryGetValue(RestfulServiceConstants.RqModelTypeHeaderKey, out modelKey))
                {
                    throw new InvalidDataException("The server sent a protoBuf response with no model key in the header, the service on the server side is behaving in an unexpected manner, contact the service administrator.");
                }

                var metaDataKey = GetMetaDataKey(protoRequest, modelKey);

                var metaData = MetaDatas.GetOrAdd(metaDataKey, s => GetMetaData(protoRequest, modelKey));

                var serializer = ObjectBuilder.GetSerializer();

                try
                {
                    return(serializer.Deserialize <TRS>(response, metaData, ModeType.WebAPI));
                }
                catch
                {
                    ClearMetaData(protoRequest);
                    throw;
                }
            }

            if (IsContentTypeSupported(responseContentType)) //deliberately put before json, in case custom json serialization is required.
            {
                return(DeserializeData <TRS>(responseContentType, response));
            }

            if (responseContentType.Equals(RestfulServiceConstants.JsonContentType, StringComparison.OrdinalIgnoreCase))
            {
                return(JsonSerializer.FromJson <TRS>(response));
            }

            throw new InvalidDataException(string.Format(
                                               "The response returned by the server did not contain a supported content-type header value, the returned content type was '{0}', supported types are '{1}' & {2}",
                                               responseContentType, RestfulServiceConstants.ProtoContentType, RestfulServiceConstants.JsonContentType));
        }