How can I programmatically get Approval Status in SharePoint? - sharepoint

I wanted to programmatically get SharePoint Page Approval Status, I tried as below
public string GetApprovalStatus(string url, string listName, string fileref)
{
string result = string.Empty;
string caml = #"
" + fileref + #"
";
using (SPSite site = new SPSite(url))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[listName];
SPQuery query = new SPQuery();
query.Query = caml;
SPListItemCollection myItems = list.GetItems(query);
if (myItems != null && myItems.Count > 0)
{
DataTable dt = myItems.GetDataTable();
result = dt.Rows[0]["_ModerationStatus"].ToString();
dt.Dispose();
}
}
}
return result;
}
And I return a number, how can I get the Approval Status in text?
Appreciate any help, thank you in advanced

The following code is from the MSDN article for SPModerationInformation.Status:
using (SPSite oSiteCollection = new SPSite("http://localhost"))
{
SPWebCollection collWebsites = oSiteCollection.AllWebs;
foreach (SPWeb oWebsite in collWebsites)
{
SPListCollection collLists = oWebsite.Lists;
foreach (SPList oList in collLists)
{
if (oList.BaseType == SPBaseType.DocumentLibrary)
{
SPDocumentLibrary oDocumentLibrary = (SPDocumentLibrary)oList;
if (!oDocumentLibrary.IsCatalog && oDocumentLibrary.EnableModeration ==
true)
{
SPQuery oQuery = new SPQuery();
oQuery.ViewAttributes =
"ModerationType='Moderator'";
SPListItemCollection collListItems =
oDocumentLibrary.GetItems(oQuery);
foreach (SPListItem oListItem in collListItems)
{
if (oListItem.ModerationInformation.Status ==
SPModerationStatusType.Pending)
{
Console.WriteLine(oWebsite.Url + "/" +
oListItem.File.Url);
oListItem.ModerationInformation.Comment =
"Automatic Approval of items";
oListItem.ModerationInformation.Status =
SPModerationStatusType.Approved;
oListItem.Update();
}
}
}
}
}
oWebsite.Dispose();
}
}

You can use the SPModerationStatusType enum SPModerationStatusType Enum - MSDN to get the text values that you want.
More info: http://spuser.blogspot.com.br/2011/03/how-to-programmatically-get-content.html

Here is the full code that gets and sets (optional) approval status (Possible values for this.oListItem.get_item('_ModerationStatus'): 0 - "Approved", 1 - "Denied", 2- "Pending"):
<script type="text/javascript" src="/jquery-1.10.2.min.js"></script>
<script src="/jquery.SPServices-2013.02a.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () { ExecuteOrDelayUntilScriptLoaded(loadConstants, "sp.js"); });
function loadConstants() {
var userid= _spPageContextInfo.userId;
var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/getuserbyid(" + userid + ")";
var requestHeaders = { "accept" : "application/json;odata=verbose" };
$.ajax({
url : requestUri,
contentType : "application/json;odata=verbose",
headers : requestHeaders,
success : onSuccess,
error : onError
});
function onSuccess(data, request){
var loginName = data.d.Title;
//get current (selected) list item id
var docurl = document.URL;
var beginindex = docurl.indexOf('?ID=') + 4;
var endindex = docurl.indexOf('&Source=');
var itemid = docurl.substring(beginindex, endindex);
var ctx = new SP.ClientContext("your site url");
var oList = ctx.get_web().get_lists().getByTitle('your list name');
this.oListItem = oList.getItemById(itemid);
var appStatus = "";
ctx.load(this.oListItem);
ctx.executeQueryAsync(Function.createDelegate(this, function () {
//get approval status
appStatus = this.oListItem.get_item('_ModerationStatus');
//set approval status to Approved (0)
this.oListItem.set_item('_ModerationStatus', 0);
this.oListItem.update();
ctx.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}), function (sender, args) { alert('Error occured' + args.get_message());});
}
function onError(error) {
alert("error");
}
}
</script>

Related

Executing a site workflow in sharepoint from a console application

