Example #1
0
        /// <summary>
        /// Removes an app from the app catalog
        /// </summary>
        /// <param name="id">The unique id of the app. Notice that this is not the product id as listed in the app catalog.</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <returns></returns>
        public async Task <bool> RemoveAsync(Guid id, AppCatalogScope scope = AppCatalogScope.Tenant)
        {
            if (id == Guid.Empty)
            {
                throw new ArgumentException(nameof(id));
            }

            await new SynchronizationContextRemover();

            return(await BaseRequest(id, AppManagerAction.Remove, true, null, scope));
        }
Example #2
0
#pragma warning restore CA2000

        private static async Task <AppMetadata> GetAppMetaData(AppCatalogScope scope, ClientContext context, string accessToken, PnPHttpProvider httpClient, string requestDigest, string id)
        {
            AppMetadata returnValue = null;
            int         retryCount  = 0;
            int         waitTime    = 10; // seconds

            var metadataRequestUrl = $"{context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps/GetById('{id}')";

            using (var metadataRequest = new HttpRequestMessage(HttpMethod.Get, metadataRequestUrl))
            {
                metadataRequest.Headers.Add("accept", "application/json;odata=nometadata");
                if (!string.IsNullOrEmpty(accessToken))
                {
                    metadataRequest.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
                }
                if (!string.IsNullOrEmpty(requestDigest))
                {
                    metadataRequest.Headers.Add("X-RequestDigest", requestDigest);
                }

                while (returnValue == null && retryCount < 5)
                {
                    // Perform actual post operation
                    HttpResponseMessage metadataResponse = await httpClient.SendAsync(metadataRequest, new System.Threading.CancellationToken());

                    if (metadataResponse.IsSuccessStatusCode)
                    {
                        // If value empty, URL is taken
                        var metadataResponseString = await metadataResponse.Content.ReadAsStringAsync();

                        if (metadataResponseString != null)
                        {
                            returnValue = JsonSerializer.Deserialize <AppMetadata>(metadataResponseString);
                        }
                    }
                    else if (metadataResponse.StatusCode != HttpStatusCode.NotFound)
                    {
                        // Something went wrong...
                        throw new Exception(await metadataResponse.Content.ReadAsStringAsync());
                    }
                    if (returnValue == null)
                    {
                        // try again
                        retryCount++;
                        Thread.Sleep(waitTime * 1000); // wait 10 seconds
                    }
                }
                return(returnValue);
            }
        }
Example #3
0
        public AppMetadata GetAppMetadata(ClientContext context, AppCatalogScope scope)
        {
            var appmanager = new AppManager(context);

            if (_id != Guid.Empty)
            {
                return(appmanager.GetAvailable(_id, scope));
            }
            if (!string.IsNullOrEmpty(_title))
            {
                return(appmanager.GetAvailable(_title, scope));
            }
            return(_metadata);
        }
Example #4
0
        /// <summary>
        /// Retracts an app in the app catalog. Notice that this will not remove the app from the app catalog.
        /// </summary>
        /// <param name="appMetadata">The app metadata object of the app to retract.</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <returns></returns>
        public async Task <bool> RetractAsync(AppMetadata appMetadata, AppCatalogScope scope = AppCatalogScope.Tenant)
        {
            if (appMetadata == null)
            {
                throw new ArgumentException(nameof(appMetadata));
            }
            if (appMetadata.Id == Guid.Empty)
            {
                throw new ArgumentException(nameof(appMetadata.Id));
            }

            await new SynchronizationContextRemover();

            return(await BaseRequest(appMetadata.Id, AppManagerAction.Retract, true, null, scope));
        }
Example #5
0
        /// <summary>
        /// Upgrades an app in a site
        /// </summary>
        /// <param name="appMetadata">The app metadata object of the app to upgrade.</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <returns></returns>
        public async Task <bool> UpgradeAsync(AppMetadata appMetadata, AppCatalogScope scope = AppCatalogScope.Tenant)
        {
            if (appMetadata == null)
            {
                throw new ArgumentException(nameof(appMetadata));
            }
            if (appMetadata.Id == Guid.Empty)
            {
                throw new ArgumentException(nameof(appMetadata.Id));
            }

            await new SynchronizationContextRemover();

            return(await UpgradeAsync(appMetadata.Id, scope));
        }
