コード例 #1
0
        public static async Task <HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestMessage req, TraceWriter log)
        {
            log.Info("C# HTTP trigger function BetterCopyFunction processed a request.");

            string errorMsg = "";

            try
            {
                dynamic data = await req.Content.ReadAsAsync <object>();

                string targetUrl     = data?.targetUrl;
                string sourceUrl     = data?.sourceUrl;
                Uri    targetSiteUri = new Uri(targetUrl);
                Uri    sourceSiteUri = new Uri(sourceUrl);
                string pageLayout    = data?.pageLayout;

                string fileName = ""; // we get this from the source item

                int sourceId;

                try
                {
                    string strSourceId = data?.sourceId;
                    sourceId = int.Parse(strSourceId);
                }
                catch (Exception)
                {
                    log.Error("Setting up variables failed.");
                    errorMsg += "Setting up variables failed.";
                    throw;
                }

                log.Info("Got the variables! Now connecting to SharePoint...");

                // Get the realm for the URL
                var realm = TokenHelper.GetRealmFromTargetUrl(targetSiteUri);
                // parse tenant admin url from the sourceUrl (there's probably a cuter way to do this but this is simple :])
                string tenantAdminUrl = sourceUrl.Substring(0, sourceUrl.IndexOf(".com") + 4).TrimEnd(new[] { '/' }).Replace(".sharepoint", "-admin.sharepoint");
                // parse tenant url from the admin url
                var tenantUrl        = tenantAdminUrl.Substring(0, tenantAdminUrl.IndexOf(".com") + 4).Replace("-admin", "");
                AzureEnvironment env = TokenHelper.getAzureEnvironment(tenantAdminUrl);

                using (var ctx_target = new OfficeDevPnP.Core.AuthenticationManager().GetAppOnlyAuthenticatedContext(targetSiteUri.ToString(), clientId, clientSecret, env))
                {
                    log.Info("Target site context built successfully!");

                    using (var ctx_source = new OfficeDevPnP.Core.AuthenticationManager().GetAppOnlyAuthenticatedContext(sourceSiteUri.ToString(), clientId, clientSecret, env))
                    {
                        log.Info("Source site context built successfully!");

                        var exists = ctx_target.WebExistsFullUrl(targetUrl);

                        string targetWebUrl = targetUrl.Replace(tenantUrl, "");
                        var    targetWeb    = ctx_target.Site.OpenWeb(targetWebUrl);

                        ctx_target.Load(ctx_target.Site);
                        ctx_target.Load(targetWeb);
                        ctx_target.ExecuteQuery();

                        var sourceWeb = ctx_source.Site.OpenWeb(sourceUrl.Replace(tenantUrl, ""));
                        ctx_source.Load(sourceWeb);
                        ctx_source.ExecuteQuery();

                        log.Info("SharePoint connection fine! Connected to: " + targetWeb.Title);

                        pageLayout = ctx_target.Site.Url + pageLayout.Substring(pageLayout.IndexOf("/_catalogs"));

                        var sourceList = sourceWeb.Lists.GetByTitle("Pages");
                        ctx_source.Load(sourceList);
                        ctx_source.ExecuteQuery();

                        var targetList = targetWeb.Lists.GetByTitle("Pages");
                        ctx_target.Load(targetList);
                        ctx_target.ExecuteQuery();

                        log.Info("... and: " + targetList.Title + " " + targetList.ItemCount);

                        string publishingPageContent = "";

                        ListItem sourceItem = null;
                        try
                        {
                            sourceItem = sourceList.GetItemById(sourceId);

                            if (sourceItem == null)
                            {
                                string    qs    = String.Format("<View><Query><Where><Eq><FieldRef Name=\"ID\"></FieldRef><Value Type=\"Number\">{0}</Value></Eq></Where></Query></View>", sourceId);
                                CamlQuery query = new CamlQuery();
                                query.ViewXml = qs;
                                var items = sourceList.GetItems(query);

                                ctx_source.Load(items);
                                ctx_source.ExecuteQuery();

                                sourceItem = items.First();
                            }
                        }
                        catch (Exception ex)
                        {
                            sourceItem = sourceWeb.GetListItem("/Pages/Forms/DispForm.aspx?ID=" + sourceId);
                            errorMsg  += ex.Message + " ";
                        }
                        finally
                        {
                            ctx_source.Load(sourceItem);
                            ctx_source.Load(sourceItem.File);
                            ctx_source.Load(sourceItem, r => r.Client_Title, r => r.Properties);
                            ctx_source.ExecuteQueryRetry();

                            log.Info("Got source item! Title: " + sourceItem.Client_Title);

                            if (sourceItem["PublishingPageContent"] != null)
                            {
                                publishingPageContent = sourceItem["PublishingPageContent"].ToString();
                            }
                        }

                        fileName = sourceItem.File.Name;

                        // at this point, we've fetched all the info we needed. On to getting the target item, and then updating the fields there.
                        ListItem targetItem = null;
                        try
                        {
                            targetItem = targetList.GetItemById(sourceId);

                            if (targetItem == null)
                            {
                                string    qs1    = String.Format("<View><Query><Where><Eq><FieldRef Name=\"ID\"></FieldRef><Value Type=\"Number\">{0}</Value></Eq></Where></Query></View>", sourceId);
                                CamlQuery query1 = new CamlQuery();
                                query1.ViewXml = qs1;
                                var items1 = targetList.GetItems(query1);

                                ctx_target.Load(items1);
                                ctx_target.ExecuteQuery();

                                targetItem = items1.First();
                            }
                        }
                        catch (Exception ex)
                        {
                            log.Warning("Getting source item via conventional ways failed. Trying the unorthodox ones...");

                            targetItem = targetWeb.GetListItem("/Pages/Forms/DispForm.aspx?ID=" + sourceId);

                            var items = targetList.GetItems(CamlQuery.CreateAllItemsQuery());
                            ctx_target.Load(items);
                            ctx_target.ExecuteQueryRetry();

                            for (int i = 0; i < items.Count; i++)
                            {
                                if (items[i].Id == sourceId)
                                {
                                    targetItem = items[i];
                                }
                            }
                        }
                        finally
                        {
                            try
                            {
                                string str = "Published automatically by an Azure Function (BetterCopyFunction).";
                                targetItem.File.CheckIn(str, CheckinType.MajorCheckIn);
                                targetItem.File.Publish(str);

                                ctx_target.Load(targetItem);

                                ctx_target.ExecuteQueryRetry();
                            }
                            catch (Exception ex)
                            {
                                log.Info("Error: " + ex.Message);
                            }

                            ctx_target.Load(targetItem);
                            ctx_target.Load(targetItem, r => r.Client_Title, r => r.Properties);
                            ctx_target.ExecuteQueryRetry();
                        }

                        log.Info("Target item title: " + targetItem.Client_Title);

                        try
                        {
                            targetItem["PublishingPageLayout"]  = pageLayout;
                            targetItem["PublishingPageContent"] = publishingPageContent;
                            targetItem.SystemUpdate();

                            ctx_target.ExecuteQuery();
                        }
                        catch (Exception ex)
                        {
                            log.Warning("There was an error in saving target item values. Values were: " + pageLayout + " " + publishingPageContent);
                            log.Warning("Error was: " + ex.Message);
                        }
                        finally
                        {
                            log.Info("Target item updated!");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                errorMsg += ex.Message;
                errorMsg += "\r\n " + ex.StackTrace;

                throw;
            }

            return(String.IsNullOrEmpty(errorMsg)
                ? req.CreateResponse(HttpStatusCode.OK, "Function run was a success.")
                : req.CreateResponse(HttpStatusCode.InternalServerError, errorMsg));
        }
コード例 #2
0
        public static async Task <object> Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage req, TraceWriter log)
        {
            log.Info($"Webhook was triggered!");

            // Grab the validationToken URL parameter
            string validationToken = req.GetQueryNameValuePairs()
                                     .FirstOrDefault(q => string.Compare(q.Key, "validationtoken", true) == 0)
                                     .Value;

            // If a validation token is present, we need to respond within 5 seconds by
            // returning the given validation token. This only happens when a new
            // web hook is being added
            if (validationToken != null)
            {
                log.Info($"Validation token {validationToken} received");
                var response = req.CreateResponse(HttpStatusCode.OK);
                response.Content = new StringContent(validationToken);
                return(response);
            }

            log.Info($"SharePoint triggered our webhook...great :-)");
            var content = await req.Content.ReadAsStringAsync();

            log.Info($"Received following payload: {content}");

            var notifications = JsonConvert.DeserializeObject <ResponseModel <NotificationModel> >(content).Value;

            log.Info($"Found {notifications.Count} notifications");

            // there should always be just one so let's get the first item
            var notification = notifications.First();

            // Get the realm for the URL
            var tenantAdminUrl   = ConfigurationManager.AppSettings["SiteCollectionRequests_TenantAdminSite"].TrimEnd(new[] { '/' });
            var tenantUrl        = tenantAdminUrl.Substring(0, tenantAdminUrl.IndexOf(".com") + 4).Replace("-admin", "");
            AzureEnvironment env = TokenHelper.getAzureEnvironment(tenantAdminUrl);

            log.Info($"Tenant url {tenantUrl} and notification from {notification.SiteUrl} ");

            string fullUrl = string.Format("{0}{1}", tenantUrl, notification.SiteUrl);

            log.Info($"{fullUrl}");
            Uri targetSiteUri = new Uri(fullUrl);

            log.Info($"Connecting to SharePoint at {targetSiteUri.AbsoluteUri}");

            var realm = TokenHelper.GetRealmFromTargetUrl(targetSiteUri);

            try
            {
                using (var ctx = new OfficeDevPnP.Core.AuthenticationManager().GetAppOnlyAuthenticatedContext(targetSiteUri.ToString(), clientId, clientSecret, env))
                {
                    log.Info("Connected to SharePoint!");

                    var ctxWeb = ctx.Site.OpenWebById(new Guid(notification.WebId));
                    try
                    {
                        ctx.ExecuteQueryRetry();
                    }
                    catch (Exception ex)
                    {
                        log.Error("Error in ctx ExecuteQueryRetry, stage 1: " + ex.Message);
                        throw;
                    }

                    Guid listId = new Guid(notification.Resource);

                    List targetList = ctxWeb.Lists.GetById(listId);
                    ctx.Load(targetList, List => List.ParentWebUrl);
                    ctx.Load(targetList, List => List.Title);
                    ctx.Load(targetList, List => List.DefaultViewUrl);
                    ctx.Load(ctxWeb, Web => Web.Url);
                    ctx.ExecuteQueryRetry();

                    log.Info($"Got list {targetList.Title} at {ctxWeb.Url} !");

                    // now send the query to a custom API as a POST
                    var values = new Dictionary <string, string>();

                    if (notifications.Count > 0)
                    {
                        log.Info($"Processing notifications...");

                        StringContent       stringcontent;
                        HttpResponseMessage apiresponse;

                        if (enrichViaExternalAPI)
                        {
                            for (int i = 0; i < notifications.Count; i++)
                            {
                                var n = notifications[i];
                                //        CloudStorageAccount storageAccount = CloudStorageAccount.Parse("<YOUR STORAGE ACCOUNT>");
                                //        // Get queue... create if does not exist.
                                //        CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
                                //        CloudQueue queue = queueClient.GetQueueReference("sharepointlistwebhookeventazuread");
                                //        queue.CreateIfNotExists();

                                //        // add message to the queue
                                string m = JsonConvert.SerializeObject(n);
                                //        log.Info($"Before adding a message to the queue. Message content: {message}");
                                //        queue.AddMessage(new CloudQueueMessage(message));
                                //        log.Info($"Message added :-)");

                                values.Add("message" + i, m);

                                log.Info($"Notification {i} : {m}");
                            }

                            //stringcontent = new FormUrlEncodedContent(values);

                            apiresponse = await _client.PostAsync(_apiAddress, stringcontent);

                            var responseString = await apiresponse.Content.ReadAsStringAsync();

                            log.Info($"Got response: " + responseString);
                        }

                        // we have the response, now we let another flow know about it - through a call to the API!
                        var    message = JsonConvert.SerializeObject(notification);
                        string link    = tenantUrl + targetList.DefaultViewUrl;
                        var    obj     = new Dictionary <string, string>();
                        obj.Add("message", "New item on a list: " + targetList.Title);
                        obj.Add("link", link);

                        var serializer = new JavaScriptSerializer();
                        var json       = serializer.Serialize(obj);
                        stringcontent = new StringContent(json, Encoding.UTF8, "application/json");

                        //stringcontent = new FormUrlEncodedContent(obj);

                        log.Info($"Now pushing this: " + stringcontent);
                        apiresponse = await _client.PostAsync(_notificationFlowAddress, stringcontent);

                        log.Info($"Pushed to Flow! Got this back: " + apiresponse);

                        // if we get here we assume the request was well received
                        return(new HttpResponseMessage(HttpStatusCode.OK));
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
                throw;
            }

            log.Info($"Got nothing! Logging bad request.");
            return(new HttpResponseMessage(HttpStatusCode.BadRequest));
        }