Why doesn't StartWorkflow() start my workflow in C#? - c#

I am attempting to programatically start a SharePoint 2013 workflow. The workflow takes five parameters, puts them in an email body and e-mails them to me. When I go to the SharePoint website I can start this workflow manually, so I know the workflow is correct. When I try to use the SharePoint API's to start the workflow, I get no errors, I get an empty Guid back, and the workflow does not run.
public Guid Add(Project project)
{
var result = Guid.Empty;
var siteUri = new Uri(ConfigurationManager.AppSettings["SharePoint.Site"]);
var workflowName = ConfigurationManager.AppSettings["SharePoint.WorkflowName"];
using (var clientContext = TokenHelper.GetS2SClientContextWithWindowsIdentity(siteUri, null))
{
var workflowServiceManager = new WorkflowServicesManager(clientContext, clientContext.Web);
var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService();
var subscriptions = workflowSubscriptionService.EnumerateSubscriptions();
clientContext.Load(subscriptions, subs => subs.Where(sub => sub.Name == workflowName));
clientContext.ExecuteQuery();
foreach (var subscription in subscriptions)
{
var instanceService = workflowServiceManager.GetWorkflowInstanceService();
var initiationData = new Dictionary<string, object>
{
{"pProjectName", project.Name},
{"pDivision", _divisionData.GetDivisionName(project.DivisionId ?? Guid.Empty) },
{"pOperatingGroup", "****TODO: Operating Group****"},
{"pClientName", _clientData.GetClientName(project.ClientId ?? Guid.Empty) },
{"pSiteUrl", "****TODO: Site URL****" }
};
var startResult = instanceService.StartWorkflow(subscription, initiationData);
result = startResult.Value;
}
}
return result;
}

string subscriptionID = "WFListSubscriptionID of your wf";//it is a guid
int itemID = "Item.ID, Id of a item that you start wf for";
Guid workflowSubscriptionIdGuid = new Guid(subscriptionID);
var workflowServiceManager = new WorkflowServicesManager(item.Web);
var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService();
var workflowSubscription = workflowSubscriptionService.GetSubscription(workflowSubscriptionIdGuid);
var inputParameters = new Dictionary<string, object>();
workflowServiceManager.GetWorkflowInstanceService().StartWorkflowOnListItem(workflowSubscription, itemID, inputParameters);

Related

Create and Manage Sharepoint DocumentSet with MS Graph

