/// <summary> /// Uploads a file or a custom binary property of a content in the provided container. /// </summary> /// <param name="parentId">Parent id.</param> /// <param name="contentName">Name of the content to create or update.</param> /// <param name="fileSize">Full length of the binary data.</param> /// <param name="blobCallback">An action that is called between the initial and the finalizer requests. /// Use this to actually save the binary through the blob storage component. /// Parameters: contentId, versionId, token</param> /// <param name="contentType">Content type of the new content. Default is determined by the allowed child types in the container.</param> /// <param name="fileName">Binary file name. Default is the content name.</param> /// <param name="propertyName">Binary field name. Default is "Binary".</param> /// <param name="server">Target server.</param> public static async Task UploadBlobAsync(int parentId, string contentName, long fileSize, Func <int, int, string, Task> blobCallback, string contentType = null, string fileName = null, string propertyName = null, ServerContext server = null) { if (string.IsNullOrEmpty(contentName)) { throw new ArgumentNullException(nameof(contentName)); } if (blobCallback == null) { throw new ArgumentNullException(nameof(blobCallback)); } // send initial request var responseText = await RESTCaller.GetResponseStringAsync(parentId, "StartBlobUploadToParent", HttpMethod.Post, JsonHelper.Serialize(new { name = contentName, contentType, fullSize = fileSize, fieldName = propertyName }), server); // call the common method that contains the part that is the same for all implementations await SaveAndFinalizeBlobInternalAsync(responseText, fileSize, blobCallback, fileName, propertyName, server); }
private static async Task SaveAndFinalizeBlobInternalAsync(string initResponse, long fileSize, Func <int, int, string, Task> blobCallback, string fileName = null, string propertyName = null, ServerContext server = null) { // parse the response of the initial request var response = JsonHelper.Deserialize(initResponse); int contentId = response.id; string token = response.token; int versionId = response.versionId; // save binary through the blob storage await blobCallback(contentId, versionId, token).ConfigureAwait(false); // send final request await RESTCaller.GetResponseStringAsync(contentId, "FinalizeBlobUpload", HttpMethod.Post, JsonHelper.Serialize(new { token, fullSize = fileSize, fieldName = propertyName, fileName }), server) .ConfigureAwait(false); }
//============================================================================= Instance API /// <summary> /// Saves the content to the server. /// </summary> public async Task SaveAsync() { dynamic postData = new ExpandoObject(); postData.Name = this.Name; // add local field values to post data if (_fields != null) { var dict = postData as IDictionary <string, object>; foreach (var field in _fields) { dict[field.Key] = field.Value; } } dynamic responseContent = Existing ? (this.Id > 0 ? await RESTCaller.PatchContentAsync(this.Id, postData, Server) : await RESTCaller.PatchContentAsync(this.Path, postData, Server)) : await RESTCaller.PostContentAsync(this.ParentPath, postData, Server); // reset local values InitializeFromResponse(responseContent); }
/// <summary> /// Calls a dynamic method on a content. It will be resolved into an asynchronous OData action request (DynamicObject implementation). /// </summary> /// <param name="binder">Method binder definition.</param> /// <param name="args">Method arguments provided by the caller.</param> /// <param name="result">An awaitable Task<dynamic> object containing the response of the action request.</param> /// <returns>Aleays true.</returns> public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { var requestData = new ODataRequest(Server) { ContentId = this.Id, Path = this.Path, ActionName = binder.Name }; HttpMethod method = null; object postData = null; // Get http method and post data from the optional argument list. // It is possible to provide both of them or none of them. if (args != null && args.Length > 0) { // tale only the first 2 params into account for (var i = 0; i < Math.Min(2, args.Length); i++) { var httpMethod = args[i] as HttpMethod; if (httpMethod != null) { method = httpMethod; } else { postData = args[i]; } } } result = RESTCaller.GetResponseJsonAsync(requestData, Server, method, postData); return(true); }
/// <summary> /// Removes members from a group. /// </summary> /// <param name="groupId">Group id.</param> /// <param name="memberIds">Ids of members to remove from the group.</param> /// <param name="server">Target server.</param> public static async Task RemoveMembersAsync(int groupId, int[] memberIds, ServerContext server = null) { await RESTCaller.GetResponseStringAsync(groupId, "RemoveMembers", HttpMethod.Post, JsonHelper.GetJsonPostModel(new { contentIds = memberIds }), server); }
/// <summary> /// Gets a blob storage token that identifies a binary in the storage. /// </summary> /// <param name="path">Content path.</param> /// <param name="version">Content version (e.g. V2.3D). If not provided, the highest version /// accessible to the current user will be served.</param> /// <param name="propertyName">Binary field name. Default is Binary.</param> /// <param name="server">Target server.</param> /// <returns>A token that can be used with the Blob storage API.</returns> public static async Task <string> GetBlobToken(string path, string version = null, string propertyName = null, ServerContext server = null) { var responseText = await RESTCaller.GetResponseStringAsync(path, "GetBinaryToken", HttpMethod.Post, JsonHelper.Serialize(new { version, fieldName = propertyName }), server); var response = JsonHelper.Deserialize(responseText); return(response.token); }
/// <summary> /// Deletes one or more content by Id or Path. /// </summary> /// <param name="idsOrPaths">One or more id or path of the <see cref="Content"/> objects to delete.</param> /// <param name="permanent">Delete the content permanently or into the Trash.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <param name="server">Target server. If null, the first one will be used from the configuration.</param> /// <returns>A task that represents an asynchronous operation.</returns> public static async Task DeleteAsync(object[] idsOrPaths, bool permanent, CancellationToken cancellationToken, ServerContext server = null) { await RESTCaller.GetResponseStringAsync("/Root", "DeleteBatch", HttpMethod.Post, JsonHelper.GetJsonPostModel(new { permanent, paths = idsOrPaths }), server) .ConfigureAwait(false); }
/// <summary> /// Undo all modifications on the content since the last checkout operation. /// </summary> public async Task UndoCheckOutAsync() { var requestData = new ODataRequest(Server) { ContentId = this.Id, Path = this.Path, ActionName = "UndoCheckOut", Select = new [] { "Id" } }; await RESTCaller.GetResponseStringAsync(requestData.GetUri(), Server, HttpMethod.Post).ConfigureAwait(false); }
/// <summary> /// Executes a count-only query in a subfolder on the server. /// </summary> /// <param name="path">Content path.</param> /// <param name="query">Content query text. If it is empty, the count of children will be returned.</param> /// <param name="server">Target server.</param> /// <returns>Count of result content.</returns> public static async Task <int> GetCountAsync(string path, string query, ServerContext server = null) { var request = new ODataRequest(server) { Path = path, IsCollectionRequest = true, ContentQuery = query, CountOnly = true }; return(await RESTCaller.GetCountAsync(request, server).ConfigureAwait(false)); }
/// <summary> /// Checks whether a content exists on the server with the provided path. /// </summary> /// <param name="path">Content path.</param> /// <param name="server">Target server.</param> public static async Task <bool> ExistsAsync(string path, ServerContext server = null) { var requestData = new ODataRequest(server) { Path = path, Metadata = MetadataFormat.None, Select = new[] { "Id" } }; var content = await RESTCaller.GetContentAsync(requestData, server).ConfigureAwait(false); return(content != null); }
/// <summary> /// Check in the content. /// </summary> public async Task CheckInAsync() { var requestData = new ODataRequest() { SiteUrl = Server.Url, ContentId = this.Id, Path = this.Path, ActionName = "CheckIn", Select = new[] { "Id" } }; await RESTCaller.GetResponseStringAsync(requestData.GetUri(), Server, HttpMethod.Post); }
/// <summary> /// Checks whether a content exists on the server with the provided path. /// </summary> /// <param name="path">Content path.</param> /// <param name="server">Target server.</param> public static async Task <bool> ExistsAsync(string path, ServerContext server = null) { var requestData = new ODataRequest() { SiteUrl = ServerContext.GetUrl(server), Path = path, Metadata = MetadataFormat.None, Select = new[] { "Id" } }; var content = await RESTCaller.GetContentAsync(requestData); return(content != null); }
/// <summary> /// Creates a copy of the content to the target location. /// </summary> /// <param name="targetPath">Target path.</param> public async Task CopyToAsync(string targetPath) { var requestData = new ODataRequest() { SiteUrl = Server.Url, ContentId = this.Id, Path = this.Path, ActionName = "CopyTo" }; await RESTCaller.GetResponseStringAsync(requestData.GetUri(), Server, HttpMethod.Post, JsonHelper.GetJsonPostModel(new { targetPath })); }
/// <summary> /// Deletes the content. /// </summary> /// <param name="permanent">Delete the content permanently or into the Trash.</param> public async Task DeleteAsync(bool permanent = true) { var requestData = new ODataRequest() { SiteUrl = Server.Url, ContentId = this.Id, Path = this.Path, ActionName = "Delete" }; await RESTCaller.GetResponseStringAsync(requestData.GetUri(), Server, HttpMethod.Post, JsonHelper.GetJsonPostModel(new { permanent })); }
/// <summary> /// Moves the content to the target location. /// </summary> /// <param name="targetPath">Target path.</param> public async Task MoveToAsync(string targetPath) { var requestData = new ODataRequest(Server) { ContentId = this.Id, Path = this.Path, ActionName = "MoveTo" }; await RESTCaller.GetResponseStringAsync(requestData.GetUri(), Server, HttpMethod.Post, JsonHelper.GetJsonPostModel(new { targetPath })) .ConfigureAwait(false); }
/// <summary> /// Executes a count-only query in a subfolder on the server. /// </summary> /// <param name="path">Content path.</param> /// <param name="query">Content query text. If it is empty, the count of children will be returned.</param> /// <param name="server">Target server.</param> /// <returns>Count of result content.</returns> public static async Task <int> GetCountAsync(string path, string query, ServerContext server = null) { var request = new ODataRequest { SiteUrl = ServerContext.GetUrl(server), Path = path, IsCollectionRequest = true, CountOnly = true }; if (!string.IsNullOrEmpty(query)) { request.Parameters.Add("query", query); } return(await RESTCaller.GetCountAsync(request, server)); }
/// <summary> /// Uploads a file to the server into the provided container. /// </summary> /// <param name="parentId">Parent id.</param> /// <param name="fileName">Name of the file to upload.</param> /// <param name="stream">File contents.</param> /// <param name="contentType">Content type of the file. Default is determined by the container.</param> /// <param name="propertyName">Name of the field to upload to. Default is Binary.</param> /// <param name="server">Target server.</param> /// <param name="progressCallback">An optional callback method that is called after each chunk is uploaded to the server.</param> /// <returns>The uploaded file content returned at the end of the upload request.</returns> public static async Task <Content> UploadAsync(int parentId, string fileName, Stream stream, string contentType = null, string propertyName = null, ServerContext server = null, Action <int> progressCallback = null) { var uploadData = new UploadData() { FileName = fileName, FileLength = stream.Length }; if (!string.IsNullOrEmpty(contentType)) { uploadData.ContentType = contentType; } if (!string.IsNullOrEmpty(propertyName)) { uploadData.PropertyName = propertyName; } return(await RESTCaller.UploadAsync(stream, uploadData, parentId, server, progressCallback)); }
/// <summary> /// Uploads a file to the server into the provided container. /// </summary> /// <param name="parentId">Parent id.</param> /// <param name="fileName">Name of the file to upload.</param> /// <param name="fileText">File content.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <param name="contentType">Content type of the file.</param> /// <param name="propertyName">Name of the field to upload to. Default is Binary.</param> /// <param name="server">Target server.</param> /// <returns>The uploaded file content returned at the end of the upload request.</returns> public static async Task <Content> UploadTextAsync(int parentId, string fileName, string fileText, CancellationToken cancellationToken, string contentType = null, string propertyName = null, ServerContext server = null) { var uploadData = new UploadData() { FileName = fileName, ContentType = contentType, }; if (!string.IsNullOrEmpty(contentType)) { uploadData.ContentType = contentType; } if (!string.IsNullOrEmpty(propertyName)) { uploadData.PropertyName = propertyName; } return(await RESTCaller.UploadTextAsync(fileText, uploadData, parentId, cancellationToken, server) .ConfigureAwait(false)); }
/// <summary> /// Loads a content from the server. Use this method to specify a detailed /// content request, for example wich fields you want to expand or select. /// </summary> /// <param name="requestData">Detailed information that will be sent as part of the request.</param> /// <param name="server">Target server.</param> public static async Task <Content> LoadAsync(ODataRequest requestData, ServerContext server = null) { return(await RESTCaller.GetContentAsync(requestData, server)); }
//============================================================================= Static API /// <summary> /// Loads a content from the server. /// </summary> /// <param name="id">Content id.</param> /// <param name="server">Target server.</param> public static async Task <Content> LoadAsync(int id, ServerContext server = null) { return(await RESTCaller.GetContentAsync(id, server)); }
/// <summary> /// Queries the server for content items using the provided request data. /// </summary> /// <param name="requestData">Detailed information that will be sent as part of the request. /// For example Top, Skip, Select, etc.</param> /// <param name="server">Target server.</param> public static async Task <IEnumerable <Content> > LoadCollectionAsync(ODataRequest requestData, ServerContext server = null) { return(await RESTCaller.GetCollectionAsync(requestData, server)); }
/// <summary> /// Loads children of a container. /// </summary> /// <param name="path">Path of the container.</param> /// <param name="server">Target server.</param> /// <returns></returns> public static async Task <IEnumerable <Content> > LoadCollectionAsync(string path, ServerContext server = null) { return(await RESTCaller.GetCollectionAsync(path, server)); }
/// <summary> /// Loads a content from the server. /// </summary> /// <param name="path">Content path.</param> /// <param name="server">Target server.</param> public static async Task <Content> LoadAsync(string path, ServerContext server = null) { return(await RESTCaller.GetContentAsync(path, server)); }