Example #6
0
        private static async Task <AppMetadata> GetAppMetaData(AppCatalogScope scope, ClientContext context, string id)
        {
            AppMetadata returnValue = null;
            int         retryCount  = 0;
            int         waitTime    = 10; // seconds

#pragma warning disable CA2000            // Dispose objects before losing scope
            var httpClient = PnPHttpClient.Instance.GetHttpClient(context);
#pragma warning restore CA2000            // Dispose objects before losing scope

            var metadataRequestUrl = $"{context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps/GetById('{id}')";

            using (var metadataRequest = new HttpRequestMessage(HttpMethod.Get, metadataRequestUrl))
            {
                metadataRequest.Headers.Add("accept", "application/json;odata=nometadata");

                await PnPHttpClient.AuthenticateRequestAsync(metadataRequest, context).ConfigureAwait(false);

                while (returnValue == null && retryCount < 5)
                {
                    // Perform actual post operation
                    HttpResponseMessage metadataResponse = await httpClient.SendAsync(metadataRequest, new System.Threading.CancellationToken());

                    if (metadataResponse.IsSuccessStatusCode)
                    {
                        // If value empty, URL is taken
                        var metadataResponseString = await metadataResponse.Content.ReadAsStringAsync();

                        if (metadataResponseString != null)
                        {
                            returnValue = JsonSerializer.Deserialize <AppMetadata>(metadataResponseString);
                        }
                    }
                    else if (metadataResponse.StatusCode != HttpStatusCode.NotFound)
                    {
                        // Something went wrong...
                        throw new Exception(await metadataResponse.Content.ReadAsStringAsync());
                    }
                    if (returnValue == null)
                    {
                        // try again
                        retryCount++;
                        await Task.Delay(waitTime * 1000); // wait 10 seconds
                    }
                }
                return(returnValue);
            }
        }
Example #7
0
 /// <summary>
 /// Returns an available app
 /// </summary>
 /// <param name="id">The unique id of the app. Notice that this is not the product id as listed in the app catalog.</param>
 /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
 /// <returns></returns>
 public AppMetadata GetAvailable(Guid id, AppCatalogScope scope = AppCatalogScope.Tenant)
 {
     return(Task.Run(() => BaseGetAvailableAsync(scope, id)).GetAwaiter().GetResult());
 }
Example #8
0
 /// <summary>
 /// Returns all available apps.
 /// </summary>
 /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
 /// <returns></returns>
 public List <AppMetadata> GetAvailable(AppCatalogScope scope = AppCatalogScope.Tenant)
 {
     return(Task.Run(() => BaseGetAvailableAsync(scope, Guid.Empty)).GetAwaiter().GetResult());
 }
Example #9
0
        private async Task <bool> BaseRequest(Guid id, AppManagerAction action, bool switchToAppCatalogContext, Dictionary <string, object> postObject, AppCatalogScope scope)
        {
            var context = _context;

            if (switchToAppCatalogContext == true && scope == AppCatalogScope.Tenant)
            {
                // switch context to appcatalog
                var appcatalogUri = _context.Web.GetAppCatalog();
                context = context.Clone(appcatalogUri);
            }
            var returnValue = false;
            var accessToken = context.GetAccessToken();

            using (var handler = new HttpClientHandler())
            {
                context.Web.EnsureProperty(w => w.Url);

                // we're not in app-only or user + app context, so let's fall back to cookie based auth
                if (String.IsNullOrEmpty(accessToken))
                {
                    handler.SetAuthenticationCookies(context);
                }

                using (var httpClient = new PnPHttpProvider(handler))
                {
                    var    method     = action.ToString();
                    string requestUrl = $"{context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps/GetByID('{id}')/{method}";

                    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUrl);
                    request.Headers.Add("accept", "application/json;odata=nometadata");
                    if (!string.IsNullOrEmpty(accessToken))
                    {
                        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
                    }
                    request.Headers.Add("X-RequestDigest", await context.GetRequestDigest());

                    if (postObject != null)
                    {
                        var jsonBody    = JsonConvert.SerializeObject(postObject);
                        var requestBody = new StringContent(jsonBody);
                        MediaTypeHeaderValue sharePointJsonMediaType;
                        MediaTypeHeaderValue.TryParse("application/json;odata=nometadata;charset=utf-8", out sharePointJsonMediaType);
                        requestBody.Headers.ContentType = sharePointJsonMediaType;
                        request.Content = requestBody;
                    }

                    // Perform actual post operation
                    HttpResponseMessage response = await httpClient.SendAsync(request, new System.Threading.CancellationToken());

                    if (response.IsSuccessStatusCode)
                    {
                        // If value empty, URL is taken
                        var responseString = await response.Content.ReadAsStringAsync();

                        if (responseString != null)
                        {
                            try
                            {
                                var responseJson = JObject.Parse(responseString);
                                returnValue = true;
                            }
                            catch { }
                        }
                    }
                    else
                    {
                        // Something went wrong...
                        throw new Exception(await response.Content.ReadAsStringAsync());
                    }
                }
            }
            return(await Task.Run(() => returnValue));
        }
