Clinton's profileCherry BytesBlogListsGuestbookMore ![]() | Help |
|
October 26 Flushing out the cache in SharePointSharePoint under the covers can do a lot of caching to optimize the rendering and loading time of pages. Using preferences in SharePoint, you can optimize this using several properties, including the size of the object cache, when to check the server for changes in the cache, and what to cache. One item SharePoint often seems to cache is the style sheets (which is quite useful) except when you want update or change them. This can prove quite annoying as your changes to the style sheet don't seem to be reflected immediately on the site, leaving you questioning whether you have not updated them correctly. To get around such a problem, there is the facility in SharePoint to easily reset (flush) the cache using the Object Cache Settings page.
As soon as you do this, you will find the cache is reset, and all the latest changes will now be reflected on your SharePoint site! October 19 How Reflector saved my life (...well not really, but it did save me a lot of pain)I am not sure how many people out there use Reflector for various purposes. I think it is a fantastic tool that enables you to decompile, analyse and view the contents of a particular assembly - essentially to see what's going on 'under the covers'. Obviously there are some ethics to what extent you use the tool to steal other company and people's intellectual property, however if you are a developer and haven't had a look at it, I would highly recommend it. Today though it saved me an enormous amount of heartache and pain. I have spent the last couple of weeks tirelessly working on a piece of code, which I have neglected to check in to source control for a couple of days. Anyway, I had a successful build today so I thought it was time to check it in. Because of my own stupidity (more than anything), whilst trying to get the latest version of the project (before checking in my code), I managed to write over the top of ALL my NEW code with the version from source control. So this basically meant my entire project went back to Wednesdays version. And there was no way to recover it, because Wednesday was the last time I used source control. Enter Reflector stage right. Because I had been regularly compiled my assembly, I did have my latest code 'hidden' away in a dll. I was able to use Reflector to reverse engineer the assembly, getting the LATEST version of my code, which I could then use to update Wednesday's version of my code. While this did take about 30 minutes, it saved me about 20 hours of rewriting all my code. More importantly it averted a heart attack I almost had when I realised what I had done (with a serious deadline looming)! October 17 Creating Dynamic Images using SharePointAn interesting task I recently have done in SharePoint was to dynamically create some images using the System.Drawing.Image object, then display them on a SharePoint page. I wanted to keep all my development within SharePoint, so this gave me quite a tough task to do. In the past when I have come to a similar problem I have used the Response object in a different page to render the content out as a image type to the screen. What I ended up doing for SharePoint was to create the image using the SharePoint WebPart, then copy this object into the Cache. ie //Create the image System.Drawing.Image img = System.Drawing.Image.FromStream(BOToGenerateStreamOfGraphic()); //Save it to the cache HttpContext.Current.Cache.Insert(imageName, img, null, DateTime.MaxValue, Once I have the object in the cache, I now need a separate page to render the graphic. I created a custom page 'customimage.aspx' (this arguably could be an .ashx page), which I deploy to the _Layouts folder of SharePoint, which gets the cache image, and flushes this out as an image. ie // Change the response headers to output a JPEG image. HttpContext.Current.Response.Clear(); HttpContext.Current.Response.ContentType = "image/jpeg"; System.Drawing.Image OC = null; //Build the image if (HttpContext.Current.Cache[imageName] != null) { img= (System.Drawing.Image)Context.Cache[imageName]; // Write the image to the response stream in JPEG format. img.Save(HttpContext.Current.Response.OutputStream, ImageFormat.Jpeg); img.Dispose(); } Once the Image is available it is just a matter of referencing the 'custompage.aspx' folder from my web part. One other point I realised was that when referencing the _Layouts folder, a relative link needed to be used (ie had to use '../_Layouts/Custompage.aspx' rather than '/_Layouts/CustomPage.aspx') otherwise the Context of the cache is lost, and no image will appear. I found a similar implementations of this here and here which also give some really good information on dynamic images in SharePoint. There is also a good article on the MDSN site for creating IHTTPHandlers, which is another way of achieving this task. October 16 Firing Events in Custom Web ControlsOf late I have been writing a number of custom controls in .NET. I really like custom web controls and find that they are a great reusable item if written correctly. Unlike a standard ASP.NET custom control, you don't get the luxury of adding your controls visually to the .ascx page, you have to programmatically add and render every control which makes up your control. However, if you do spend a little bit of extra time doing this, it means you get a compiled assembly with your control/s in it, which can easily be referenced by any project, and easily reused. However, the biggest headache I have come across when creating these custom controls, is that Events from existing controls never seem to work. The (very simple) solution is that you have to implement the INamingContainer Interface in order for these events to work. Simply add this and everything works ie: [ToolboxData("<{0}:MyCustomControl runat=server></{0}:MyCustomControl >")] public class MyCustomControl : WebControl, INamingContainer { protected override void OnInit(EventArgs e) { AnExistingControl.CheckedChanged += new EventHandler(AnExistingControl_CheckedChanged); //Other init code... }protected void AnExistingControl_CheckedChanged(object sender, EventArgs e) { //Now this will actually work... } } If you want more info on writing composite custom controls, there is a great article on the Code Project on Managing ViewState, Rendering and Events in Composite Custom Server Controls. October 15 Querying items in a SharePoint ListWhen querying a list in SharePoint, the SPList.GetItems method is a simple and relatively easy way to return a list of records from the SharePoint List (returned as a SPListItemCollection). This is implemented simply as follows:
As you progress a bit, you will find that you won't necessarily want to return all the items in a list. That's when using the SPQuery object comes in real handy. Simply write the CAML query for the code that you wish to return, then pass the SPQuery object to the GetItems method. This should then return the exact subset of data that you were after. ( using (SPWeb currentWeb = currentSite.OpenWeb(_RelativeWebUrl)) { SPList currentList = currentWeb.Lists[_ListName]; SPQuery query = new SPQuery(); query.Query = String.Format("<Where><Eq><FieldRef Name=\"{0}\" /><Value Type=\"{1}\">{2}</Value></Eq></Where>",_InternalName, _Type,_Value); SPListItemCollection items = currentList.GetItems(query); } HOWEVER, you must be careful that you write your CAML code correctly, or the method will return all records! This really surprised me and is a strange 'feature' one would think - I personally would have thought this should have returned NO records if it the query was incorrect. So basically if you find that every time you run a query there is a full record set returning, then check your CAML query... For testing or writing your CAML queries, I would recommend downloading and trying out the U2U CAML Query Builder - this is a great little tool. October 09 Programmatically running a User Profile ImportThe User Profile Database in SharePoint is a great centralised location for storing all the information about the users of your SharePoint Portal. This can be anything from their phone number, to their photo through to information about them for their CV. I find it a very useful part of SharePoint, and leverages a lot of features in SharePoint which can be used for social and business networking via SharePoint. In order to get information into the User Profile Database, a nightly job can be setup which imports user information out of Active Directory - which is where most of this information should reside anyway. In the current project I am working on, we importing information from various applications into Active Directory (ie from Human Resource Applications) where it is initially added, then after this is imported into Active Directory, we are then using the built in import tool in SharePoint to populate this information into the SharePoint User Profile database so that this information can be used for user searches, organizational hierarchy and on the My Site pages. However, as these imports are happening using a BizTalk orchestration, we wanted to manually kick off the import in the code ourselves. Bring on the UserProfileConfigManager class. This class makes doing these imports an absolute cinch. Simply create a new instance in the current context, then you can easily kick off an import! If only everything was this easy!! UserProfileConfigManager upcm = new UserProfileConfigManager(serverContext); if(!upcm.IsImportInProgress) upcm.StartImport(true); October 03 Weird Content Controls error in custom SharePoint Page LayoutsPage Layouts are a great feature in SharePoint 2007 that allow you to help you dictate the overall look and feel of a web page. You can have several different page layouts for a site, with each one offering different ways of displaying content to the viewers. Up until recently I was manually uploading my page layout files into the Master Page and Page Layout gallery in SharePoint, however I recently decided to automate this process by using solutions and features to deploy the page layouts. However, as soon as I uploaded one of my Page Layouts using the feature, I suddenly got the following error on a number of the pages in my site: Server Error in '/' Application. Parser Error Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately. Parser Error Message: Only Content controls are allowed directly in a content page that contains Content controls. Source Error: Line 80: </table> Line 81: </asp:content> Line 82: <html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010- 5B3-11d1-A29F-00AA00C14882"><head> Line 83: <!--[if gte mso 9]><xml> Line 84: <mso:CustomDocumentProperties> This error really confused me. If I opened the page layout using SharePoint Designer, I found that the file was appending the additional <html> information to the end of my page layout page – this was definitely not in my original file. If I manually deleted this using SharePoint Designer then everything worked fine. This was all well and good, however I really wanted to have this automatically uploaded with no manual intervention. Luckily I came across this post here by Rich Finn. It turns out the error is because I have used a lower case </asp:content> tag at the end. By changing this to </asp:Content>, and then redeploying the solution, my problem was instantly solved. |
|
|