1
Reza Alirezaei , SharePoint MVP /MCTSDevelopment Horizon, Corp.http://blogs.devhorizon.com/rezaTwitter: rezaal
Turning Chaos into Order: Best Practices for Developing
SharePoint Applications
2
AgendaConfigurationList RepositoriesPerformanceSecuritySome Architectural Decisions
Good Understandings of SharePoint DevDefinitely Not a 101 session
Prerequisites
3
Why do I care?
Anti best practices:
“I suppose it is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail.”
Abraham Maslow
4
Most common solutions:SPWebConfigModification class SharePoint ListConfiguration From Web Services Property bags (SPWebApplication.Properties)Hierarchical Object Store (HOS) – See SharePoint P&P RI
SPWebConfigModification’s Top 6 Issues http://www.devhorizon.com/go/103
Scope at Web Application, not Site collection
Note: Persisted attributes in SPPresistedObject class as BLOB XML and its too easy to corrupt then by storing a non-serializable complex type
Configuration Management Strategy
5
DEMO
Hybrid Approach (Property Bag + appsettings)
6
ONLY one slow Web Part…ONLY one slow Process….
Q1) How many Web Parts are on the page? Q2) How many instances of your Web Part are on the page?Q3) Do I need to model this business process within the same application domain as the current app pool resides?
So, what are my SharePoint innate async options?
Create a Worker class to handle asynchronous code
SPLongOperation Class
Background Processes-ed Event handlersWorkflows
“Execution in Parallel” is King!
7
Workflow or
Event Handler?
Cancel?Event
Receiver
Workflow
HumanInterference
?
Running > 5 min
High Volume Yes
Yes
Yes
Yes
8
DEMO
Asynchronous Dev• Web Part• SPLongOperation
9
MOSS is NOT a Single ApplicationIIS
Custom WPs/Procs
MOSS
WSSCRL/Native APIs
MDAC LDAP
BDC AudienceExcelSrv Forms
CMS Analytics
Search ProfilesAll of these technologies must fit in a single 32-bit process
10
x64 IssuesMany of the current dev tools run in WOWSome tools don’t support x64 bit (STSDEV)Not ISV friendlyVS 2008 WF Templates (Seq and State) not supported
x86 Issues What you saw in last slide + A lot more issues!
Go hybrid & Build “ Any CPU”
11
MSDN Paper http://www.devhorizon.com/go/104 Roger Lamb’s Bloghttp://www.devhorizon.com/go/105
. Net Rule for Disposing Objects
Edge –Cases!!
SPDisposeCheckhttp://www.devhorizon.com/go/106
Memory Leaks
12
Edge Case -1public class MyFeatureRec : SPFeatureReceiver
{
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
//Does the following reference to SPSite leak?SPSite site = properties.Feature.Parent as SPSite;
}}
13
Edge Case -2public class MyClass: SPItemEventReceiver
{
public override void ItemUpdated(SPItemEventProperties properties)
{
//Does the following reference to SPWeb leak?SPWeb web = properties.OpenWeb();
}}
14
Edge Case -3public class MyClass: SPWebProvisioningProvider
{
public override void Provision(SPWebProvisioningProperties props)
{
//Does the following reference to SPWeb leak?SPWeb web = props.Web;
}}
15
My $0.02
Don’t Dispose of Edge Cases
16
DEMO
•SPDisposeCheck•Edge Cases
17
How about this one?
SPWeb oWeb = SPContext.Current.Web;
//Does the following reference to SPSite leak?
SPSite oSite = oWeb.Site;
Say No To Disposing Of objects hanging off SPContext
List Capacity Planning
Working with Large List on MSDNhttp://www.devhorizon.com/go/107
Recap of the MSDN paper on my bloghttp://www.devhorizon.com/go/108
Bottom Line is :2000 items per list limit is ….. SPList w/DataTable or SPList w/for/each ……..Escalation of SQL Server Lock on Lists Table is serious Be cautious about using Collections & Avoid Using
Indexes on each Call
19
Properly Working With Collections
// BAD waySPWeb web = SPContext.Current.Web;string tasksID = web.Lists[“Tasks”].ID;string tasksTitle = web.Lists[“Tasks”].Title;
// GOOD waySPWeb web = SPContext.Current.Web;SPList tasksList = web.Lists[“Tasks”];string tasksID = tasksList.ID;string tasksTitle = tasksList.Title;
20
What is wrong with this code?
SPList bigList = web1.Lists[“BigList”];
foreach(SPListItem item in bigList.Items){
if(item[“MyColumn”] == “Foo”){
Console.WriteLine(“Found One!”);
}}
21
SPList.Items gets a collection with ALL list itemsTerrible for big listsLots of memory neededLots of SQL I/OLots of networkLots of CPU
Instead use SPList.GetItemsTakes a CAML query
Working with SPListSay No To
22
Accessing SharePoint List Items Patterns The Direct Object Model Calls(0):
With ZERO intervening layers of abstraction.
The List Item Repository Pattern (1):This pattern abstracts calls to SharePoint lists. It uses a programmer-provided repository class (ListItemRepository ).
The Entity Repository Pattern (2):This pattern provides two abstraction layers. It usesbusiness entities and a ListItemRepository class.
23
Adding an item to a List using Direct Object Model Calls
SPList list = web.Lists[Lists.Announcements];
SPListItem item = list.Items.Add();item[“Title”] = "Direct List Data Access";item[“Body”] = "Item added using Direct Access Pattern.";
////allow updates to the database as a result of a GET request or without requiring a security validation
web.AllowUnsafeUpdates = true;item.Update();web.AllowUnsafeUpdates = false;
id = item.ID;
24
Adding an item to a List using List Item Repository Pattern
ListItemRepository listItemRepository = new ListItemRepository();
Dictionary<Guid, object> fields = new Dictionary<Guid, object>();
fields.Add(Fields.Title, "ListItemRepostitory Data Access");fields.Add(Fields.Body, "Item added using ListItemRepostitory Data Access.");
SPListItem item2 = listItemRepository.Add(web, Lists.Announcements, fields);
25
Adding an item to a List using Entity Repository Pattern
AnnouncementRepository announcementRepository = new AnnouncementRepository();
Announcement announcement = new Announcement() { Title = "AnnouncementRepository Data Access", Body = "Item added using AnnouncementRepository." };
id = announcementRepository.Add(announcement, web);
26
What is wrong with this code?
SPList bigList = web1.Lists[“BigList”];
foreach(SPListItem item in bigList.Items){
if(item[“MyColumn”] == “Foo”){
Console.WriteLine(“Found One!”);
}}
27
Adding an item to a Listusing Entity Repository Pattern
//BigList access code refactored using repositoryBigListRepository bigListRepository =
new BigListRepository();
BigListItem bigListItem =bigListRepository.GetByMyColumn(“Foo”);
if (bigListItem != null) Console.WriteLine(“Found One!”);
28
Entity Repository Pattern
Custom Business
Logic
CRUD OperationsStrongly Typed Business Entities Repository CRUD Operations
SPListItem
SharePoint Lists
29
Quiz: Entity Repositories
Question: Why in the world do I need to create repositories on top of SharePoint lists?
a) Maintainability b) Reusabilityc) Testability (Substitutability)d) I don’t want to rely it on Web Part devs to
decide how to access Listse) All of the above
30
DEMO
•Accessing SharePoint List Items Patterns
Aggregation ScopeInformation ScopePerformance CharacteristicsAccuracy (Latency)
Aggregating Site and List Information
Direct cross-site collection querySearch API (FullTextSqlQuery Object)
Aggregation Scope = Site Collection :Content Query Web Part (QueryOverride Prop) PortalSiteMapProvider Class
Primarily used for navigation controlsOptimized to query data not only across lists,but across websScope limited to the current site collectionImportant: Not good for infrequent queries or frequently changed dataImportant: MOSS Only
Techniques for Aggregating Site and List Information
33
Options for Querying SP Data
SPLis
t w/ D
ataTab
le
SPLis
t w/ f
or/eac
h
Browse
r view
Lists.
asmx
SPLis
tItem w
/ Data
Table
SPLis
t w/ S
PQuery
Searc
h
PortalSi
teMap
Provid
er
201622
145552
3585 392 339 327 327 40
List with 100,000 items, Page Size of 100 Items, no Indexed Columns, Site Under Load
milliseconds
34
DEMO
•Aggregating Site and List Information
35
THINK SHAREPOINT
Last but certainly not least:
http://blogs.devhorizon.com/reza