Example #10
0
        /// <summary>
        /// Returns an available app
        /// </summary>
        /// <param name="id">The unique id of the app. Notice that this is not the product id as listed in the app catalog.</param>
        /// <param name="title">The title of the app.</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <returns></returns>
        private async Task <dynamic> BaseGetAvailableAsync(AppCatalogScope scope, Guid id = default(Guid), string title = "")
        {
            dynamic addins = null;

            var accessToken = _context.GetAccessToken();

            using (var handler = new HttpClientHandler())
            {
                _context.Web.EnsureProperty(w => w.Url);

                // we're not in app-only or user + app context, so let's fall back to cookie based auth
                if (String.IsNullOrEmpty(accessToken))
                {
                    handler.SetAuthenticationCookies(_context);
                }

                using (var httpClient = new PnPHttpProvider(handler))
                {
                    string requestUrl = $"{_context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps";
                    if (Guid.Empty != id)
                    {
                        requestUrl = $"{_context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps/GetById('{id}')";
                    }
                    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUrl);
                    request.Headers.Add("accept", "application/json;odata=verbose");
                    if (!string.IsNullOrEmpty(accessToken))
                    {
                        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
                    }
                    else
                    {
                        if (_context.Credentials is NetworkCredential networkCredential)
                        {
                            handler.Credentials = networkCredential;
                        }
                    }
                    request.Headers.Add("X-RequestDigest", await _context.GetRequestDigest());

                    // Perform actual post operation
                    HttpResponseMessage response = await httpClient.SendAsync(request, new System.Threading.CancellationToken());

                    if (response.IsSuccessStatusCode)
                    {
                        // If value empty, URL is taken
                        var responseString = await response.Content.ReadAsStringAsync();

                        if (responseString != null)
                        {
                            try
                            {
                                if (Guid.Empty == id && string.IsNullOrEmpty(title))
                                {
                                    var responseJson   = JObject.Parse(responseString);
                                    var returnedAddins = responseJson["d"]["results"] as JArray;

                                    addins = JsonConvert.DeserializeObject <List <AppMetadata> >(returnedAddins.ToString());
                                }
                                else if (!String.IsNullOrEmpty(title))
                                {
                                    var responseJson   = JObject.Parse(responseString);
                                    var returnedAddins = responseJson["d"]["results"] as JArray;

                                    var listAddins = JsonConvert.DeserializeObject <List <AppMetadata> >(returnedAddins.ToString());
                                    addins = listAddins.Where(a => a.Title == title).FirstOrDefault();
                                }
                                else
                                {
                                    var responseJson   = JObject.Parse(responseString);
                                    var returnedAddins = responseJson["d"];
                                    addins = JsonConvert.DeserializeObject <AppMetadata>(returnedAddins.ToString());
                                }
                            }
                            catch { }
                        }
                    }
                    else
                    {
                        // Something went wrong...
                        throw new Exception(await response.Content.ReadAsStringAsync());
                    }
                }
            }
            return(await Task.Run(() => addins));
        }
Example #11
0
        /// <summary>
        /// Uploads a file to the Tenant App Catalog
        /// </summary>
        /// <param name="file">A byte array containing the file</param>
        /// <param name="filename">The filename (e.g. myapp.sppkg) of the file to upload</param>
        /// <param name="overwrite">If true will overwrite an existing entry</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <param name="timeoutSeconds">If specified will set the timeout on the request. Defaults to 200 seconds.</param>
        /// <returns></returns>
        public async Task <AppMetadata> AddAsync(byte[] file, string filename, bool overwrite = false, AppCatalogScope scope = AppCatalogScope.Tenant, int timeoutSeconds = 200)
        {
            if (file == null && file.Length == 0)
            {
                throw new ArgumentException(nameof(file));
            }
            if (string.IsNullOrEmpty(filename))
            {
                throw new ArgumentException(nameof(filename));
            }

            await new SynchronizationContextRemover();

            return(await BaseAddRequest(file, filename, overwrite, timeoutSeconds, scope));
        }
Example #12
0
 /// <summary>
 /// Uploads an app file to the Tenant App Catalog
 /// </summary>
 /// <param name="path"></param>
 /// <param name="overwrite">If true will overwrite an existing entry</param>
 /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
 /// <param name="timeoutSeconds">If specified will set the timeout on the request. Defaults to 200 seconds.</param>
 /// <returns></returns>
 public AppMetadata Add(string path, bool overwrite = false, AppCatalogScope scope = AppCatalogScope.Tenant, int timeoutSeconds = 200)
 {
     return(Task.Run(() => AddAsync(path, overwrite, scope, timeoutSeconds)).GetAwaiter().GetResult());
 }
Example #13
0
        /// <summary>
        /// Returns an avialable app
        /// </summary>
        /// <param name="title">The title of the app.</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <returns></returns>
        public async Task <AppMetadata> GetAvailableAsync(string title, AppCatalogScope scope = AppCatalogScope.Tenant)
        {
            await new SynchronizationContextRemover();

            return(await BaseGetAvailableAsync(scope, Guid.Empty, title));
        }
Example #14
0
 /// <summary>
 /// Deploys/trusts an app in the app catalog
 /// </summary>
 /// <param name="id">The unique id of the app. Notice that this is not the product id as listed in the app catalog.</param>
 /// <param name="skipFeatureDeployment">If set to true will skip the feature deployed for tenant scoped apps.</param>
 /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
 /// <returns></returns>
 public bool Deploy(Guid id, bool skipFeatureDeployment = true, AppCatalogScope scope = AppCatalogScope.Tenant)
 {
     return(Task.Run(() => DeployAsync(id, skipFeatureDeployment, scope)).GetAwaiter().GetResult());
 }
