среда, 2 октября 2013 г.

Включения/выключение анонимного доступа к некоторым объектам

Проверка для листа: 
if ((list.AnonymousPermMask64 & SPBasePermissions.ViewListItems) == SPBasePermissions.ViewListItems)
{ // Anonymous Enabled }

Для отключения:
list.AnonymousPermMask64 = SPBasePermissions.EmptyMask;

Для розширения прав пользователей:

list.AnonymousPermMask64 = SPBasePermissions.AddListItems | BasePermissions.EditListItems | SPBasePermissions.DeleteListItems;
list.Update();

Для включения анонимного доступа к Web (при условии, что анонимный доступ настроен для Web application):web.AnonymousState = SPWeb.WebAnonymousState.On;
web.AnonymousPermMask64 = SPBasePermissions.ViewListItems | SPBasePermissions.ViewVersions | SPBasePermissions.Open | SPBasePermissions.ViewPages;
web.Update();

Для включения для библиотеки или листа:
list.AnonymousState = SPWeb.WebAnonymousState.On;
list.AnonymousPermMask64 = SPBasePermissions.ViewListItems | SPBasePermissions.EditListItems | SPBasePermissions.AddListItems;
list.Update();

четверг, 5 сентября 2013 г.

Использовать URL дя сортировки и фильтрации в листе

Сортировка
SortField=Title&SortDir=Desc
Если нужно отсортировать по другому полю, необходимо заменить Title на имя требуемого поля. Если вы хотите отсортировать в порядке возрастания, вы должны заменить  Desc  на Asc.

Фильтрация
FilterField1=Writer&FilterValue1=Chris%20Tobey
Лист отобразит элементы только те, у которых Writer = Chris Tobey. Для использования другого поля необходимо также заменить данные на желаемые, как в сортировке. Для фильтрации по нескольким полям необходимо наращивать значения на 1. Например:
FilterField1=Writer&FilterValue1=Chris%20Tobey&FilterField2=Reader&FilterValue2=Djon%20Dow

Мультифильтрация
По аналогии с обычной фильтрацией FilterField1=Writer&FilterValue1=Chris%20Tobey, но вместо FilterField1 необходимо использовать FilterField (без 1 !!!), а вместо FilterValue1 используется FilterMiltiValue= Chris%20Tobey;Jane%20Fabitski. FilterMultiValue не чувчтвительный к регистру “in progress” и “In Progress” вернет одни и тот же результат. FilterMultiValue поддерживает шаблоны поиска – при поиске “task*” найдутся “Task 1”, “Task 2” и т.д.. Фильтры и сортировки можно компоновать ?FilterField1=AssignedTo&FilterValue1=Luis Bonifaz&FilterName=Title&FilterMultiValue=*meeting*&SortField=Title&SortDir=Desc

Как создать SharePoint страницу с анонимным доступом

Иногда нам необходимо дать анонимный доступ к SharePoint странице, при условии что на этом WebApplication не включен анонимный доступ. Мы должны выполнить несколько шагов:

1. Добавить в код страницы - protected override bool AllowAnonymousAccess { get { return true; } }
2. Необходимо наследовать класс не от  LayoutsPageBase, а от UnsecuredLayoutsPageBase. Детальнее MSDN: http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.unsecuredlayoutspagebase.aspx
3. Удостоверится что мы не успользуем DynamicMasterPageFile="~/masterurl/default.master", мзменить его надо на MasterPageFile="~/_layouts/simple.master", и ещё  simple.master должен лежать в той же папке что и запрашиваемая анонимная страница 

SPQuery scope

У объекта SPQuery существует область выполнения. Она может быть одной из:
Member name
Description
Default
Показать только файлы и вложенные папки указанной папки.
Recursive
Показать все файлы во всех папках.
RecursiveAll
Показать все файлы и все вложенные папки всех папок
FilesOnly
Показать только файлы из определенной папки.


Для примера, я буду сравнивать результаты запросов с разной областью. В листе есть папки и подпапки. Всего элементов должно быть 561:

string siteUrl = @"http://xxxxxxx&#8221";
using (SPSite site = new SPSite(siteUrl))
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists["Project Documents"];
     Console.WriteLine("List: " + list.Title);
     Console.WriteLine("ReallyCount: " + list.ItemCount);
     SPQuery spQry = new SPQuery();
     spQry.RowLimit = 300;
     do
     {
           SPListItemCollection items = list.GetItems(spQry);
           Console.WriteLine("FirstQuery: " + items.Count);
           spQry.ListItemCollectionPosition = items.ListItemCollectionPosition;
} while (spQry.ListItemCollectionPosition != null);
     spQry = new SPQuery();
     spQry.ViewAttributes = "Scope=\"RecursiveAll\"";
     spQry.RowLimit = 300;
     do
     {
           SPListItemCollection items = list.GetItems(spQry);
           Console.WriteLine("SecondQuery: " + items.Count);
           spQry.ListItemCollectionPosition = items.ListItemCollectionPosition;
} while (spQry.ListItemCollectionPosition != null);
}
Console.Read();