I can't find any way to create a documentset in Sharepoint Library using MS graph. Is there a way to do it? any help is mostly appreciated
AFAIK, there is no straight forward API today that you can leverage to achieve this.
Being said that, you can try this workout and see if this helps -
Get document library's drive id.
GET https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${listId}?$expand=drive
Create folder.
POST https://graph.microsoft.com/v1.0/drives/${library.drive.id}/root/children
Request body
{
"name": "New Folder name",
"folder": {},
"#microsoft.graph.conflictBehavior": "rename"
}
Get SharePoint item id for created folder.
GET https://graph.microsoft.com/v1.0/sites/${siteId}/drives/${library.drive.id}/items/${folder.id}?expand=sharepointids
4.Update the item in the Document Library so that it updates to the desired Document Set.
PATCH https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${listId}/items/${sharepointIds.listItemId}
Request body
{
"contentType": {
"id": "content-type-id-of-the-document-set"
},
"fields": {
//fields that you wish to set
}
}
I was able to complete this in the following way, sorry for not updating eariler:
Vars:
SpURL = "site.sharepoint.com";
SiteURL = "/sites/myTestSite";
LibraryName = "Library";
ContentType = "mycontenttype";
1- Get Site ID By Path:
var scopes = new string[] { ISD.MicrosoftGraph.Constants.ScopeDefault };
var client = GraphServiceClientFactory.GetAuthenticatedGraphClient(() => AcquireAppToken(scopes), "https://graph.microsoft.com/beta");
var site = await client.Sites.GetByPath(siteURL, spURL).Request().GetAsync();
return site.Id;
2- Drive ID by Path:
var scopes = new string[] { ISD.MicrosoftGraph.Constants.ScopeDefault };
var client = GraphServiceClientFactory.GetAuthenticatedGraphClient(() => AcquireAppToken(scopes), "https://graph.microsoft.com/beta");
var request = client.Sites[siteID].Drives.Request();
var result = await request.GetAsync();
//.Filter is not working here for some reasone
var filter = result?.Where(x => x.Name.Contains(LibraryName)).ToList();
if (filter.Count > 0) {
return filter.First().Id;
}
else {
return "";
}
3- Get List ID:
var scopes = new string[] { ISD.MicrosoftGraph.Constants.ScopeDefault };
var client = GraphServiceClientFactory.GetAuthenticatedGraphClient(() => AcquireAppToken(scopes), "https://graph.microsoft.com/beta");
var request = client.Sites[siteID].Lists.Request().Filter($"displayName eq '{ListName}'");
var result = await request.GetAsync();
return result.First().Id;
List ID:
var scopes = new string[] { ISD.MicrosoftGraph.Constants.ScopeDefault };
var client = GraphServiceClientFactory.GetAuthenticatedGraphClient(() => AcquireAppToken(scopes), "https://graph.microsoft.com/beta");
var request = client.Sites[siteID].Lists.Request().Filter($"displayName eq '{ListName}'");
var result = await request.GetAsync();return result.First().Id;
Add new folder:
var scopes = new string[] { ISD.MicrosoftGraph.Constants.ScopeDefault };
var client = GraphServiceClientFactory.GetAuthenticatedGraphClient(() => AcquireAppToken(scopes), "https://graph.microsoft.com/beta");
var folder = new DriveItem
{
Name = foldername,
Folder = new Microsoft.Graph.Folder(),
AdditionalData = new Dictionary<string, object>()
{
{"#microsoft.graph.conflictBehavior", "rename"}
},
};
var folderObj = await client.Drives[driveID].Root.Children.Request().AddAsync(folder);
return folderObj.Id;
//Save folderID from the above return
contentType ID:
var scopes = new string[] { ISD.MicrosoftGraph.Constants.ScopeDefault };
var client = GraphServiceClientFactory.GetAuthenticatedGraphClient(() => AcquireAppToken(scopes), "https://graph.microsoft.com/beta");
var request = client.Sites[siteID].Lists[listID].ContentTypes.Request().Filter($"name eq '{contentTypeName}'");
var result = await request.GetAsync();
return result.First().Id;
List Item ID:
var scopes = new string[] { ISD.MicrosoftGraph.Constants.ScopeDefault };
var client = GraphServiceClientFactory.GetAuthenticatedGraphClient(() => AcquireAppToken(scopes), "https://graph.microsoft.com/beta");
var request = client.Sites[siteID].Drives[driveID].Items[folderID].Request().Select("sharepointIds");
var result = await request.GetAsync();
return result.SharepointIds.ListItemId;
Set folder content type and Proprities:
var scopes = new string[] { ISD.MicrosoftGraph.Constants.ScopeDefault };
var client = GraphServiceClientFactory.GetAuthenticatedGraphClient(() => AcquireAppToken(scopes), "https://graph.microsoft.com/beta");
var listItem = new Microsoft.Graph.ListItem
{
Fields = new FieldValueSet
{
AdditionalData = new Dictionary<string, object>()
{
{"Country", "Palestine"},
{ "My_x0020_Field", "2000"}//Custom field with spaces
}
}
, ContentType = new ContentTypeInfo() {
Id = "0x5465424879454894654564654F300A1C2CDC00E306F9F19B9654654654654" //this is a sample content type id acquired in step 6
}
};
var request = client.Sites[siteID].Lists[listID].Items[listItemID].Request();
var result = await request.UpdateAsync(listItem);
Hope this helps someone

Woocommerce.NET + C#: get the ID of product from SKU

I am making a small app using C# with Woocommerce.NET wrapper.
I would like to edit a product, but I do not have the ID of a product - only SKU.
What would be the easiest way to get product ID from SKU number?
I have tried this:
RestAPI rest = new RestAPI(url, key, secret);
WCObject wc = new WCObject(rest);
var products = wc.Product.GetAll().GetAwaiter().GetResult();
products.ForEach(p => if p.sku = productSKU)
{
var productIDfromSKU = p.id;
}
EDIT: I have changed the code, to convert to int and it now works!
foreach (var p in products)
{
if (p.sku == SKU)
{
IDfromSKU = Convert.ToInt32(p.id);
};
};
But the problem is, that I only get a list of 10 products - not all.
Is there a setting for that?
My question remain - Is there a more straight forward way?
EDIT 2:
I have implemented your answers, the code works, but it is terribly slow.
2-3 minutes on ~5000 products.
What can I do to speed things up?
EDIT 3:
Sorry, have not done enough testing - the second answer great!
string SKU = "***wanted SKU***";
List<Product> products = new List<Product>();
Dictionary<string, string> pDic = new Dictionary<string, string>();
pDic.Add("sku", SKU);
int productIDfromSKU = 0;
string productNamefromSKU = "";
products = await wc.Product.GetAll(pDic);
if (products.Count > 0)
{
productIDfromSKU = Convert.ToInt32(products[0].id);
productNfromSKU = products[0].name;
}
Consider my problem solved!
Thank you all!
RestAPI rest = new RestAPI(url, key, secret);
WCObject wc = new WCObject(rest);
string SKU = "***wanted SKU***";
List<Product> products = new List<Product>();
Dictionary<string, string> pDic = new Dictionary<string, string>();
pDic.Add("sku", SKU);
int productIDfromSKU = 0;
string productNamefromSKU = "";
products = await wc.Product.GetAll(pDic);
if (products.Count > 0)
{
productIDfromSKU = Convert.ToInt32(products[0].id);
productNfromSKU = products[0].name;
}
RestAPI rest = new RestAPI(url, key, secret);
WCObject wc = new WCObject(rest);
List<Product> products = new List<Product>();
Dictionary<string, string> dic1 = new Dictionary<string, string>();
dic1.Add("per_page", "100");
int pageNumber1 = 1;
dic1.Add("page", pageNumber1.ToString());
bool endWhile1 = false;
while (!endWhile1)
{
var productsTemp = await wc.Product.GetAll(dic1);
if (productsTemp.Count > 0)
{
products.AddRange(productsTemp);
pageNumber1++;
dic1["page"] = pageNumber1.ToString();
}
else
{
endWhile1 = true;
}
}
foreach (Product p in products)
{
if (p.sku == SKU)
{
IDfromSKU = Convert.ToInt32(p.id);
break;
};
}