Example #15
0
 /// <summary>
 /// Uninstalls an app from a site.
 /// </summary>
 /// <param name="id">The unique id of the app. Notice that this is not the product id as listed in the app catalog.</param>
 /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
 /// <returns></returns>
 public bool Uninstall(Guid id, AppCatalogScope scope = AppCatalogScope.Tenant)
 {
     return(Task.Run(() => UninstallAsync(id, scope)).GetAwaiter().GetResult());
 }
Example #16
0
        /// <summary>
        /// Uploads an app file to the Tenant App Catalog
        /// </summary>
        /// <param name="path"></param>
        /// <param name="overwrite">If true will overwrite an existing entry</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <param name="timeoutSeconds">If specified will set the timeout on the request. Defaults to 200 seconds.</param>
        /// <returns></returns>
        public async Task <AppMetadata> AddAsync(string path, bool overwrite = false, AppCatalogScope scope = AppCatalogScope.Tenant, int timeoutSeconds = 200)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentException(nameof(path));
            }

            if (!System.IO.File.Exists(path))
            {
                throw new IOException("File does not exist");
            }

            var bytes    = System.IO.File.ReadAllBytes(path);
            var fileInfo = new FileInfo(path);

            await new SynchronizationContextRemover();

            return(await BaseAddRequest(bytes, fileInfo.Name, overwrite, timeoutSeconds, scope));
        }
Example #17
0
#pragma warning disable CA2000
        private async Task <AppMetadata> BaseAddRequest(byte[] file, string filename, bool overwrite, int timeoutSeconds, AppCatalogScope scope)
        {
            AppMetadata returnValue = null;
            var         isCloned    = false;
            var         context     = _context;

            if (scope == AppCatalogScope.Tenant)
            {
                // switch context to appcatalog
                var appcatalogUri = _context.Web.GetAppCatalog();
                context  = context.Clone(appcatalogUri);
                isCloned = true;
            }

            var accessToken = context.GetAccessToken();

            using (var handler = new HttpClientHandler())
            {
                context.Web.EnsureProperty(w => w.Url);

                if (string.IsNullOrEmpty(accessToken))
                {
                    context.SetAuthenticationCookiesForHandler(handler);
                }

                using (var httpClient = new PnPHttpProvider(handler))
                {
                    string requestUrl = $"{context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/Add(overwrite={(overwrite.ToString().ToLower())}, url='{filename}')";

                    var requestDigest = string.Empty;
                    if (!string.IsNullOrEmpty(accessToken))
                    {
                        requestDigest = await context.GetRequestDigestAsync().ConfigureAwait(false);
                    }
                    else
                    {
                        requestDigest = await context.GetRequestDigestAsync(handler.CookieContainer).ConfigureAwait(false);
                    }
                    using (var request = new HttpRequestMessage(HttpMethod.Post, requestUrl))
                    {
                        request.Headers.Add("accept", "application/json;odata=nometadata");
                        if (!string.IsNullOrEmpty(accessToken))
                        {
                            request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
                        }
                        else
                        {
                            if (context.Credentials is NetworkCredential networkCredential)
                            {
                                handler.Credentials = networkCredential;
                            }
                        }
                        if (!string.IsNullOrEmpty(requestDigest))
                        {
                            request.Headers.Add("X-RequestDigest", requestDigest);
                        }
                        request.Headers.Add("binaryStringRequestBody", "true");
                        request.Content    = new ByteArrayContent(file);
                        httpClient.Timeout = new TimeSpan(0, 0, timeoutSeconds);
                        // Perform actual post operation
                        HttpResponseMessage response = await httpClient.SendAsync(request, new System.Threading.CancellationToken());

                        if (response.IsSuccessStatusCode)
                        {
                            // If value empty, URL is taken
                            var responseString = await response.Content.ReadAsStringAsync();

                            if (responseString != null)
                            {
                                using (var jsonDocument = JsonDocument.Parse(responseString))
                                {
                                    if (jsonDocument.RootElement.TryGetProperty("UniqueId", out JsonElement uniqueIdElement))
                                    {
                                        var id = uniqueIdElement.GetString();
                                        returnValue = await GetAppMetaData(scope, context, accessToken, httpClient, requestDigest, id);
                                    }
                                }
                            }
                        }
                        else
                        {
                            // Something went wrong...
                            throw new Exception(await response.Content.ReadAsStringAsync());
                        }
                    }
                }
            }
            if (isCloned)
            {
                context.Dispose();
            }
            return(await Task.Run(() => returnValue));
        }