Результат:

Как вы можете  увидеть  list.ItemCount  показывает что элементов в листе всего 8.  Но установив наиболее часто употребляемое значение области  RecursiveAll я получил 561 элемент в 2 захода. 

Получение следующего ID в списке или библиотеке

Иногда действительно хорошо знать, какой ID элемента будет следующим для листа или библиотеки.  Решение этому я нашел, путем прямого подключения к базе данных контента и выбора колонки "tp_NextAvailableId" в таблице "AllLists" для версии 2007 или "NextAvailableId" в  "AllListsAux" для версии 2010 года..
Запросы будут выглядит так:
2007:  SELECT tp_NextAvailableId FROM AllLists where tp_ID=‘{Id листа}’
2010:  SELECT NextAvailableId FROM AllListsAux where ListID=‘{Id листа}’
Наконец, вы можете использовать это расширение для определания следующего ID для кокретного списка:
///<summary>
///Extension above list which send next available item id 
///</summary>
///<returns></returns>
public static int GetNextAvailableIdFromList(this SPList list, SPSite site)
{
    Guid listId = list.ID;
    int nextAvailableId = -1;
    if (site.WebApplication.ContentDatabases.Count > 0)
    {
        string DBConnString = site.ContentDatabase.DatabaseConnectionString;
        SqlConnection con = new SqlConnection(DBConnString);
        try
        {
           con.Open();
           SqlCommand com = con.CreateCommand();
           com.CommandText = String.Format("SELECT NextAvailableId FROM AllListsAux where ListID=’{0}’",
           listId.ToString());
           nextAvailableId = (int)com.ExecuteScalar();
        }
        finally
        {
           con.Close();
        }
    }
    return nextAvailableId;
}

четверг, 22 августа 2013 г.

ListViewByQuery контрол

Введение

ListViewByQuery контрол умеет рендерит view любого листа на основе запроса.

listviewbyquery
Когда контрол покажет юзеров можно будет их отсортировать или применить к ним фильт, но эти события требуют собственной реализаци.

Синтакс

ListViewByQuery контрол это часть Microsoft.SharePoint.dll и расположен в пространстве Microsoft.SharePoint.WebControls. Обявлять нужно так:

<spuc:ListViewByQuery ID="CustomersListViewByQuery" runat="server" Width="700px" />

Так он работать не будет, свойства List и Query можно установить только из кода.
Не забывайте добавить вверху страницы:

<%@ Register TagPrefix="spuc" Namespace="Microsoft.SharePoint.WebControls"
             Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

Можно создать контрол прямо из кода:

private ListViewByQuery CustomersListViewByQuery;
private void EnsureChildControls()
{
     CustomersListViewByQuery = new ListViewByQuery();
     // The rest of the code follows here....
}
Для нормальной работы требуется установить несколько обязательных свойств: List тип которого SPList и Query тип которого SPQuery. В OnLoad или EnsureChildControls можно добавить код:

list = SPContext.Current.Web.Lists["Customers"];
CustomersListViewByQuery.List = list;
string query = null;
if (!Page.IsPostBack)
{
    query = "<OrderBy><FieldRef Name='Title' Ascending='true' /></OrderBy>";
}
else
{
    // apply filtering and/or sorting
}
SPQuery qry = new SPQuery(list.DefaultView);
qry.Query = query;
CustomersListViewByQuery.Query = qry;
Запрос обязательно должен строиться на существующем view листа или контрол не будет работать. Данные в контроле отображаются согласно переданному запросу.
Можно устанавливать ограничение на кол-во возвращаемых записей RowLimit:
qry.RowLimit = 50;

Сортировка

Юзер может сортировать колонку стандартным кликаньем на header колонки и выбрав A on Top or Z on Top.

listviewbyquery-sort2

Это генерирует post back, и данные будут переданы на серверную сторону для обработки сохраненные в Context.Request["SortField"] и Context.Request["SortDir"]. Следующий код показывает как можно работать с ними.

