Replacement for DoesUserHavePermissions for List object in SP2013 - sharepoint

I'm working on an app that reuses some code from a previous solution.
The idea is to show a user all of the lists of a certain type in all the webs in a site collection so that the user can aggregate some data.
static public List<SPListMeta> AllSiteAnnouncementsLists(ClientContext clientContext)
{
var returnList = new List<SPListMeta>();
var per = new BasePermissions();
per.Set(PermissionKind.Open);
if (clientContext.Site.RootWeb.DoesUserHavePermissions(per).Value)
{
var rootWebLists = clientContext.Site.RootWeb.Lists;
returnList.AddRange(from List oList in rootWebLists
where oList.DoesUserHavePermissions(SPBasePermissions.ViewListItems) &&
where oList.BaseTemplate == (int)ListTemplateType.Announcements
select new SPListMeta(oList));
var collWebs =
clientContext.Site.OpenWebById(clientContext.Site.RootWeb.Id).GetSubwebsForCurrentUser(null);
foreach(Web oWeb in collWebs)
{
}
}
return returnList;
}
The critical line that does not work and does not seem to have a replacement is
oList.DoesUserHavePermissions(SPBasePermissions.ViewListItems)
as this has been removed from the CSOM List object
What's the new way to do this?

The new way to check for permissions is:
List.EffectiveBasePermissions.Has(PermissionKind.Open)

Related

Multi-Select fields on a Sharepoint list using OWSSVR.dll

I am in the process of creating a massive SSIS project to move the data from a series of Sharepoint Lists to a new Dynamics CRM Implementation (On-line). The SSIS package uses an OData Source to pull the data from the lists.
There are two columns on my list that do not show up on the OData call. These two columns have Multi-Select or Multi-Lookup values. REST services do not support multi-select choice fields. (Found on another thread: The methods you are attempting only work with choice columns that are NOT multi-select. Unfortunately, multi-select choice columns are not supported by the REST interface. Same holds true for SharePoint 2013 apparently.)
Therefore, I need to try to access the data in these columns on the SharePoint List using the OWSSVR.dll. The list I am having issues with gives me a "This page can’t be displayed" or a "This site can’t be reached" depending on the browser I use.
I verified the List ID by grabbing It from the list settings. Since it didn't work, I went to another SharePoint List I already migrated to verify the URL format. The other list works and brings back the data in XML format.
I am wondering if the OWSSVR.dll has the same restriction on Multi-select values. Any ideas or suggestions?
Psuedo URLS (restricted access site):
Works: http://dummy.sharepointSite.Com/cases/_vti_bin/owssvr.dll?Cmd=Display&List={b703d405-48c8-4211-9137-e1b50bdb0330}&XMLDATA=TRUE
Broken: http://dummy.sharepointSite.Com/cases/_vti_bin/owssvr.dll?Cmd=Display&List={8e148584-b5be-48f5-9343-85d23a7731cc}&XMLDATA=TRUE
I figured out a way to do this without using OWSSVR. I have to set up the User Context to the SharePoint site then retrieve the list of items.
Methods:
public static ClientContext SetupSPContext(string documentLibrarySiteURL,
string userName, string password, string domain = "")
{
ClientContext clientContext = new ClientContext(documentLibrarySiteURL);
SecureString pwString = new SecureString();
foreach (char c in password.ToCharArray()) { pwString.AppendChar(c); }
if (!String.IsNullOrWhiteSpace(domain))
clientContext.Credentials = new NetworkCredential(userName, pwString, domain);
else
clientContext.Credentials = new SharePointOnlineCredentials(userName, pwString);
Web web = clientContext.Web;
clientContext.Load(web);
clientContext.ExecuteQuery();
return clientContext;
}
public static ListItemCollection GetListItems(ClientContext context, string listName)
{
ListCollection listCollection = context.Web.Lists;
List targetList = context.Web.Lists.GetByTitle(listName);
CamlQuery query = new CamlQuery();
query.ViewXml = "<Query><OrderBy><FieldRef Name='fieldName' /></OrderBy></Query>";
ListItemCollection collListItem = targetList.GetItems(query);
context.Load(collListItem);
context.ExecuteQuery();
if (collListItem.Count == 0)
{
return null;
}
else
{
return collListItem;
}
}
Code in SSIS Script Component:
//In the PreExecute method:
// Variables were defined for the class and not in the preExecute Method
ClientContext spContext = SetupSPContext(Variables.spLocation, Variables.spUserName,
Variables.spPassword, Variables.spDomain);
ListItemCollection listItems = GetListItems(spContext, "List Name");
//Inside the Individual loop inside SSIS (Input0_ProcessInputRow):
ListItem listItem = GetListItem(listItems, fieldValue);
//Multiple Lookup Code
var values = (FieldLookupValue[])listItem["fieldName"];
var finalValue = "FieldName values: ";
if (values.Length > 0)
{
foreach (var value in values)
{
finalValue = value.LookupValue + "; ";
}
}
//Multiple Select
if (listItem["fieldName2"] != null)
{
var valuesTwo = (string[])listItem["fieldName2"];
string combinedValues = "fieldName2 Values: ";
foreach (var value in valuesTwo)
{
combinedValues += value + "; ";
}
}