Example #18
0
#pragma warning disable CA2000
        private async Task <bool> BaseRequest(Guid id, AppManagerAction action, bool switchToAppCatalogContext, Dictionary <string, object> postObject, AppCatalogScope scope, int timeoutSeconds = 200)
        {
            var isCloned = false;
            var context  = _context;

            if (switchToAppCatalogContext == true && scope == AppCatalogScope.Tenant)
            {
                // switch context to appcatalog
                var appcatalogUri = _context.Web.GetAppCatalog();
                context  = context.Clone(appcatalogUri);
                isCloned = true;
            }
            var returnValue = false;
            var accessToken = context.GetAccessToken();

            using (var handler = new HttpClientHandler())
            {
                context.Web.EnsureProperty(w => w.Url);

                if (string.IsNullOrEmpty(accessToken))
                {
                    context.SetAuthenticationCookiesForHandler(handler);
                }

                using (var httpClient = new PnPHttpProvider(handler))
                {
                    httpClient.Timeout = new TimeSpan(0, 0, timeoutSeconds);

                    var method     = action.ToString();
                    var requestUrl = $"{context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps/GetByID('{id}')/{method}";

                    using (var request = new HttpRequestMessage(HttpMethod.Post, requestUrl))
                    {
                        request.Headers.Add("accept", "application/json;odata=nometadata");
                        if (!string.IsNullOrEmpty(accessToken))
                        {
                            request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
                            request.Headers.Add("X-RequestDigest", await context.GetRequestDigestAsync().ConfigureAwait(false));
                        }
                        else
                        {
                            if (context.Credentials is NetworkCredential networkCredential)
                            {
                                handler.Credentials = networkCredential;
                            }
                            request.Headers.Add("X-RequestDigest", await context.GetRequestDigestAsync(handler.CookieContainer).ConfigureAwait(false));
                        }

                        if (postObject != null)
                        {
                            var jsonBody    = JsonSerializer.Serialize(postObject);
                            var requestBody = new StringContent(jsonBody);
                            if (MediaTypeHeaderValue.TryParse("application/json;odata=nometadata;charset=utf-8", out MediaTypeHeaderValue sharePointJsonMediaType))
                            {
                                requestBody.Headers.ContentType = sharePointJsonMediaType;
                            }
                            request.Content = requestBody;
                        }

                        // Perform actual post operation
                        HttpResponseMessage response = await httpClient.SendAsync(request, new System.Threading.CancellationToken());

                        if (response.IsSuccessStatusCode)
                        {
                            // If value empty, URL is taken
                            var responseString = await response.Content.ReadAsStringAsync();

                            if (responseString != null)
                            {
                                try
                                {
                                    returnValue = true;
                                }
                                catch { }
                            }
                        }
                        else
                        {
                            // Something went wrong...
                            throw new Exception(await response.Content.ReadAsStringAsync());
                        }
                    }
                }
            }
            if (isCloned)
            {
                context.Dispose();
            }
            return(await Task.Run(() => returnValue));
        }
Example #19
0
        /// <summary>
        /// Returns an available app
        /// </summary>
        /// <param name="id">The unique id of the app. Notice that this is not the product id as listed in the app catalog.</param>
        /// <param name="title">The title of the app.</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <returns></returns>
        private async Task <dynamic> BaseGetAvailableAsync(AppCatalogScope scope, Guid id = default(Guid), string title = "")
        {
            dynamic addins = null;

            var accessToken = _context.GetAccessToken();

            using (var handler = new HttpClientHandler())
            {
                if (string.IsNullOrEmpty(accessToken))
                {
                    _context.SetAuthenticationCookiesForHandler(handler);
                }

                _context.Web.EnsureProperty(w => w.Url);


                using (var httpClient = new PnPHttpProvider(handler))
                {
                    string requestUrl = $"{_context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps";
                    if (Guid.Empty != id)
                    {
                        requestUrl = $"{_context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps/GetById('{id}')";
                    }
                    using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUrl))
                    {
                        request.Headers.Add("accept", "application/json;odata=nometadata");
                        if (!string.IsNullOrEmpty(accessToken))
                        {
                            request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
                            request.Headers.Add("X-RequestDigest", await _context.GetRequestDigestAsync().ConfigureAwait(false));
                        }
                        else
                        {
                            if (_context.Credentials is NetworkCredential networkCredential)
                            {
                                handler.Credentials = networkCredential;
                            }
                            request.Headers.Add("X-RequestDigest", await _context.GetRequestDigestAsync(handler.CookieContainer).ConfigureAwait(false));
                        }

                        // Perform actual post operation
                        HttpResponseMessage response = await httpClient.SendAsync(request, new System.Threading.CancellationToken());

                        if (response.IsSuccessStatusCode)
                        {
                            // If value empty, URL is taken
                            var responseString = await response.Content.ReadAsStringAsync();

                            if (responseString != null)
                            {
                                try
                                {
                                    if (Guid.Empty == id && string.IsNullOrEmpty(title))
                                    {
                                        var resultCollection = JsonSerializer.Deserialize <ResultCollection <AppMetadata> >(responseString, new JsonSerializerOptions()
                                        {
                                            IgnoreNullValues = true
                                        });
                                        if (resultCollection.Items != null && resultCollection.Items.Any())
                                        {
                                            addins = resultCollection.Items;
                                        }
                                    }
                                    else if (!String.IsNullOrEmpty(title))
                                    {
                                        var resultCollection = JsonSerializer.Deserialize <ResultCollection <AppMetadata> >(responseString, new JsonSerializerOptions()
                                        {
                                            IgnoreNullValues = true
                                        });
                                        if (resultCollection.Items != null && resultCollection.Items.Any())
                                        {
                                            addins = resultCollection.Items.FirstOrDefault(a => a.Title.Equals(title));
                                        }
                                    }
                                    else
                                    {
                                        addins = JsonSerializer.Deserialize <AppMetadata>(responseString);
                                    }
                                }
                                catch { }
                            }
                        }
                        else
                        {
                            // Something went wrong...
                            throw new Exception(await response.Content.ReadAsStringAsync());
                        }
                    }
                }
            }
            return(await Task.Run(() => addins));
        }