if (!Page.IsPostBack)
{
    query = "<Query><OrderBy><FieldRef Name='Title' Ascending='true' /></OrderBy></Query>";
}
else
{
    // apply filtering and/or sorting
   if (this.Context.Request != null && this.Context.Request["SortField"] != null)
   {
       string sortorder = BuildSortOrder(this.Context.Request["SortField"],
           (this.Context.Request["SortDir"] == "Asc" ? "true" : "false"));
       if (string.IsNullOrEmpty(query))
           query = sortorder;
       else
           query += sortorder;
   }
}
private string BuildSortOrder(string fieldName, string sortOrder)
{
    string query = null;
    if (!string.IsNullOrEmpty(fieldName))
    {
        query = string.Format("<OrderBy><FieldRef Name='{0}' Ascending='{1}' /></OrderBy>", fieldName, sortOrder);
    }           
    return query;
}

Фильтрация
Также юзер может фильтровать данные в ListViewByQuery контроле  listviewbyquery-filter После этого также происходит posting back, выбранное поле хранится в Context.Request["FilterField1"], а выбранное значение в Context.Request["FilterValue1"]. Если фильтров более чем один (например выбран ещё один фильтр в другой колонке) они будут хранится по такому же принципу с именами FilterField2 и FilterValue2. private string BuildFilter() {     string query = "{0}";     bool isFound = true;     int counter = 1;     while (isFound)     {           string filterfield = "FilterField" + counter.ToString();           string filtervalue = "FilterValue" + counter.ToString();           if (this.Context.Request[filterfield] != null && this.Context.Request[filtervalue] != null)           {                // Field type must be treated differently in case of other data type                if (counter > 1)                    query = "<And>" + query + "{0}</And>";                query = string.Format(query, string.Format("<Eq><FieldRef Name='{0}' /><Value Type='Text'>{1}</Value></Eq>",                this.Context.Request[filterfield], this.Context.Request[filtervalue]));                counter++;           }           else           {                isFound = false;           }     }     if (!string.IsNullOrEmpty(query))        query = "<Where>" + query + "</Where>";     return query; } Этот код будет работать только для текстовых полей. Если необходимы другие типы, например number, choice или lookup, необходимо использовать так: SPField field = list.Fields[filterfield]; query = string.Format(query, string.Format("<Eq><FieldRef Name='{0}' /><Value Type='{1}'>{2}</Value></Eq>",                        this.Context.Request[filterfield], field.TypeAsString, this.Context.Request[filtervalue]));

Группировка

ListViewByQuery контрол может также гррупировать элементы, для этого нужно использовать CAML GroupBy элемент: query = "<GroupBy Collapse='FALSE'><FieldRef Name='CountryRegionName' /><FieldRef Name='City' /></GroupBy>"; Этот пример группирует данные по CountryRegionName и по City. listviewbyquery-expanded Если вы решили показать сразу сгруппированый вариант, установите Collapse аттрибут в TRUE и получите: listviewbyquery-collapsed Но здесь есть проблема, если они сгруппированы по умолчанию, то при открытиии вы получити только надпись Loading и никаких данных. listviewbyquery-collapsed-expanding Эта проблема решается так: устанавливаем Collapse аттрибут в FALSE и размещаем наш ListViewByQuery контрол в DIV, затем задаём у дива ID. Ниже дива вставляем скрипт: <div id="ViewDiv" class="ms-authoringcontrols" style="width:700px">      <spuc:ListViewByQuery ID="CustomersListViewByQuery" runat="server" Width="700px" /> </div> <script language="javascript">     ExpLinkFormer = function(divId)     {          this._DivId = divId;          this._init();     }     ExpLinkFormer.prototype = {         _init: function() {          var div = document.getElementById(this._DivId);          var links = div.getElementsByTagName("a");         for (var i = 0; i < links.length; i++) {           if (links[i].href == "javascript:" && links[i].onclick.toString().indexOf("ExpCollGroup") > -1) {               //alert(links[i]);               links[i].click();            }         }      }     }     var expLnk = new ExpLinkFormer('ViewDiv'); </script> ListViewByQuery контрол загружает все данные без группировки, но при рендеринге страницы, клик метод выполняется для всех hyperlinks которые имеют вызов на ExpCollGroup в их href аттрибуте.

Как изменить имя и email адресс существующего пользователя

Можно это сделать через PowerShell

Set-SPUser -Identity 'имямашины\TestUser' -DisplayName TestUser'  -Email 'testuser@yahoo.com' -Web http:// имямашины[порт]