Access is denied Exception when updating List items using SPUserToken

I try to do some actions on Sharepoint 2010 list using an unlowed user( having only read right) and i got Access denied exception.
Is it possible to do it whithout changing the user rights.
please find below my code:
public void StartWorkFlow(int itemID, int wfTemplateID, String entityName, String userShortname)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPUser spUser;
using (site = new SPSite(siteUrl))
{
using (web = site.RootWeb)
{
spUser = web.EnsureUser(userShortname);
}
}
using (site = new SPSite(siteUrl, spUser.UserToken))
{
using (web = site.AllWebs["WPrs"])
{
list = web.Lists["Workflow Template"];
SPListItem item = list.Items.GetItemById(wfTemplateID);
SPList processList = web.Lists["List Process " + item["Template_x0020_Name"]];
SPListItem newInstance = processList.Items.Add();
newInstance["Template_x0020_Name"] = item["Template_x0020_Name"];
newInstance["Template_x0020_Description"] = item["Template_x0020_Description"];
newInstance["Date_x0020_De_x0020_Publication"] = item["Date_x0020_De_x0020_Publication"];
newInstance["Item_x0020_Id"] = itemID;
newInstance["Item_x0020_Extradata"] = entityName.ToLower() + "||Parameter||" + "";
newInstance["CTName"] = Utility.GetInstance().GetSuperItemNameBySubItemName(entityName);
web.AllowUnsafeUpdates = true;
newInstance.Update();
web.AllowUnsafeUpdates = false;
}
}
});
}
Thank you in advance.
To be able to use site.AllWebs the user must have Full Control to the site. Instead of using AllWebs try to get the sub sites using the following code -
SPWebCollection subwebs = CurrentSite.OpenWeb().GetSubwebsForCurrentUser();
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spweb.getsubwebsforcurrentuser%28v=office.12%29.aspx
http://social.msdn.microsoft.com/Forums/sharepoint/en-US/e7ff284f-fe4b-42fb-8b21-a475e331a18c/access-denied-for-user-with-contribute-rights?forum=sharepointdevelopmentlegacy
Also you would not be able to update a listitem with read only rights.
If the only requirement is to set up the Created By/Modified By field - you should be able to overwrite default value by using SystemUpdate instead of Update. But still you need to run this RunWithElevatedPrivileges mode instead of UserToken
Although I'm not sure what will happen if have any other dependent actions after this update (event receivers or workflows) i'm not sure what context it will use (i.e. if SharePoint internally will use current SPWeb.CurrentUser object.

Searching managed navigation termset

Is there a way to search/find a specific managed navigation term by guid using server object model
This code
var termGuid = new Guid(fieldValue.TermGuid);
var navTermSet = TaxonomyNavigation.GetTermSetForWeb(SPContext.Current.Web, StandardNavigationProviderNames.GlobalNavigationTaxonomyProvider, true);
if (navTermSet == null) return String.Empty;
var navTerm = navTermSet.Terms.Where(c => c.Id == termGuid).FirstOrDefault();
if (navTerm == null) return String.Empty;
return navTerm.GetWebRelativeFriendlyUrl();
only works if the term is in the first level, if its deeper down in hierarchy it doesn't find it and I'm not seeing any other mechanism that gets me a flat list of terms
It looks like a severe limitation with API
When you're looking for a certain term and you don't know how deep this resides and wether it's a parent or child, this becomes more complicated. If the API has no direct way of getting all the terms, regardless wether they're child or parent, I guess your best option is to list them all yourself by looping all terms + children and then find them by Guid.
Below code can be used to list all terms. The code is taken and shortened for your ease from this article.
List<Term> allTerms = new List<Term>();
void BuildTermList()
{
SPSite thisSite = SPContext.Current.Site;
TaxonomySession session = new TaxonomySession (thisSite);
foreach (TermStore termStore in session.TermStores)
{
foreach (Group group in termStore.Groups)
{
foreach (TermSet termSet in group.TermSets)
{
foreach (Term term in termSet.Terms)
{
AddTermSet(term);
}
}
}
}
}
void AddTermSet(Term term)
{
allItems.Add(term);
foreach (Term t in term.Terms)
AddTermSet(t);
}
Now that you have the list you can query it. Hope this helps.

Add/Create new document in SharePoint document Library programmatically

I have created a new Document Library and set up custom content type with MS Word Document Template. When i click on Create new template it works fine. but i need to be able to add some logic on a button event where it will go into that library and create a new document, so that when i go into that library i will see a new document that has been created by that button event.
i tried doing it as i would do a regular list item, but i got the following error on item.update:
To add an item to a document library, use SPFileCollection.Add()
Now i did some research but everywhere i see the code for uploading a file to the document library but no where i can find how to add a new document using my template that is associated in that doc library.
please help and thanks.
public static void colFileMtod()
{
using (SPSite objsite = new SPSite("http://smi-dev.na.sysco.net/SyscoFinance/FSR/"))
{
using (SPWeb objWeb = objsite.OpenWeb())
{
SPFileCollection collFiles = objWeb.GetFolder("BPCPublishRecord").Files;
SPList lst = objWeb.Lists["BPCPublishRecordCopy"];
if (lst != null)
{
if (objWeb.Lists.Cast<SPList>().Any(list => list.Title.Equals("BPCPublishRecordCopy", StringComparison.OrdinalIgnoreCase)))
{
foreach (SPFile file in collFiles)
{
string strDestUrl = collFiles.Folder.Url + "/" + file.Name;
byte[] binFile = file.OpenBinary();
SPUser oUserAuthor = file.Author;
SPUser oUserModified = file.ModifiedBy;
System.DateTime dtCreated = file.TimeCreated;
System.DateTime dtModified = file.TimeLastModified;
SPFile oFileNew = collFiles.Add(strDestUrl, binFile, oUserAuthor, oUserModified, dtCreated, dtModified);
SPListItem oListItem = lst.AddItem();
oListItem = oFileNew.Item;
oListItem["Created"] = dtCreated;
oListItem["Modified"] = dtModified;
oListItem.Update();
objWeb.AllowUnsafeUpdates = true;
}
}
}
}
}
}

Bast Way On Passing Query Parameters to Solrnet

I have been working on making a Search using Solrnet which is working the way I want to. But I just would like some advice on the best way to pass my query parameters from my web page into Solrnet.
What I would ideally like to do is pass my query string parameters similar to how this site does it: http://www.watchfinder.co.uk/SearchResults.aspx?q=%3a&f_brand=Rolex&f_bracelets=Steel&f_movements=Automatic.
As you can see from the sites query string it looks like it is being passed into SolrNet directly. Here is I am doing it at the moment (facet query segment):
public class SoftwareSalesSearcher
{
public static SoftwareSalesSearchResults Facet()
{
ISolrOperations solr = SolrOperationsCache.GetSolrOperations(ConfigurationManager.AppSettings["SolrUrl"]);
//Iterate through querystring to get the required fields to query Solrnet
List queryCollection = new List();
foreach (string key in HttpContext.Current.Request.QueryString.Keys)
{
queryCollection.Add(new SolrQuery(String.Format("{0}:{1}", key, HttpContext.Current.Request.QueryString[key])));
}
var lessThan25 = new SolrQueryByRange("SoftwareSales", 0m, 25m);
var moreThan25 = new SolrQueryByRange("SoftwareSales", 26m, 50m);
var moreThan50 = new SolrQueryByRange("SoftwareSales", 51m, 75m);
var moreThan75 = new SolrQueryByRange("SoftwareSales", 76m, 100m);
QueryOptions options = new QueryOptions
{
Rows = 0,
Facet = new FacetParameters {
Queries = new[] { new SolrFacetQuery(lessThan25), new SolrFacetQuery(moreThan25), new SolrFacetQuery(moreThan50), new SolrFacetQuery(moreThan75) }
},
FilterQueries = queryCollection.ToArray()
};
var results = solr.Query(SolrQuery.All, options);
var searchResults = new SoftwareSalesSearchResults();
List softwareSalesInformation = new List();
foreach (var facet in results.FacetQueries)
{
if (facet.Value != 0)
{
SoftwareSalesFacetDetail salesItem = new SoftwareSalesFacetDetail();
salesItem.Price = facet.Key;
salesItem.Value = facet.Value;
softwareSalesInformation.Add(salesItem);
}
}
searchResults.Results = softwareSalesInformation;
searchResults.TotalResults = results.NumFound;
searchResults.QueryTime = results.Header.QTime;
return searchResults;
}
}
At the moment I can't seem to see how I can query all my results from my current code by add the following querystring: q=:.
I'm not sure what you mean by "parameters being passed into SolrNet directly". It seems that watchfinder is using some variant of the model binder included in the SolrNet sample app.
Also take a look at the controller in the sample app to see how the SolrNet parameters are built.

Resources