Example #20
0
        /// <summary>
        /// Returns an available app
        /// </summary>
        /// <param name="id">The id of the app</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <returns></returns>
        public async Task <AppMetadata> GetAvailableAsync(Guid id, AppCatalogScope scope = AppCatalogScope.Tenant)
        {
            await new SynchronizationContextRemover();

            return(await BaseGetAvailableAsync(scope, id));
        }
Example #21
0
 /// <summary>
 /// Returns an available app
 /// </summary>
 /// <param name="title">The title of the app.</param>
 /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
 /// <returns></returns>
 public AppMetadata GetAvailable(string title, AppCatalogScope scope = AppCatalogScope.Tenant)
 {
     return(Task.Run(() => BaseGetAvailableAsync(scope, Guid.Empty, title)).GetAwaiter().GetResult());
 }
Example #22
0
        /// <summary>
        /// Deploys/trusts an app in the app catalog
        /// </summary>
        /// <param name="id">The unique id of the app. Notice that this is not the product id as listed in the app catalog.</param>
        /// <param name="skipFeatureDeployment">If set to true will skip the feature deployed for tenant scoped apps.</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <returns></returns>
        public async Task <bool> DeployAsync(Guid id, bool skipFeatureDeployment = true, AppCatalogScope scope = AppCatalogScope.Tenant)
        {
            if (id == Guid.Empty)
            {
                throw new ArgumentException(nameof(id));
            }
            var postObj = new Dictionary <string, object>
            {
                { "skipFeatureDeployment", skipFeatureDeployment }
            };

            await new SynchronizationContextRemover();

            return(await BaseRequest(id, AppManagerAction.Deploy, true, postObj, scope));
        }
Example #23
0
        /// <summary>
        /// Returns an available app
        /// </summary>
        /// <param name="id">The unique id of the app. Notice that this is not the product id as listed in the app catalog.</param>
        /// <param name="title">The title of the app.</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <returns></returns>
        private async Task <dynamic> BaseGetAvailableAsync(AppCatalogScope scope, Guid id = default(Guid), string title = "")
        {
            dynamic addins = null;

            _context.Web.EnsureProperty(w => w.Url);

#pragma warning disable CA2000 // Dispose objects before losing scope
            var httpClient = PnPHttpClient.Instance.GetHttpClient(_context);
#pragma warning restore CA2000 // Dispose objects before losing scope

            string requestUrl = $"{_context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps";

            if (Guid.Empty != id)
            {
                requestUrl = $"{_context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps/GetById('{id}')";
            }

            using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUrl))
            {
                request.Headers.Add("accept", "application/json;odata=nometadata");

                PnPHttpClient.AuthenticateRequestAsync(request, _context).GetAwaiter().GetResult();

                // Perform actual post operation
                HttpResponseMessage response = await httpClient.SendAsync(request, new CancellationToken());

                if (response.IsSuccessStatusCode)
                {
                    // If value empty, URL is taken
                    var responseString = await response.Content.ReadAsStringAsync();

                    if (responseString != null)
                    {
                        try
                        {
                            if (Guid.Empty == id && string.IsNullOrEmpty(title))
                            {
                                var resultCollection = JsonSerializer.Deserialize <ResultCollection <AppMetadata> >(responseString, new JsonSerializerOptions()
                                {
                                    IgnoreNullValues = true
                                });
                                if (resultCollection.Items != null && resultCollection.Items.Any())
                                {
                                    addins = resultCollection.Items;
                                }
                            }
                            else if (!String.IsNullOrEmpty(title))
                            {
                                var resultCollection = JsonSerializer.Deserialize <ResultCollection <AppMetadata> >(responseString, new JsonSerializerOptions()
                                {
                                    IgnoreNullValues = true
                                });
                                if (resultCollection.Items != null && resultCollection.Items.Any())
                                {
                                    addins = resultCollection.Items.FirstOrDefault(a => a.Title.Equals(title));
                                }
                            }
                            else
                            {
                                addins = JsonSerializer.Deserialize <AppMetadata>(responseString);
                            }
                        }
                        catch { }
                    }
                }
                else
                {
                    // Something went wrong...
                    throw new Exception(await response.Content.ReadAsStringAsync());
                }
            }
            return(await Task.Run(() => addins));
        }
Example #24
0
 /// <summary>
 /// Uploads a file to the Tenant App Catalog
 /// </summary>
 /// <param name="file">A byte array containing the file</param>
 /// <param name="filename">The filename (e.g. myapp.sppkg) of the file to upload</param>
 /// <param name="overwrite">If true will overwrite an existing entry</param>
 /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
 /// <returns></returns>
 public AppMetadata Add(byte[] file, string filename, bool overwrite = false, AppCatalogScope scope = AppCatalogScope.Tenant)
 {
     return(Task.Run(() => AddAsync(file, filename, overwrite, scope)).GetAwaiter().GetResult());
 }
