public object GetChanges() { var changes = _values .Select(pair => { var value = pair.Value; object snapshot; if (_snapshot.TryGetValue(pair.Key, out snapshot) && Equals(value, snapshot)) { var tracking = value as IChangeTracking; if (tracking == null) { return(null); } value = tracking.GetChanges(); if (value == null) { return(null); } } return(new { pair.Key, value }); }) .Where(item => item != null) .ToDictionary(item => item.Key, item => item.value); if (changes.Count == 0) { return(null); } var resource = new SDataResource(changes); ((ISDataProtocolObject)resource).Info = _info; return(resource); }
private SDataRequest CreateBatchRequest(ICollection <SDataParameters> items) { Guard.ArgumentNotNull(items, "items"); var resources = new SDataCollection <SDataResource>(items.Count); string path = null; MediaType?contentType = null; var include = new List <string>(); var select = new List <string>(); int? precedence = null; MediaType?format = null; string language = null; string version = null; var accept = new List <MediaType>(); var form = new Dictionary <string, string>(); var files = new List <AttachedFile>(); var extensionArgs = new Dictionary <string, string>(); foreach (var parms in items) { if (parms.StartIndex != null) { throw new NotSupportedException("StartIndex not supported in batch requests"); } if (parms.Count != null) { throw new NotSupportedException("Count not supported in batch requests"); } if (parms.Where != null) { throw new NotSupportedException("Where not supported in batch requests"); } if (parms.OrderBy != null) { throw new NotSupportedException("OrderBy not supported in batch requests"); } if (parms.Search != null) { throw new NotSupportedException("Search not supported in batch requests"); } if (parms.TrackingId != null) { throw new NotSupportedException("TrackingId not supported in batch requests"); } if (parms.IncludeSchema != null) { throw new NotSupportedException("IncludeSchema not supported in batch requests"); } if (parms.ReturnDelta != null) { throw new NotSupportedException("ReturnDelta not supported in batch requests"); } if (parms.Path != path) { if (path != null) { throw new SDataClientException("All non-null path values must be the same"); } path = parms.Path; } if (parms.ContentType != contentType) { if (contentType != null) { throw new SDataClientException("All non-null content type values must be the same"); } contentType = parms.ContentType; } if (parms.Include != null) { include.AddRange(parms.Include.Split(',')); } if (parms.Select != null) { select.AddRange(parms.Select.Split(',')); } if (parms.Precedence != null && parms.Precedence != precedence) { precedence = Math.Max(precedence ?? 0, parms.Precedence.Value); } if (parms.Format != format) { if (format != null) { throw new SDataClientException("All non-null format values must be the same"); } format = parms.Format; } if (parms.Language != language) { if (language != null) { throw new SDataClientException("All non-null language values must be the same"); } language = parms.Language; } if (parms.Version != version) { if (version != null) { throw new SDataClientException("All non-null version values must be the same"); } version = parms.Version; } if (parms.Accept != null) { accept.AddRange(parms.Accept); } foreach (var data in parms.Form) { form.Add(data.Key, data.Value); } files.AddRange(parms.Files); foreach (var arg in parms.ExtensionArgs) { extensionArgs[arg.Key] = arg.Value; } SDataResource resource; if (parms.Content == null) { resource = new SDataResource(); } else { var content = parms.Content; if (parms.Method == HttpMethod.Put && DifferentialUpdate) { var tracking = content as IChangeTracking; if (tracking != null) { content = tracking.GetChanges(); if (content == null) { throw new SDataClientException("Content doesn't have any changes"); } } } resource = ContentHelper.Serialize(content, NamingScheme) as SDataResource; if (resource == null) { throw new SDataClientException("Only resources can be submitted in batch requests"); } } resource.HttpMethod = parms.Method; if (parms.Method != HttpMethod.Post) { if (resource.Key == null) { throw new SDataClientException("A selector must be specified for GET, PUT and DELETE batch requests"); } var itemUri = new SDataUri(Uri) { Include = parms.Include, Select = parms.Select, Precedence = parms.Precedence }; if (path != null) { itemUri.AppendPath(path); } itemUri.LastPathSegment.Selector = SDataUri.FormatConstant(resource.Key); resource.Id = itemUri.AbsoluteUri; resource.Url = itemUri.Uri; } if (parms.ETag != null) { resource.IfMatch = parms.ETag; } resources.Add(resource); } var uri = new SDataUri(Uri) { Precedence = precedence, Format = format ?? Format, Language = language ?? Language, Version = version ?? Version }; if (path != null) { uri.AppendPath(path); } uri.AppendPath("$batch"); if (include.Count > 0) { uri.Include = string.Join(",", include.Distinct().ToArray()); } if (select.Count > 0) { uri.Select = string.Join(",", select.Distinct().ToArray()); } foreach (var arg in extensionArgs) { uri["_" + arg.Key] = arg.Value; } var request = CreateRequest(uri, HttpMethod.Post, resources); request.ContentType = contentType ?? Format; if (accept.Count > 0) { request.Accept = accept.Distinct().ToArray(); } foreach (var data in form) { request.Form.Add(data.Key, data.Value); } foreach (var file in files) { request.Files.Add(file); } if (language != null) { request.AcceptLanguage = language ?? Language; } TraceRequest(request); return(request); }
private static T GetServiceResult <T>(ISDataClient client, Expression bodyExpr, SDataResource content) { var value = content["response"]; var response = (SDataResource)value; var attr = ((MethodCallExpression)bodyExpr).Method.GetCustomAttribute <SDataServiceOperationAttribute>(); if (attr != null && !string.IsNullOrEmpty(attr.ResultPropertyName)) { value = response[attr.ResultPropertyName]; } else if (response.Count == 1) { var firstValue = response.Values.First(); var type = typeof(T); type = Nullable.GetUnderlyingType(type) ?? type; if (ContentHelper.IsObject(type) == ContentHelper.IsObject(firstValue)) { value = firstValue; } } var result = ContentHelper.Deserialize <T>(value, client.NamingScheme); var tracking = result as IChangeTracking; if (tracking != null) { tracking.AcceptChanges(); } return(result); }
private static SDataParameters GetServiceParameters(ISDataClient client, Expression bodyExpr, string path) { Guard.ArgumentNotNull(client, "client"); var callExpr = bodyExpr as MethodCallExpression; if (callExpr == null) { throw new SDataClientException("Expression must be a method call"); } var attr = callExpr.Method.GetCustomAttribute <SDataServiceOperationAttribute>(); var namingScheme = client.NamingScheme ?? NamingScheme.Default; var request = new SDataResource(); var instance = callExpr.Object != null?Expression.Lambda(callExpr.Object).Compile().DynamicInvoke() : null; if (path == null) { path = SDataPathAttribute.GetPath(instance != null ? instance.GetType() : callExpr.Method.DeclaringType); } if (instance != null) { if (attr == null || attr.PassInstanceBy == InstancePassingConvention.Selector || (attr.PassInstanceBy == InstancePassingConvention.Default && string.IsNullOrEmpty(attr.InstancePropertyName))) { if (path == null) { throw new SDataClientException("Path must be specified when passing instance context by selector"); } var key = ContentHelper.GetProtocolValue <string>(instance, SDataProtocolProperty.Key); if (string.IsNullOrEmpty(key)) { throw new SDataClientException("Unable to extract resource key from instance"); } path += string.Format("({0})", SDataUri.FormatConstant(key)); } else if (attr.PassInstanceBy == InstancePassingConvention.Default) { var key = ContentHelper.GetProtocolValue <string>(instance, SDataProtocolProperty.Key); request[attr.InstancePropertyName] = !string.IsNullOrEmpty(key) ? key : instance; } else { if (string.IsNullOrEmpty(attr.InstancePropertyName)) { throw new SDataClientException("Instance property name must be specified when passing instance context by key property or object property"); } if (attr.PassInstanceBy == InstancePassingConvention.KeyProperty) { var key = ContentHelper.GetProtocolValue <string>(instance, SDataProtocolProperty.Key); if (string.IsNullOrEmpty(key)) { throw new SDataClientException("Unable to extract resource key from instance"); } request[attr.InstancePropertyName] = key; } else if (attr.PassInstanceBy == InstancePassingConvention.ObjectProperty) { request[attr.InstancePropertyName] = instance; } } } if (path != null) { path += "/"; } path += "$service/" + namingScheme.GetName(callExpr.Method); foreach (var pair in callExpr.Method.GetParameters().Zip(callExpr.Arguments, (param, arg) => new { param, arg })) { request[namingScheme.GetName(pair.param)] = Expression.Lambda(pair.arg).Compile().DynamicInvoke(); } var xmlLocalName = attr != null ? attr.XmlLocalName : null; var xmlNamespace = attr != null ? attr.XmlNamespace : null; var content = new SDataResource(xmlLocalName, xmlNamespace) { { "request", request } }; return(new SDataParameters { Method = HttpMethod.Post, Path = path, Content = content }); }
public ResourceCustomTypeDescriptor(SDataResource instance) { _instance = instance; }