Microsoft Days 2010 – код и PowerPoint Slides

by Ради Атанасов 17. April 2010 16:58

За мен това беше първият MS Days на който съм присъствал - бях супер доволен. Добра атмосфера, много партньори, добри лекции… дори имаше и бира ?!?!?

Лекцията, която изнесох беше най-техническата на тема SharePoint – искаше ми се да има повече SharePoint (:

Ето и кода, който обещах: PerformanceManagement.zip

Това, за което може да ви е полезен е:

  1. Добавяне на бутон в Ribbon на SharePoint 2010
  2. Link към custom javascript file за този бутон
  3. отваряне на диалогов прозорец с т.н. Dialog Framework
  4. SP2010 webpart, който генерира Office документи с Open XML и Word Automation Services – супер интересно (:
  5. Има и един web service в SP 2010

Ето и презентацията: MS Days Radi Atanassov

Аз лично бях доволен от лекцията, въпреки че забравих да покажа генерираните PDF и XPS files…

Ето го и рейтинга ми:

Ради Атанасов

Архитектура и изграждане на бизнес приложения с SharePoint 2010, Silverlight и Open XML SDK (Ниво: 300)

79

Oбща оценка на презентацията

7.85 / 9

Ради Атанасов

Архитектура и изграждане на бизнес приложения с SharePoint 2010, Silverlight и Open XML SDK (Ниво: 300)

79

Компетентност на лектора

8.08 / 9

Ради Атанасов

Архитектура и изграждане на бизнес приложения с SharePoint 2010, Silverlight и Open XML SDK (Ниво: 300)

79

Предоставената информация е полезна за моята работа

7.46 / 9

Ради Атанасов

Архитектура и изграждане на бизнес приложения с SharePoint 2010, Silverlight и Open XML SDK (Ниво: 300)

79

Презентационни умения на лектора

7.54 / 9

Поздрави!

Tags: , , , , ,

Bulgarian

Използване на LINQ to XML върху резултатите от SharePoint Web Services

by Ради Атанасов 18. March 2010 12:02

Когато работиме със Silverlight имаме възможност да използваме LINQ to XML за извличане на данни от резултатите от SharePoint Web Services. Тези дни разгледах LINQ to XML и никога повече не бих работил с XmlDocument обектите (:

Ето няколко примера:

GetListItems() – това е метод от Lists.asmx, и ето му отговора:

<listitems xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema"
xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<rs:data ItemCount="13">
   <z:row ... ows_ContentType="Task" ows_Title="New Task 1" ... />
   ... more rows here
</rs:data>
</listitems>

За да извлечем заглавията на list items и да ги подредим в List<string> обект:

private List<string> ProcessListResults(SPListsWS.GetListItemsCompletedEventArgs e)
{
    string result = e.Result.ToString();
 
    XNamespace ns = "#RowsetSchema";
    XElement results = new XElement(e.Result);
 
    var listItems = from x in results.Descendants(ns + "row")
                    where x.Attribute("ows_Title") != null
                    select x;
 
    List<string> itemsList = new List<string>();
 
    foreach (var item in listItems)
    {
        string title = item.Attribute("ows_Title").Value;
        itemsList.Add(title);
    }
    return itemsList;
}

GetUserInfo() – Този метод е от usergroup.asmx и ни дава информация за user в текущия SPSite обект (взима го от скрития user list). Ето отговора:

<GetUserInfo xmlns="http://schemas.microsoft.com/sharepoint/soap/directory/">
  <User ID="7" Sid="S-1-5-21-347908140-582334945-263120918-1111" Name="Radi"
    LoginName="DEV\radi" Email="" Notes="" IsSiteAdmin="False"
    IsDomainGroup="False" />
</GetUserInfo>

 

И как извлиам LoginName:

public static string GetLoginFromServiceResponse(XElement result)
{
    XNamespace ns = "http://schemas.microsoft.com/sharepoint/soap/directory/";
 
    XName xUser = XName.Get("User", ns.NamespaceName);
    XName xUserInfo = XName.Get("GetUserInfo", ns.NamespaceName);
 
    XElement user = result.Element(xUser);
 
    if (user != null) {  return user.Attribute("LoginName").Value; }
 
    return null;
}

Това което подавам на метода е “e.Result.ToString()” от отговора.

Очаквайте още!

Tags: , , , ,

Bulgarian

SharePoint meets LINQ to XML: CAML заявки за работа с Lists.asmx

by Ради Атанасов 18. March 2010 10:28

Напоследък ми се налага да работя с LINQ to XML за интеграционни сценарии включващи Silverlight и SharePoint. LINQ to XML е страхотно – сравнително по-добре от създаване на XML чрез обекти като XmlDocument.

Ето пример – повиквам GetListItems() метода на Lists.asmx. Със следният код извличам list items от Task списъка създадени от специфичен user. Този пример би трябвало да работи както за WSS v3, така и за MSF v4.

XElement query = new XElement("Query",
        new XElement("Where",
            new XElement("Eq",
                new XElement("FieldRef", new XAttribute("Name", "Author"), new XAttribute("LookupId", "True")),
                new XElement("Value", new XAttribute("Type", "User"), userID)
)));


XElement queryOptions = new XElement("QueryOptions");
XElement viewFields = new XElement("ViewFields");

_listService.GetListItemsAsync("Tasks", null,
    query, viewFields, "100", queryOptions, null, null);

userID e SharePoint ID-то на потребителя, за който искам да видя резултатите. Можете да получите тази информация от usergroup.asmx.

Успех!

Tags: , , , ,

Bulgarian

Автоматично показване на DIP когато се отваря Word документ

by Ради Атанасов 21. February 2010 07:45

Работя по един проект, в който имам дефинирани Content Types в Feature. Тези Content Types имат различни document templates, и ми се наложи да конфигурирам Document Information Panel (DIP) да се отваря автоматично. Това става лесно чрез интерфейса, но трябваше да е част от автоматизиран деплоймент.

В следващия код показвам как става това. Подаваме SPContentType обект, на който му се дефинира нов CustomXsn елемент в своята XmlDocuments колекция. Ако под-елемента openByDefault е “True”, DIP ще се покаже при отварянето на документа. Използвам FeatureReceiver за прекарам мойте Content Types през този статичен метод:

public static void ConfigureContentTypes(SPContentType ct)
{
    XmlDocument doc = GetCustomXsnDocument();
 
    ct.XmlDocuments.Add(doc);
    ct.Update(true);
}
 
private static XmlDocument GetCustomXsnDocument()
{
    XmlDocument doc = new XmlDocument();
    
    string xml = "<customXsn xmlns=\"http://schemas.microsoft.com/office/2006/metadata/customXsn\"><xsnLocation></xsnLocation><cached>True</cached><openByDefault>True</openByDefault><xsnScope></xsnScope></customXsn>";
 
    doc.LoadXml(xml);
    return doc;
}

Можете да намерите повече информация за CustomXsn елемента на този MSDN линк: Content Type Document Information Panel Schema

Дано това помогне на някой.

Tags: , , ,

Bulgarian

Формите на списъци в SharePoint 2007 - как работят те – Втора Част

by Ради Атанасов 20. February 2010 13:55

Този пост е продължение на предишния, в който разглеждам как можем да заменим “NewFormUrl”, “EditFormUrl” и “DisplayFormUrl” притежанията на Content Type обекти, с цел да се заменят формите, с които SharePoint показва данни за определен list item. Тука ще опиша как SharePoint използва Rendering Templates по време на зареждането на тези форми, и как можем да ги заменим с произволни, така че да добавиме функционалност.

Ето как работят Rendering Templates:

Всеки list item в SharePoint списък е под формата на определен Content Type. В повечето случай това е или “Item”, или “Document” Content Type, в зависимост от списъка, в който този list item се намира. Като разработчици, ние създаваме нови Content Types, които имат смисъл за съответния бизнес: Invoice, Quote, Proposal и т.н.

Всеки Content Type има свой “New”, “Edit” и “Display” форми за събиране и показване на своите данни. Всяка една от тези форми е дефинирана чрез “Form Rendering Template”, който съдържа HTML markup, или ASCX контролки.

Тези Rendering Templates са дефинирани в ASCX файлове в _CONTROLTEMPLATES папката (...12\TEMPLATE\CONTROLTEMPLATES). На повечето обекти в SharePoint са им дефинирани Rendering Templates в DefaultTemplates.ascx, там ще намерите HTML на много обекти като Toolbar, ListFieldIterator и т.н. Ето как е дефиниран DocumentLibraryForm:

<SharePoint:RenderingTemplate ID="DocumentLibraryForm" runat="server">
    <Template>
        <SharePoint:InformationBar runat="server"/>
        <wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbltop" 
        RightButtonSeparator="" runat="server">
            <Template_RightButtons>
                <SharePoint:SaveButton runat="server"/>
                <SharePoint:GoBackButton runat="server"/>
            </Template_RightButtons>
        </wssuc:ToolBar>
        <SharePoint:FormToolBar runat="server"/>
        <SharePoint:FormComponent TemplateName="DocumentLibraryFormCore" 
        runat="server"/>
    </Template>
</SharePoint:RenderingTemplate>

Забележете, че този Rendering Template вика други “FormCompontent” обекти чрез “TemplateName” атрибута. Това е много сходно с PHP…

Нашата цел, е да заменим тези Rendering Templates, за да променим това, което крайните потребители виждат като работят с нашите Content Types.

Имаме 2 варианта:

Вариант 1: посочване на наши Rendering Templates в самата дефиниция на наш Content Type.

Дефиниции на Content Types ни дават тази възможност чрез XmlDocument елементи:

<!-- Document Content Type -->
<ContentType ID="0x0101006BD6DAD38F7947799A6F2EE72F5C3C24"
    Name="TemporaryContentType"
    Group="Custom Content Types"
    Description="">
    <FieldRefs>
        <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" />
    </FieldRefs>
    <XmlDocuments>
        <XmlDocument 
        NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
            <FormTemplates 
            xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
                <Display>MyCustomForm</Display>
                <Edit>MyCustomForm</Edit>
                <New>MyCustomForm</New>
            </FormTemplates>
        </XmlDocument>
    </XmlDocuments>
</ContentType>

 

С горният FormTemplates елемент (в XmlDocument) съм посочил на този Content Type да използва MyCustomForm за Display, New и Edit формите си.

За да създадем MyCustomForm като Rendering Template, трябва да си направим свой ASCX файл и да го сложим в CONTROLTEMPLATES папката. Това е хубаво да стане чрез Feature.

Ето примерен Rendering Template в свой ASCX файл. SharePoint ще разгледа и запомни всички RenderingTemplate обекти по време на зареждане на своя Application Pool, стига те да се намират в CONTROLTEMPLATES папката.

<SharePoint:RenderingTemplate ID="MyCustomForm" runat="server">
    <Template>
        Hello
    </Template>
</SharePoint:RenderingTemplate>

Можете да добавите HTML и свой ASCX контролки и напълно да промените това, което крайните потребители виждат и използват.

Ето какво всъщност става „зад сцената“:

В първата част описах как ListFormWebPart се добавя от платформата на ASPX страници, които по принцип SharePoint би използвал за да покаже свойте “New”, “Edit” и “Display” форми. Този Web Part върши цялата работа в намирането на точния Rendering Template за текущия Content Type, върху който крайният потребител иска да работи.

Ето малко код от Reflector… Това е TemplateName, притежанието на този ListFormWebPart, който проверява текущия Content Type и връща името на конфигурирания Rendering Template.

image

Това ни води до следващата опция:

Вариант 2: Да посочим името на Rendering Template чрез код.

Кода е много прост (: SPContentType обекта открива 3 притежания:

cType.NewFormTemplateName = “MyCustomForm”;
cType.EditFormTemplateName = “MyCustomForm”;;
cType.DisplayFormTemplateName = “MyCustomForm”;
cType.Update(true);

С това ще се постигне същото нещо като Опция 1, но няма нужда от декларативен CAML. Чрез cType.Update(true); изпращаме промените към дъщерни Content Types.

Успех.

Tags: , ,

Bulgarian

Формите на списъци в SharePoint 2007 - как работят те

by Ради Атанасов 7. February 2010 09:05

В този пост разглеждам как работят формите на списъци и Content Types в SharePoint 2007 (в случая WSS v3) и какви са ни възможностите за разширяване и разработка. В тази първа част ще обясня как да използваме наши си ASPX форми, а във втора – как да заменим стандартните Rendering Templates с нови. С втория пост ще сложа и линк към решение с пример за двата варианта.

Когато създадем списък в SharePoint, ние всъщност създаваме копие на базата на съществуващ шаблон – List Template. Тези шаблони са дефирнирани в Features, и всеки Feature с шаблон за списък ще съдържа дефиниращ файл: schema.xml. Този schema.xml може се разгледа за всеки списък, който WSS v3 ни предлага: разгледайте 12\TEMPLATE\FEATURES папката, там има Features като CustomList, ContactList, DocumentLibrary. Всичките имат schema.xml, който дефинира особеностите им.

В края на този XML (CAML) файл може да видим „Form” елемент, който дефинира ASPX страниците, които ще бъдат използвани за списъка, на който схемата принадлежи.

clip_image002

Когато се създава списък, платформата прави копие на файл-а дефиниран в “SetupPath” атрибута на “Form” елемента, и го качва в базата данни с посоченото име в “Url” атрибута. След като страницата е създадена (това е обикновен Web Part Page), SharePoint слага ListFormWebPart в посочения WebPartZoneID. “pages\form.aspx”, и подобни други ASPX страници се намират в 12\TEMPLATE\Pages, и там можете да сложите своите. Горният screenshot е от CustomList, но можете да разгледате и всички останали.

Интересното става, когато Content Types са добавени в списъци. Всеки Content Type може да има свои DisplayForm, EditForm или NewForm зададени, а всеки списък може да има множество Content Types. Съответно за създаването на различен вид съдържание в един списък можете да имате различни форми за различните Content Types – това е много добра гъвкавост. От друга гледна точка, всеки Content Type може да има един и същ интерфейс (форма) навсякъде, когато е използван многократно.

Как работи всичкото това зад сцената?

В SharePoint SPContentType обектът ни позволява да му зададем EditFormUrl, DispFormUrl, и NewFormUrl (притежания):

cType.EditFormUrl = "_layouts/ourprojectfolder/customedit.aspx";

cType.NewFormUrl = "_layouts/ourprojectfolder/customnew.aspx";

cType.DisplayFormUrl = "_layouts/ourprojectfolder/customdisplay.aspx";

Ако тези са дефинирани от нас, SharePoint прави следното:

· С избирането на “New” бутона или съответните опции от менюто на всеки ред в списъка, SharePoint ни праща на EditForm.aspx, NewForm.aspx или DispForm.aspx според избора.

· Когато създава списъка, платформата конфигурира ListFormWebPart на всяка от тези ASPX страници (откопирани са от Pages\form.aspx). WebPartZoneID атрибута определя къде точно да се добави този Web Part. Тези страници не могат без този Web Part – SharePoint се оплаква ако се опитате да го насочите към страница без ListFormWebPart.

· Този ListFormWebPart проверява текущия SPControlMode (Edit, New, Display), и дали съответното притежание (EditFormUrl, DispFormUrl, или NewFormUrl) на текущия Content Type е зададен. Логиката може да бъде проследена ако разгледаме кода на този web part – в OnInit метода се прави проверка на притежанието this.FormPageUrl, което всъщност е obfuscated и не мога да ви го покажа.

clip_image003

Независимо дали е зададен от нас или не (EditFormUrl, DispFormUrl, или NewFormUrl), SharePoint ни праща към съответната страница - NewForm.aspx, EditForm.aspx или DispForm.aspx. На тези страници ListFormWebPart проверява текущия Content Type (всеки List Item в SharePoint има зададен Content Type) и ни препраща към съответната форма (ако тя е зададена от нас). this.FormPageUrl определя коя е тя на база на текущия SPControlMode (New, Edit, Display), но не мога да ви покажа кода на this.FormPageUrl защото е obfuscated. Така всъщност става конфигурирането на поризволни форми.

Проблемът на този дизайн, е че SharePoint първо ни праща към NewForm.aspx (или една от другите) и след малко код отново ни препраща чрез SPUtility.Redirect (което зад сцената е по-украсен Response.Redirect). Това са два post-back-a, и можете да ги проследите с Firebug или Fiddler, или който и да е друг HTTP listener. Освен, че препратките са две, NewForm.aspx е Web Part Page, а те не са хич леки.

Това, което все още не знам е как да конфигурираме EditFormUrl, NewFormUrl или DispFormUrl в схемата на ContentType елемента (чрез CAML). Примерът по-горе е чрез код и обектния модел, но той не е идеален за всички случаи. В WSS v3 “Form” елемента е “obsolete”, така че начина, по който го правихме в WSS v2 е вече невалиден. Втория ни вариант всъщност е да работим с XmlDocuments елемента в CAML – той ни позволява да сменим съответния Rendering Template на формата. Така става чрез CAML, но двата метода работят по коренно различен начин.

Във втората част на този пост ще разгледам как да заменим стандартните Rendering Templates с произволни, и съответно алтернативния вариант да разширяваме формите на списъци и Content Types.

Надявам се това ще помогне на някой.

Tags: , ,

Bulgarian

CKS: Development Tools - Съвместни усилия за нашето community

by Ради Атанасов 28. January 2010 08:14

С появата на Visual Studio 2010 Beta и вградените инструменти за разработване на SharePoint решения, някои активни представители на SharePoint dev общността се съюзиха да съставят extensions за VS, които улесняват нашата работа. Това, което MS предлага, е много добро и страхотно подобрение от инструментите за SP 2007, но винаги има и място за допълнение от community-тo.

Community Kit for SharePoint: Development Tools Edition е колекция от новите open-source инструменти събрани в едно. Waldek Mastykarz е много активен блогер, MOSS MVP и страхотен SharePoint dev, който много уважавам. Wouter van Vugt е човека, който ми предаде материала за SP Ignite Training 2010 и ме подготви да се кандидатирам като потенциален преподавател за България. Очаквам само добри неща от тези хора, и разбира се от останалите, които допринасят за CKS: Development Tools.

Линк: Community Kit for SharePoint: Development Tools Edition (CKS:DEV)

(Благодаря на Веско за проверката!)

Tags: ,

Bulgarian

About the author

Аз съм консултант, архитект и разработчик на SharePoint решения.

Feeds

Get RSS Feed (Bulgarian)
Get RSS Feed (English)    
Get RSS Feed  (Both)        


Abilitics