Example #25
0
        private async Task <bool> BaseRequest(Guid id, AppManagerAction action, bool switchToAppCatalogContext, Dictionary <string, object> postObject, AppCatalogScope scope, int timeoutSeconds = 200)
        {
            var isCloned = false;
            var context  = _context;

            if (switchToAppCatalogContext == true && scope == AppCatalogScope.Tenant)
            {
                // switch context to appcatalog
                var appcatalogUri = _context.Web.GetAppCatalog();
#pragma warning disable CA2000 // Dispose objects before losing scope
                context = context.Clone(appcatalogUri);
#pragma warning restore CA2000 // Dispose objects before losing scope
                isCloned = true;
            }
            var returnValue = false;

            context.Web.EnsureProperty(w => w.Url);
#pragma warning disable CA2000 // Dispose objects before losing scope
            var httpClient = PnPHttpClient.Instance.GetHttpClient(context);
#pragma warning restore CA2000 // Dispose objects before losing scope

            httpClient.Timeout = new TimeSpan(0, 0, timeoutSeconds);

            var method     = action.ToString();
            var requestUrl = $"{context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps/GetByID('{id}')/{method}";

            using (var request = new HttpRequestMessage(HttpMethod.Post, requestUrl))
            {
                request.Headers.Add("accept", "application/json;odata=nometadata");
                await PnPHttpClient.AuthenticateRequestAsync(request, context).ConfigureAwait(false);

                if (postObject != null)
                {
                    var jsonBody    = JsonSerializer.Serialize(postObject);
                    var requestBody = new StringContent(jsonBody);
                    if (MediaTypeHeaderValue.TryParse("application/json;odata=nometadata;charset=utf-8", out MediaTypeHeaderValue sharePointJsonMediaType))
                    {
                        requestBody.Headers.ContentType = sharePointJsonMediaType;
                    }
                    request.Content = requestBody;
                }


                // Perform actual post operation
                HttpResponseMessage response = await httpClient.SendAsync(request, new CancellationToken());

                if (response.IsSuccessStatusCode)
                {
                    // If value empty, URL is taken
                    var responseString = await response.Content.ReadAsStringAsync();

                    if (responseString != null)
                    {
                        try
                        {
                            returnValue = true;
                        }
                        catch { }
                    }
                }
                else
                {
                    // Something went wrong...
                    throw new Exception(await response.Content.ReadAsStringAsync());
                }
            }
            if (isCloned)
            {
                context.Dispose();
            }
            return(await Task.Run(() => returnValue));
        }
Example #26
0
 /// <summary>
 /// Removes an app from the app catalog
 /// </summary>
 /// <param name="id">The unique id of the app. Notice that this is not the product id as listed in the app catalog.</param>
 /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
 /// <returns></returns>
 public bool Remove(Guid id, AppCatalogScope scope = AppCatalogScope.Tenant)
 {
     return(Task.Run(() => RemoveAsync(id, scope)).GetAwaiter().GetResult());
 }
Example #27
0
        private async Task <AppMetadata> BaseAddRequest(byte[] file, string filename, bool overwrite, int timeoutSeconds, AppCatalogScope scope)
        {
            AppMetadata returnValue = null;
            var         isCloned    = false;
            var         context     = _context;

            if (scope == AppCatalogScope.Tenant)
            {
                // switch context to appcatalog
                var appcatalogUri = _context.Web.GetAppCatalog();
#pragma warning disable CA2000 // Dispose objects before losing scope
                context = context.Clone(appcatalogUri);
#pragma warning restore CA2000 // Dispose objects before losing scope
                isCloned = true;
            }

            context.Web.EnsureProperty(w => w.Url);

#pragma warning disable CA2000 // Dispose objects before losing scope
            var httpClient = PnPHttpClient.Instance.GetHttpClient(context);
#pragma warning restore CA2000 // Dispose objects before losing scope

            string requestUrl = $"{context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/Add(overwrite={(overwrite.ToString().ToLower())}, url='{filename}')";

            var requestDigest = string.Empty;

            using (var request = new HttpRequestMessage(HttpMethod.Post, requestUrl))
            {
                request.Headers.Add("accept", "application/json;odata=nometadata");

                await PnPHttpClient.AuthenticateRequestAsync(request, context).ConfigureAwait(false);

                request.Headers.Add("binaryStringRequestBody", "true");
                request.Content    = new ByteArrayContent(file);
                httpClient.Timeout = new TimeSpan(0, 0, timeoutSeconds);

                // Perform actual post operation
                HttpResponseMessage response = await httpClient.SendAsync(request, new CancellationToken());

                if (response.IsSuccessStatusCode)
                {
                    // If value empty, URL is taken
                    var responseString = await response.Content.ReadAsStringAsync();

                    if (responseString != null)
                    {
                        using (var jsonDocument = JsonDocument.Parse(responseString))
                        {
                            if (jsonDocument.RootElement.TryGetProperty("UniqueId", out JsonElement uniqueIdElement))
                            {
                                var id = uniqueIdElement.GetString();
                                returnValue = await GetAppMetaData(scope, context, id);
                            }
                        }
                    }
                }
                else
                {
                    // Something went wrong...
                    throw new Exception(await response.Content.ReadAsStringAsync());
                }
            }
            if (isCloned)
            {
                context.Dispose();
            }
            return(await Task.Run(() => returnValue));
        }