C# (Xamarin iOS) How to loop son data on Custom UITableViewCell?

Any Help will be appreaciated :) Thank you in advance
I tried to loop other object inside of the function and its working but on this, it can't loop. Help. this is rush, and I'm not that familiar with creating iOS app.
public override void ViewDidLoad()
{
base.ViewDidLoad();
using (var web = new WebClient())
{
var url = "http://www.creativeinterlace.com/smitten/maintenance/api/feeds/get-miss-location/101";
json = web.DownloadString(url);
}
json = json.Replace("{\"location\":", "").Replace("}]}", "}]");
var ls = JArray.Parse(json);
if (ls.Count != 0)
{
foreach (var x in ls)
{
var name = x.SelectToken("location");
name1 = Convert.ToString(name);
var loc = x.SelectToken("address");
loc1 = Convert.ToString(loc);
var time = x.SelectToken("time_ago");
time1 = Convert.ToString(time);
locations = new List<Locations>
{
new Locations
{
shopname = name1,
address= loc1,
time = time1
},
};
}
nmtable.Source = new LocationSource(locations);
nmtable.RowHeight = 60;
nmtable.ReloadData();
}
}
You initialize the locations every time in the loop,so the list updates with only the newest object. You should initialize the list outside of the loop , and add object every time.
locations = new List<Locations>();
if (ls.Count != 0)
{
foreach (var x in ls)
{
var name = x.SelectToken("location");
name1 = Convert.ToString(name);
var loc = x.SelectToken("address");
loc1 = Convert.ToString(loc);
var time = x.SelectToken("time_ago");
time1 = Convert.ToString(time);
locations.Add(new Locations{ shopname = name1,address= loc1,time = time1});
};
}

Xamarin Android FindViewById<ListView> returns null

