350 likes | 480 Views
Turning Chaos into Order: Best Practices for Developing SharePoint Applications. Reza Alirezaei , SharePoint MVP /MCTS Development Horizon, Corp. http://blogs.devhorizon.com/reza Twitter : rezaal. Agenda. Configuration List Repositories Performance Security
E N D
Turning Chaos into Order: Best Practices for Developing SharePoint Applications Reza Alirezaei , SharePoint MVP /MCTS Development Horizon, Corp. http://blogs.devhorizon.com/reza Twitter: rezaal
Agenda • Configuration • List Repositories • Performance • Security • Some Architectural Decisions Prerequisites • Good Understandings of SharePoint Dev • Definitely Not a 101 session
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
Configuration Management Strategy • Most common solutions: • SPWebConfigModification class • SharePoint List • Configuration 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
DEMO • Hybrid Approach (Property Bag + appsettings)
“Execution in Parallel” is King! • 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 handlers • Workflows
Yes Event Receiver Cancel? Workflow or Event Handler? Human Interference? Workflow Yes Running > 5 min Yes High Volume Yes
DEMO Asynchronous Dev • Web Part • SPLongOperation
MOSS is NOT a Single Application IIS Custom WPs/Procs MOSS All of these technologies must fit in a single 32-bit process Search Profiles Audience BDC Forms ExcelSrv Analytics CMS WSS CRL/Native APIs MDAC LDAP
x86 Issues x64 Issues • What you saw in last slide + A lot more issues! • Many of the current dev tools run in WOW • Some tools don’t support x64 bit (STSDEV) • Not ISV friendly • VS 2008 WF Templates (Seq and State) not supported Go hybrid & Build “ Any CPU”
Memory Leaks • MSDN Paper http://www.devhorizon.com/go/104 • Roger Lamb’s Blog http://www.devhorizon.com/go/105 • . Net Rule for Disposing Objects • Edge –Cases!! • SPDisposeCheck http://www.devhorizon.com/go/106
Edge Case -1 public class MyFeatureRec : SPFeatureReceiver { public override void FeatureActivated(SPFeatureReceiverProperties properties) { //Does the following reference to SPSite leak? SPSitesite = properties.Feature.Parent as SPSite; } }
Edge Case -2 public class MyClass: SPItemEventReceiver { public override void ItemUpdated(SPItemEventProperties properties) { //Does the following reference to SPWeb leak? SPWebweb = properties.OpenWeb(); } }
Edge Case -3 public class MyClass: SPWebProvisioningProvider { public override void Provision (SPWebProvisioningProperties props) { //Does the following reference to SPWeb leak? SPWebweb = props.Web; } }
My $0.02 • Don’t Dispose of Edge Cases
DEMO • SPDisposeCheck • Edge Cases
How about this one? SPWeboWeb = SPContext.Current.Web; //Does the following reference to SPSite leak? SPSiteoSite = oWeb.Site; Say No To Disposing Of objects hanging off SPContext
List Capacity Planning • Working with Large List on MSDN http://www.devhorizon.com/go/107 • Recap of the MSDN paper on my blog http://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
Properly Working With Collections // BAD way SPWeb web = SPContext.Current.Web; string tasksID = web.Lists[“Tasks”].ID; string tasksTitle = web.Lists[“Tasks”].Title; // GOOD way SPWeb web = SPContext.Current.Web; SPListtasksList = web.Lists[“Tasks”]; string tasksID = tasksList.ID; string tasksTitle = tasksList.Title;
What is wrong with this code? SPListbigList = web1.Lists[“BigList”]; foreach(SPListItem item in bigList.Items) { if(item[“MyColumn”] == “Foo”) { Console.WriteLine(“Found One!”); } }
SPList.Items gets a collection with ALL list items Terrible for big lists Lots of memory needed Lots of SQL I/O Lots of network Lots of CPU Instead use SPList.GetItems Takes a CAML query Working with SPList Say No To
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 uses • business entities and a ListItemRepository class.
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;
Adding an item to a List using List Item Repository Pattern ListItemRepositorylistItemRepository = newListItemRepository(); 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);
Adding an item to a List using Entity Repository Pattern AnnouncementRepositoryannouncementRepository = newAnnouncementRepository(); Announcementannouncement = newAnnouncement() { Title = "AnnouncementRepository Data Access", Body = "Item added using AnnouncementRepository." }; id = announcementRepository.Add(announcement, web);
What is wrong with this code? SPListbigList = web1.Lists[“BigList”]; foreach(SPListItem item in bigList.Items) { if(item[“MyColumn”] == “Foo”) { Console.WriteLine(“Found One!”); } }
Adding an item to a Listusing Entity Repository Pattern //BigList access code refactored using repository BigListRepositorybigListRepository = newBigListRepository(); BigListItembigListItem = bigListRepository.GetByMyColumn(“Foo”); if (bigListItem != null) Console.WriteLine(“Found One!”);
Quiz: Entity Repositories Question: Why in the world do I need to create repositories on top of SharePoint lists? • Maintainability • Reusability • Testability (Substitutability) • I don’t want to rely it on Web Part devs to decide how to access Lists • All of the above
DEMO • Accessing SharePoint List Items Patterns
Aggregating Site and List Information • Aggregation Scope • Information Scope • Performance Characteristics • Accuracy (Latency)
Techniques for Aggregating Site and List Information • Direct cross-site collection query • Search API (FullTextSqlQuery Object) Aggregation Scope = Site Collection : • Content Query Web Part (QueryOverride Prop) • PortalSiteMapProvider Class • Primarily used for navigation controls • Optimized to query data not only across lists,but across webs • Scope limited to the current site collection • Important: Not good for infrequent queries or frequently changed data • Important: MOSS Only
DEMO • Aggregating Site and List Information
Last but certainly not least: THINK SHAREPOINT http://blogs.devhorizon.com/reza