Example #28
0
        private async Task <AppMetadata> BaseAddRequest(byte[] file, string filename, bool overwrite, int timeoutSeconds, AppCatalogScope scope)
        {
            AppMetadata returnValue = null;

            var context = _context;

            if (scope == AppCatalogScope.Tenant)
            {
                // switch context to appcatalog
                var appcatalogUri = _context.Web.GetAppCatalog();
                context = context.Clone(appcatalogUri);
            }

            var accessToken = context.GetAccessToken();

            using (var handler = new HttpClientHandler())
            {
                context.Web.EnsureProperty(w => w.Url);

                // we're not in app-only or user + app context, so let's fall back to cookie based auth
                if (String.IsNullOrEmpty(accessToken))
                {
                    handler.SetAuthenticationCookies(context);
                }

                using (var httpClient = new PnPHttpProvider(handler))
                {
                    string requestUrl = $"{context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/Add(overwrite={(overwrite.ToString().ToLower())}, url='{filename}')";

                    var requestDigest = await context.GetRequestDigest();

                    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUrl);
                    request.Headers.Add("accept", "application/json;odata=verbose");
                    if (!string.IsNullOrEmpty(accessToken))
                    {
                        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
                    }
                    else
                    {
                        if (context.Credentials is NetworkCredential networkCredential)
                        {
                            handler.Credentials = networkCredential;
                        }
                    }
                    request.Headers.Add("X-RequestDigest", requestDigest);
                    request.Headers.Add("binaryStringRequestBody", "true");
                    request.Content    = new ByteArrayContent(file);
                    httpClient.Timeout = new TimeSpan(0, 0, timeoutSeconds);
                    // Perform actual post operation
                    HttpResponseMessage response = await httpClient.SendAsync(request, new System.Threading.CancellationToken());

                    if (response.IsSuccessStatusCode)
                    {
                        // If value empty, URL is taken
                        var responseString = await response.Content.ReadAsStringAsync();

                        if (responseString != null)
                        {
                            var responseJson = JObject.Parse(responseString);
                            var id           = responseJson["d"]["UniqueId"].ToString();

                            var metadataRequestUrl = $"{context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps/GetById('{id}')";

                            HttpRequestMessage metadataRequest = new HttpRequestMessage(HttpMethod.Post, metadataRequestUrl);
                            metadataRequest.Headers.Add("accept", "application/json;odata=verbose");
                            if (!string.IsNullOrEmpty(accessToken))
                            {
                                metadataRequest.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
                            }
                            metadataRequest.Headers.Add("X-RequestDigest", requestDigest);

                            // Perform actual post operation
                            HttpResponseMessage metadataResponse = await httpClient.SendAsync(metadataRequest, new System.Threading.CancellationToken());

                            if (metadataResponse.IsSuccessStatusCode)
                            {
                                // If value empty, URL is taken
                                var metadataResponseString = await metadataResponse.Content.ReadAsStringAsync();

                                if (metadataResponseString != null)
                                {
                                    var metadataResponseJson = JObject.Parse(metadataResponseString);
                                    var returnedAddins       = metadataResponseJson["d"];
                                    returnValue = JsonConvert.DeserializeObject <AppMetadata>(returnedAddins.ToString());
                                }
                            }
                            else
                            {
                                // Something went wrong...
                                throw new Exception(await metadataResponse.Content.ReadAsStringAsync());
                            }
                        }
                    }
                    else
                    {
                        // Something went wrong...
                        throw new Exception(await response.Content.ReadAsStringAsync());
                    }
                }
            }
            return(await Task.Run(() => returnValue));
        }
Example #29
0
 /// <summary>
 /// Removes an app from the app catalog
 /// </summary>
 /// <param name="appMetadata">The app metadata object of the app to remove.</param>
 /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
 /// <returns></returns>
 public bool Remove(AppMetadata appMetadata, AppCatalogScope scope = AppCatalogScope.Tenant)
 {
     return(Task.Run(() => RemoveAsync(appMetadata, scope)).GetAwaiter().GetResult());
 }
Example #30
0
 /// <summary>
 /// Upgrades an app in a site
 /// </summary>
 /// <param name="id">The unique id of the app. Notice that this is not the product id as listed in the app catalog.</param>
 /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
 /// <returns></returns>
 public bool Upgrade(Guid id, AppCatalogScope scope = AppCatalogScope.Tenant)
 {
     return(Task.Run(() => UpgradeAsync(id)).GetAwaiter().GetResult());
 }