I am trying to execute a site workflow from a console application.When the code to execute the workflow runs, it thows an error
An unhandled exception of type 'Microsoft.SharePoint.Client.ServerException' occurred in Microsoft.SharePoint.Client.Runtime.dll
Additional information:
Cannot invoke method or retrieve property from null object. Object returned by the following call stack is null. "GetWorkflowInteropService new Microsoft.SharePoint.WorkflowServices.WorkflowServicesManager()"
string userName = "username";
string password = "password";
string siteUrl = "https://share.example.com/sites/workflowsite";
string workflowName = "MyWorkflow";
using (ClientContext clientContext = new ClientContext(siteUrl))
{
SecureString securePassword = new SecureString();
foreach (char c in password.ToCharArray()) securePassword.AppendChar(c);
clientContext.Credentials = new NetworkCredential(userName, securePassword);
Web web = clientContext.Web;
WorkflowAssociationCollection wfAssociations = web.WorkflowAssociations;
WorkflowAssociation wfAssociation = wfAssociations.GetByName(workflowName);
clientContext.Load(wfAssociation);
clientContext.ExecuteQuery();
WorkflowServicesManager manager = new WorkflowServicesManager(clientContext, web);
InteropService workflowInteropService = manager.GetWorkflowInteropService();
clientContext.Load(workflowInteropService);
clientContext.ExecuteQuery();
workflowInteropService.StartWorkflow(wfAssociation.Name, new Guid(), Guid.Empty, Guid.Empty, null);
clientContext.ExecuteQuery(
}
The code below for your reference:
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.WorkflowServices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;
namespace CSOMStartWorkflow {
class Program {
static void Main(string[] args) {
Console.WriteLine("Enter the Office 365 Login Name");
string loginId = Console.ReadLine();
string pwd = GetInput("Password", true);
Console.WriteLine("Web Url:");
string webUrl = Console.ReadLine();
Console.WriteLine("List Name:");
string listName = Console.ReadLine();
Console.WriteLine("Workflow Name");
string workflowName = Console.ReadLine();
var passWord = new SecureString();
foreach (char c in pwd.ToCharArray()) passWord.AppendChar(c);
using (var ctx = new ClientContext(webUrl)) {
ctx.Credentials = new SharePointOnlineCredentials(loginId, passWord);
var workflowServicesManager = new WorkflowServicesManager(ctx, ctx.Web);
var workflowInteropService = workflowServicesManager.GetWorkflowInteropService();
var workflowSubscriptionService = workflowServicesManager.GetWorkflowSubscriptionService();
var workflowDeploymentService = workflowServicesManager.GetWorkflowDeploymentService();
var workflowInstanceService = workflowServicesManager.GetWorkflowInstanceService();
var publishedWorkflowDefinitions = workflowDeploymentService.EnumerateDefinitions(true);
ctx.Load(publishedWorkflowDefinitions);
ctx.ExecuteQuery();
var def = from defs in publishedWorkflowDefinitions
where defs.DisplayName == workflowName
select defs;
WorkflowDefinition workflow = def.FirstOrDefault();
if(workflow != null) {
// get all workflow associations
var workflowAssociations = workflowSubscriptionService.EnumerateSubscriptionsByDefinition(workflow.Id);
ctx.Load(workflowAssociations);
ctx.ExecuteQuery();
// find the first association
var firstWorkflowAssociation = workflowAssociations.First();
// start the workflow
var startParameters = new Dictionary<string, object>();
if (ctx.Web.ListExists(listName)) {
List list = ctx.Web.GetListByTitle(listName);
CamlQuery query = CamlQuery.CreateAllItemsQuery();
ListItemCollection items = list.GetItems(query);
// Retrieve all items in the ListItemCollection from List.GetItems(Query).
ctx.Load(items);
ctx.ExecuteQuery();
foreach (ListItem listItem in items) {
Console.WriteLine("Starting workflow for item: " + listItem.Id);
workflowInstanceService.StartWorkflowOnListItem(firstWorkflowAssociation, listItem.Id, startParameters);
ctx.ExecuteQuery();
}
}
}
}
Console.WriteLine("Press any key to close....");
Console.ReadKey();
}
private static string GetInput(string label, bool isPassword) {
Console.ForegroundColor = ConsoleColor.White;
Console.Write("{0} : ", label);
Console.ForegroundColor = ConsoleColor.Gray;
string strPwd = "";
for (ConsoleKeyInfo keyInfo = Console.ReadKey(true); keyInfo.Key != ConsoleKey.Enter; keyInfo = Console.ReadKey(true)) {
if (keyInfo.Key == ConsoleKey.Backspace) {
if (strPwd.Length > 0) {
strPwd = strPwd.Remove(strPwd.Length - 1);
Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
Console.Write(" ");
Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
}
} else if (keyInfo.Key != ConsoleKey.Enter) {
if (isPassword) {
Console.Write("*");
} else {
Console.Write(keyInfo.KeyChar);
}
strPwd += keyInfo.KeyChar;
}
}
Console.WriteLine("");
return strPwd;
}
}
}
Reference: Starting a SharePoint Online Workflow with the Client Side Object Model (CSOM)

NetSuite SuiteTalk API - Get Inventory Details

I'm using the SuiteTalk (API) service for NetSuite to retrieve a list of Assemblies. I need to load the InventoryDetails fields on the results to view the serial/lot numbers assigned to the items. This is the current code that I'm using, but the results still show those fields to come back as NULL, although I can see the other fields for the AssemblyBuild object. How do I get the inventory details (serials/lot#'s) to return on a transaction search?
public static List<AssemblyBuildResult> Get()
{
var listAssemblyBuilds = new List<AssemblyBuildResult>();
var service = Service.Context();
var ts = new TransactionSearch();
var tsb = new TransactionSearchBasic();
var sfType = new SearchEnumMultiSelectField
{
#operator = SearchEnumMultiSelectFieldOperator.anyOf,
operatorSpecified = true,
searchValue = new string[] { "_assemblyBuild" }
};
tsb.type = sfType;
ts.basic = tsb;
ts.inventoryDetailJoin = new InventoryDetailSearchBasic();
// perform the search
var response = service.search(ts);
response.pageSizeSpecified = true;
// Process response
if (response.status.isSuccess)
{
// Process the records returned in the response
// Get more records with pagination
if (response.totalRecords > 0)
{
for (var x = 1; x <= response.totalPages; x++)
{
var records = response.recordList;
foreach (var t in records)
{
var ab = (AssemblyBuild) t;
listAssemblyBuilds.Add(GetAssemblyBuildsResult(ab));
}
if (response.pageIndex < response.totalPages)
{
response = service.searchMoreWithId(response.searchId, x + 1);
}
}
}
}
// Parse and return NetSuite WorkOrder into assembly WorkOrderResult list
return listAssemblyBuilds;
}
After much pain and suffering, I was able to solve this problem with the following code:
/// <summary>
/// Returns List of AssemblyBuilds from NetSuite
/// </summary>
/// <returns></returns>
public static List<AssemblyBuildResult> Get(string id = "", bool getDetails = false)
{
// Object to populate and return results
var listAssemblyBuilds = new List<AssemblyBuildResult>();
// Initiate Service and SavedSearch (TransactionSearchAdvanced)
var service = Service.Context();
var tsa = new TransactionSearchAdvanced
{
savedSearchScriptId = "customsearch_web_assemblysearchmainlist"
};
// Filter by ID if specified
if (id != "")
{
tsa.criteria = new TransactionSearch()
{
basic = new TransactionSearchBasic()
{
internalId = new SearchMultiSelectField
{
#operator = SearchMultiSelectFieldOperator.anyOf,
operatorSpecified = true,
searchValue = new[] {
new RecordRef() {
type = RecordType.assemblyBuild,
typeSpecified = true,
internalId = id
}
}
}
}
};
}
// Construct custom columns to return
var tsr = new TransactionSearchRow();
var tsrb = new TransactionSearchRowBasic();
var orderIdCols = new SearchColumnSelectField[1];
var orderIdCol = new SearchColumnSelectField();
orderIdCols[0] = orderIdCol;
tsrb.internalId = orderIdCols;
var tranDateCols = new SearchColumnDateField[1];
var tranDateCol = new SearchColumnDateField();
tranDateCols[0] = tranDateCol;
tsrb.tranDate = tranDateCols;
var serialNumberCols = new SearchColumnStringField[1];
var serialNumberCol = new SearchColumnStringField();
serialNumberCols[0] = serialNumberCol;
tsrb.serialNumbers = serialNumberCols;
// Perform the Search
tsr.basic = tsrb;
tsa.columns = tsr;
var response = service.search(tsa);
// Process response
if (response.status.isSuccess)
{
var searchRows = response.searchRowList;
if (searchRows != null && searchRows.Length >= 1)
{
foreach (SearchRow t in searchRows)
{
var transactionRow = (TransactionSearchRow)t;
listAssemblyBuilds.Add(GetAssemblyBuildsResult(transactionRow, getDetails));
}
}
}
// Parse and return NetSuite WorkOrder into assembly WorkOrderResult list
return listAssemblyBuilds;
}
private static string GetAssemblyBuildLotNumbers(string id)
{
var service = Service.Context();
var serialNumbers = "";
var tsa = new TransactionSearchAdvanced
{
savedSearchScriptId = "customsearch_web_assemblysearchlineitems"
};
service.searchPreferences = new SearchPreferences { bodyFieldsOnly = false };
tsa.criteria = new TransactionSearch()
{
basic = new TransactionSearchBasic()
{
internalId = new SearchMultiSelectField
{
#operator = SearchMultiSelectFieldOperator.anyOf,
operatorSpecified = true,
searchValue = new[] {
new RecordRef() {
type = RecordType.assemblyBuild,
typeSpecified = true,
internalId = id
}
}
}
}
};
// Construct custom columns to return
var tsr = new TransactionSearchRow();
var tsrb = new TransactionSearchRowBasic();
var orderIdCols = new SearchColumnSelectField[1];
var orderIdCol = new SearchColumnSelectField();
orderIdCols[0] = orderIdCol;
tsrb.internalId = orderIdCols;
var serialNumberCols = new SearchColumnStringField[1];
var serialNumberCol = new SearchColumnStringField();
serialNumberCols[0] = serialNumberCol;
tsrb.serialNumbers = serialNumberCols;
tsr.basic = tsrb;
tsa.columns = tsr;
var response = service.search(tsa);
if (response.status.isSuccess)
{
var searchRows = response.searchRowList;
if (searchRows != null && searchRows.Length >= 1)
{
foreach (SearchRow t in searchRows)
{
var transactionRow = (TransactionSearchRow)t;
if (transactionRow.basic.serialNumbers != null)
{
return transactionRow.basic.serialNumbers[0].searchValue;
}
}
}
}
return serialNumbers;
}
private static AssemblyBuildResult GetAssemblyBuildsResult(TransactionSearchRow tsr, bool getDetails)
{
if (tsr != null)
{
var assemblyInfo = new AssemblyBuildResult
{
NetSuiteId = tsr.basic.internalId[0].searchValue.internalId,
ManufacturedDate = tsr.basic.tranDate[0].searchValue,
SerialNumbers = tsr.basic.serialNumbers[0].searchValue
};
// If selected, this will do additional NetSuite queries to get detailed data (slower)
if (getDetails)
{
// Look up Lot Number
assemblyInfo.LotNumber = GetAssemblyBuildLotNumbers(tsr.basic.internalId[0].searchValue.internalId);
}
return assemblyInfo;
}
return null;
}
What I learned about pulling data from NetSuite:
Using SavedSearches is the best method to pull data that doesn't automatically come through in the API objects
It is barely supported
Don't specify an ID on the SavedSearch, specify a criteria in the TransactionSearch to get one record
You will need to specify which columns to actually pull down. NetSuite doesn't just send you the data from a SavedSearch automatically
You cannot view data in a SavedSearch that contains a Grouping
In the Saved Search, use the Criteria Main Line = true/false to read data from the main record (top of UI screen), and line items (bottom of screen)

CAML query contains does not work

I've got this code, which takes a part of the title to perform a query and filter part of the content of a list:
<script type="text/javascript">
var items_lista;
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', Initialize);
function Initialize() {
var PDP_Link_Filter = $("title").text().split("-")[1].split(".")[0];
PDP_Link_Filter = "Link_" + PDP_Link_Filter + "_";
var contexto = SP.ClientContext.get_current();
var web = contexto.get_web();
var listas = web.get_lists();
var parametros = listas.getByTitle('Parametrizacion_WF');
var query = new SP.CamlQuery();
query.set_viewXml("<Query><Where><Contains><FieldRef Name='Title'/>" +
"<Value Type='Text'>" + PDP_Link_Filter + "</Value></Contains></Where></Query>");
console.log(query);
items_lista = parametros.getItems(query);
contexto.load(items_lista);
contexto.executeQueryAsync(Function.createDelegate(this, this.onRequestSucceeded), Function.createDelegate(this, this.onRequestFailed));
} //Initialize
function onRequestSucceeded()
{
console.log(items_lista);
for(i = 0; i < items_lista.get_count(); i++)
{
console.log(items_lista.get_item(i).get_item('Title'));
}
}
function onRequestFailed() { console.log('Error'); }
</script>
The query filter that it generates (obtained through console.log()):
<Query><Where><Contains><FieldRef Name='Title'/><Value Type='Text'>P000</Value></Contains></Where></Query>
But when the for loop runs it shows all the content of the list not just the rows that match the filter.
What am I doing wrong?
This is most probably related with malformed value for SP.CamlQuery.viewXml property. Since this property expects XML schema that defines the list view, the root element has to be View element, for example:
var ctx = SP.ClientContext.get_current();
var list = ctx.get_web().get_lists().getByTitle(listTitle);
var items = list.getItems('<View Scope="RecursiveAll"><Query></Query></View>');
In your case enclose the query with View element:
<View>
<Query>...</Query>
</View>

Add group to list using SharePoint 2010 JSOM

Can someone give me an example of adding a SharePoint group to a list using the javascript client object model. I was able to create groups and add them to the site but I haven't seen any documentation on adding the groups to a list? I know how to do this via c# but not javascript.
How to grant permissions for Group in List via CSOM (JavaScript) in SharePoint 2013
The following example demonstrates how to grant Contribute permissions for group Approvers in list:
var context = SP.ClientContext.get_current();
var web = context.get_web();
var list = web.get_lists().getByTitle(listTitle);
var group = web.get_siteGroups().getByName("Approvers");
var roleDef = web.get_roleDefinitions().getByType(SP.RoleType.contributor);
var roleDefBindings = SP.RoleDefinitionBindingCollection.newObject(context);
roleDefBindings.add(roleDef);
list.get_roleAssignments().add(group,roleDefBindings);
list.update();
context.load(group);
context.load(list);
context.load(roleDef);
context.executeQueryAsync(
function () {
console.log('For group ' + group.get_title() + ' has been granted ' + roleDef.get_name() + ' permissons in List ' + list.get_title());
},
function (sender, args) {
console.log("Error: " + args.get_message());
}
);
Since SP.GroupCollection does not contain the method getByName in SharePoint 2010, use the method SP.GroupCollection.getById(id) instead to return Group client object:
var group = web.get_siteGroups().getById(16); //get Approvers group by Id
function getGroupByName(groupName, completeFunction) {
if (groupName == null) {
throw new Error("Group Name cannot be null");
}
var rv = null;
var currentContext = SP.ClientContext.get_current();
var currentWeb = currentWeb = currentContext.get_web();
var allGroups = currentWeb.get_siteGroups();
currentContext.load(allGroups);
currentContext.executeQueryAsync(getGroupByName_Success, getGroupByName_Failed);
function getGroupByName_Success() {
var groupEnumerator = allGroups.getEnumerator();
while (groupEnumerator.moveNext()) {
rv = groupEnumerator.get_current();
var groupTitle = rv.get_title();
if (groupTitle == groupName) {
groupFound = true;
break;
}
}
if (groupFound == false) {
rv = null;
}
completeFunction(rv);
}
function getGroupByName_Failed(sender, args) {
alert("Error Occurred: " + args.get_message() + "\n" + args.get_stackTrace());
}
}

SP list item - disable "Edit" for all users except for the item creator but still leave a single column editable for all users

Is it possible to use Item-level Permissions in SP 2013 to disable other users modifying items not created by them but still allow them to modify a single field (column) from that item?
I want everyone to be able to input information in that column after clicking "Edit" item button but yet not able to modify any other field if the item is not created by him.
Only the item creator should be able to modify all the fields.
Any ideas how to achieve that are more than welcome :)
You could use client object model for the same as follows:
$(document).ready(function () {
if(CheckCreatedBy() != GetCurrentUser())
{
$("input[Title='EditableByAllUsers']").prop("disabled", true);
}
});
function CheckCreatedBy()
{
var clientContext = new SP.ClientContext.get_current();
var siteColl = clientContext.get_site();
var oList = siteColl.get_rootWeb().get_lists().getByTitle('ChangeEditForm');
var itemId = _spGetQueryParam('id') ;
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('<View><Query><Where><Eq><FieldRef Name=\'ID\'/>' +
'<Value Type=\'Number\'>'+ itemId +'</Value></Eq></Where></Query></View>');
this.collListItem= oList.getItems(camlQuery);
clientContext.load(collListItem);
clientContext.executeQueryAsync(Function.createDelegate(this,this.onCheckCreatedBySuccessMethod), Function.createDelegate(this, this.onCheckCreatedByFailureMethod));
return this.value;
}
function onCheckCreatedBySuccessMethod(sender, args)
{
var CreatedBy = '';
var listItemEnumerator = collListItem.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
CreatedBy = oListItem.get_item('Author').get_lookupValue();
alert(CreatedBy);
return CreatedBy ;
}
}
function onCheckCreatedByFailureMethod(sender, args)
{
alert('request failed ' + args.get_message() + '\n' + args.get_stackTrace());
}
function GetCurrentUser()
{
var ClientContext = new SP.ClientContext.get_current();
this.CurrentWeb = ClientContext.get_web();
ClientContext.load(this.CurrentWeb.get_currentUser());
ClientContext.executeQueryAsync(Function.createDelegate(this, this.onSuccessMethod), Function.createDelegate(this, this.onFailureMethod));
return this.value;
}
function onSuccessMethod(sender, args)
{
var userObject =this.CurrentWeb.get_currentUser().get_title();
return userObject;
}
function onFailureMethod(sender, args) {
alert('request failed ' + args.get_message() + '\n' + args.get_stackTrace());
}
It can also be done using XSL. This will help you with the same.
I hope this helps.

Resources