I am trying to pull REST data from an api deserialise it and place it in a list. I have tried like so
private void ParseAndDisplay(JsonValue json)
{
ListView lstData = FindViewById<ListView>(Resource.Id.lstData);
List<Team> list_teams = new List<Team>();
RootObject objs = JsonConvert.DeserializeObject<RootObject>(json.ToString());
foreach (var obj in objs.teams)
{
var id = obj._links.self.href;
var indexOfLastBackSlash = id.LastIndexOf("/") + 1;
id = id.Substring(indexOfLastBackSlash);
Team team = new Team();
team.name = obj.name;
//team.id = id;
list_teams.Add(team);
//var list = list_teams.ToArray();
var slist = new List<string>();
foreach (Team t in list_teams) { string s = t.name;
slist.Add(s);
}
var data = new string[slist.Count()];
data = slist.ToArray();
lstData.Adapter = new ArrayAdapter(this,Resource.Xml.listViewTemplate, data);
}
However lstData comes up as null when I try to assign it to the ArrayAdapter and an unhandled exception error occurs. I am trying to run it to my phone.

Get Posts (Wall Facebook) of me and my friends

I use
https://developers.facebook.com/tools/access_token/
I create an App. I want get Posts of the wall of me and my friends.
I try me/feed and me/posts but I get nothing.
I have this unit test.
Any suggestions?
[TestMethod]
public void Basic_using_SDK()
{
// http://blog.prabir.me/posts/facebook-csharp-sdk-making-requests
var fb = new Facebook.FacebookClient();
var result = (IDictionary<string, object>)fb.Get("4");
var id = (string)result["id"];
var name = (string)result["name"];
var firstName = (string)result["first_name"];
var lastName = (string)result["last_name"];
var link = (string)result["link"];
var username = (string)result["username"];
var gender = (string)result["gender"];
var male = (string)result["locale"];
var parameters = new Dictionary<string, object>();
parameters["fields"] = "id,name";
result = (IDictionary<string, object>)fb.Get("4", parameters);
id = (string)result["id"];
name = (string)result["name"];
dynamic result2 = fb.Get("4");
id = result2.id;
name = result2.name;
firstName = result2.first_name;
lastName = result2.last_name;
link = result2.link;
username = result2.username;
gender = result2.gender;
male = result2.locale;
dynamic parameters2 = new ExpandoObject();
parameters2.fields = "id,name";
dynamic result3 = fb.Get("4", parameters);
id = result3.id;
name = result3.name;
dynamic me = fb.Get("zuck");
firstName = me.first_name;
lastName = me.last_name;
var client = new FacebookClient(AccessToken);
dynamic me2 = client.Get("me");
string aboutMe = me2.about;
dynamic result4 = client.Get("/me/feed");
foreach (dynamic post in result4.data)
{
var fromName = post.from.name;
Console.WriteLine(fromName);
}
dynamic result5 = client.Get("/me/posts");
for (int i = 0; i < result5.Count; i++)
{
}
// https://www.facebook.com/profile.php?id=xxxxxxx
// https://graph.facebook.com/xxxxxxx
var uidKiquenet = "xxxxx";
var query = string.Format(#"SELECT status_id,message,time,source,uid,place_id
FROM status WHERE uid IN (SELECT uid FROM status WHERE uid = '" + uidKiquenet + "') ORDER BY time DESC");
dynamic parameters6 = new ExpandoObject();
parameters6.q = query;
dynamic results6 = fb.Get("/xxxxx?fields=id,name,age_range,about,email,first_name,gender");
string myMessage = "Hello from Test";
fb.PostTaskAsync("me/feed", new { message = myMessage }).ContinueWith(t =>
{
if (!t.IsFaulted)
{
string message = "Great, your message has been posted to you wall!";
Console.WriteLine(message);
}
});
fb.GetTaskAsync("me").ContinueWith(t =>
{
if (!t.IsFaulted)
{
var result11 = (IDictionary<string, object>)t.Result;
string myDetails = string.Format("Your name is: {0} {1} and your Facebook profile Url is: {3}",
(string)result11["first_name"], (string)result11["last_name"],
(string)result11["link"]);
Console.WriteLine(myDetails);
}
});
// This uses Facebook Query Language
// See https://developers.facebook.com/docs/technical-guides/fql/ for more information.
query = string.Format("SELECT uid,name,pic_square FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1={0}) ORDER BY name ASC", "me()");
fb.GetTaskAsync("fql", new { q = query }).ContinueWith(t =>
{
if (!t.IsFaulted)
{
var result1 = (IDictionary<string, object>)t.Result;
var data = (IList<object>)result1["data"];
var count = data.Count;
var message = string.Format("You have {0} friends", count);
Console.WriteLine(message);
foreach (IDictionary<string, object> friend in data)
Console.WriteLine((string)friend["name"]);
}
});
}
You must authorize with the correct permission in order to get access to feed posts. Try authorizing with user_posts, as it is explained in the docs: https://developers.facebook.com/docs/graph-api/reference/v2.3/user/feed#read
Be aware that this does not get you access to posts of friends, unless they posted on the wall of the authorized user.
About review, you may want to read this: https://developers.facebook.com/docs/facebook-login/review/faqs#what_is_review
Btw, FQL is deprecated and will only work in v2.0 Apps - not in newer ones.
Same thing happened to me . Here is my Solution
I made my project registered on Facebook developer console. Then I did my code same as you but could not get posts / information . After some time i submitted my application for app review to facebook team (it was still in early development phase) and after their feedback I got my code working . So pending Application review can be your issue also . This option is available in application setting . Give it a shot
Update
Another code sample is here
if (Request["code"] == null)
{
Response.Redirect(string.Format("https://graph.facebook.com/oauth/authorize?client_id={0}&redirect_uri={1}&scope={2}",
FB_app_id, Request.Url.AbsoluteUri, FB_scope));
return false;
}
else
{
Dictionary<string, string> tokens = new Dictionary<string, string>();
string url = string.Format("https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&scope={2}&code={3}&client_secret={4}&perms=status_update"
, FB_app_id, Request.Url.AbsoluteUri, FB_scope, Request["code"].ToString(), FB_secret_id);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader rd = new StreamReader(response.GetResponseStream());
string vals = rd.ReadToEnd();
foreach (string token in vals.Split('&'))
{
tokens.Add(token.Substring(0, token.IndexOf('=')), token.Substring(token.IndexOf("=") + 1, token.Length - token.IndexOf('=') - 1));
}
string access_token = tokens["access_token"];
Session["fb_access_token"] = access_token;
return true;
}
}

Categories

Resources