Monday, June 22, 2009

Sharepoint 2010 (#14) - Some goodies for us designers

SharePoint 2010 will not support Internet Explorer 6 (more info). So, what this means to us designers is that we won't have to bow down to the confines of IE6's lack of modern CSS layouts. We can use things like .myCSS TD:first-child which is only supported in IE7+ (for IE -- FireFox and others support this).

Another feature that we'll be sure to use and hack the styles of are the the Web-enabled Ribbon control. I'm sure that we'll be pushing the limits to make these ribbons do our bidding in our SP 2010 sites.

Cheers.

Sunday, May 17, 2009

Designing for SharePoint (Indy Code Camp Presentation)

I was excited to see a great turnout this weekend for Indy Code Camp (and even more for my presentation :) ). In my presentation, "Designing for SharePoint", I talked about taking a Graphic Design and converting it into a Master Page, Page Layouts and Web Parts to get the vision of the company. Below are some notes and links to sites that should be useful for those looking to follow the same pattern.

Graphic Designs

If you're a designer, you probably already have a graphics program that you use for your designs, but if you are not, then you probably would like some guidance in this area. My preference is Adobe Fireworks which I have used for many years, back when the product was owned by Macromedia. Fireworks is geared for developing graphics for web sites, and can also be used for dealing with photo images, etc. Adobe Photoshop is another graphics program that is more powerful and more expensive than Fireworks. This program is more useful for photo editing and effects, than being geared for the web.

Master Pages

Master Pages: Love them, hate them -- either way they are an intregal part of SharePoint. You need to develop these bad boys so that the top Internet Browsers will show the SharePoint site the same way (for the most part). So, either start with the default.master (can be found by connecting to the SharePoint site via SharePoint Designer, then navigate to _catalogs/masterpages/ directory). WSS will just have the one master page "default.master" and MOSS will have multiple master pages.

Heather Solomon (SharePoint Design Guru) has created a minimal master page. You can download it to start out your new master page. Remember that you will want to keep a hold of all the Content Place Holders of the master page. If you are not going to use them, just put them in a hidden ASP:Panel.

Other parts of the master page that you will want to pay attention to are:

  • Welcome Bar (My Site / My Links / Site Actions button)

  • Main Navigation (this can be replaced with a Telerik RAD menu for instance)

  • Publishing Console (if using MOSS)

  • Quick Navigation Menu (used as the vertical navigation bar -- usually MOSS sites hide this)



  • Page Layouts

    Page Layouts can also be found in the folder _catalogs/masterpages and are identified by the .ASPX file extension. Page Layouts inherit from a master page, and control structure of Web Part Zones AND are tied to a specific Content Type (Welcome, Article, etc., or a Custom Content Type). These are pretty straight forward as they are a mix of HTML and Sharepoint controls. You can create many page layouts for your SharePoint sites.


    Modifying Out of the Box (OOTB) Web Parts

    This is one of those things that gets debated by SharePoint developers as to the true use of OOTB Web Parts. Some purists believe that custom web parts should be left to only .NET web parts. Depending on the needs of the web part, .NET could be the way to do. However, if you are looking to extend a web part that can be mostly handled by modifying a DataFormWebPart in SharePoint Designer, this can cut way down on time and frustration from NOT having to develop a .NET web part.

    Here is a quick list of how you create and modify an OOTB Web Part to do your bidding on SharePoint.

    1) Open SharePoint Designer and connect to your SharePoint site

    2) Click on File > New and create a new .ASPX page that inherits from your Master Page

    3) In the new page, go into the code view and create a new <DIV> tag (for Table)

    4) (In Design View) Click in the center of your new tag so the cursor is within your tag

    5) Click on Insert > SharePoint > Web Part Zone (must be in Design View)

    6) Click on DataFormWebPart > Insert to insert a new DataFormWebPart

    ... Follow the instructions on connecting to the datasource in SharePoint Designer

    7) If you want to add columns, you can by right-clicking on any of the column headers you want, and choosing to insert a column to the right or left

    8) At this point, before you do anything else, you should hop in the code and look for "ListID" and replace this with "ListName". Also, you will want to find the corresponding "ListID" "Guid" and replace this with the actual list name. Doing this will ensure that this web part can be deployed across different environment whereas a ListID and Guid would fail.

    9) Click in the header of the web part so it's all highlighted

    10) Click on File > Export > Save Web Part > To Site Gallery (this will import the current web part into the Site Gallery on your SharePoint server -- it puts it in the "Miscellaneous" category by the way)

    That's it. If you have any questions, feel free to contact me.

    :)

    Thursday, April 2, 2009

    Filter Current User for Document Library in a CAML Query

    I had a situation where I needed to create a web part that searched all of the Document Libraries of a SharePoint site, and then gave the option to filter the list by the current user logged onto the site (similar to the "Relavent Documents" OOTB Web Part).

    Anyways, the CAML Query is simplistic in nature, but was kind of a pain to reach this conclusion since most of what you will find on the Web is using the "AssignedTo" Field name to match against the current user. The key internal name field for a Document Library to use is "Editor".

    Anyways, here is the "Where" clause I used to hit against the Document Libraries:

    SPSiteDataQuery q = new SPSiteDataQuery();

    q.ViewFields = "<FieldRef Name=\"FileRef\" /><FieldRef Name=\"ID\" /><FieldRef Name=\"Modified\" /><FieldRef Name=\"Modified_x0020_By\" />";
    q.Query = "<Where><Eq><FieldRef Name=\"Editor\" /><Value Type=\"User\"><UserID/></Value></Eq></Where><OrderBy><FieldRef Name=\"Modified\" Ascending=\"False\" /></OrderBy>";
    q.RowLimit = 10;
    q.Webs = "<Webs Scope=\"Recursive\" />";
    q.Lists = "<Lists ServerTemplate=\"101\"/>";

    SPWeb Collection: List Sites / Webs

    I had an opportunity recently to make a web part that is like a site map to the entire site collection no matter where it was dropped on the SharePoint site. I also made an option (not shown in code) that allows the "default starting site/web" to be overridden so that you can start from any site/web node and then show recursive webs from there.

    Enough talk, here's the code:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebPartPages;
    using Microsoft.SharePoint.Utilities;
    using System.Data;

    namespace JamesCurtis.SharePoint.Examples
    {
    public class SPWebCollectionExample : Microsoft.SharePoint.WebPartPages.WebPart
    {
    #region Constants

    #endregion

    #region Fields

    Label lblDisplay = new Label();
    Label lblError = new Label();
    StringBuilder sb = new StringBuilder();

    #endregion

    #region Delagates

    protected override void CreateChildControls()
    {
    try
    {
    base.CreateChildControls();

    lblDisplay.Text = GetData(SPContext.Current.Site.Url);
    this.Controls.Add(lblDisplay);
    }
    catch (Exception ex)
    {
    lblError.Text = ex.Message;
    this.Controls.Add(lblError);
    }
    }

    #endregion

    #region Private Methods

    protected string GetData(string site)
    {
    using (SPSite s = new SPSite(site))
    {
    SPWebCollection swc = s.AllWebs;
    for (int i = 0; i < swc.Count - 1; i++)
    {
    sb.Append(SPEncode.HtmlEncode(swc[i].Url));
    sb.Append("<br/>");
    }
    }
    return sb.ToString();
    }

    #endregion

    }
    }

    Happy Programming!

    Friday, February 27, 2009

    RAID Controller Not Initializing on boot after restart

    I ran into an interesting issue with an older Dell server that I have. I tried to add some RAM to it, and one of the RAM sticks ended up being bad, but in the process of trying to boot up, it seems to have tried to load the BIOS information, but then failed when it hit the bad RAM.

    So, what it did, was reset the BIOS! I didn't figure this out at first because I was getting nervous that the server would skip over the normal "Controller 0... Initializing..." part and then fail because it couldn't find a boot device.

    The fix:

    1) Start the Server

    2) Go into SETUP

    3) Go to INTEGRATED DEVICES

    4) Look for the SCSI Setup (was on the top of the window in my screens)

    5) Set the value to SCSI or RAID, depending on your setup

    6) Exit and Save from the BIOS

    Hopefully, if you situation is the same, this will fix it. :)

    Wednesday, February 18, 2009

    SQL Reporting Services - Service Unavailable

    There you are, happy and excited that you are about to start using SQL Reporting Services, and then it happens... you navigate to your report server (typically http://localhost/Reports) and you get an ugly error "Service Unavailable".

    The good news is that it's probably just a quarky .NET 2.0 install that is messing it up. If it is, here's how to easily reinstall .NET 2.0 to make IIS happy:

    1) Go to C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ and copy the path in the "address bar" in Windows Explorer

    2) Go to Start > Run and type in CMD

    3) In the Command Window, type: cd (and then with your mouse, right-click on the window and then "Paste") -- the end result should be "cd C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727"

    4) Type: aspnet_regiis -i and hit [enter]

    These steps will reinstall .NET 2.0 and should fix the Service Unavailable error.

    Friday, January 16, 2009

    SubSonic versus LinqToSQL: Simple Delete

    Continuing the series, SubSonic versus LinqToSQL, this example shows a simple delete using SubSonic and then the equivalent using LinqToSQL. It is worth to note that SubSonic has two ways to delete records, on just updates a bit field called "IsDeleted" and essentially turns the record "off" while the "Destroy" method actually deletes the record.

    If you are looking for other posts in this series, here is the list:

  • SubSonic versus LinqToSQL: Simple Select

  • SubSonic versus LinqToSQL: Simple Insert

  • SubSonic versus LinqToSQL: Simple Update

  • SubSonic versus LinqToSQL: Simple Delete


  • Here is the simple delete using SubSonic:
    using SubSonic;
    using MyCustomDAL;

    ...

    protected void DeleteProduct(int ProductID)
    {
    Product p = new Product(ProductID)
    p.Destroy();
    }

    And here is the simple delete using LinqToSQL:
    using System.Linq;

    ...

    protected void DeleteProduct(int ProductID)
    {
    NorthwindDataContext db = new NorthwindDataContext();

    Product p = (from products in db.Products
    where products.ProductID == ProductID
    select products).FirstOrDefault();
    db.Products.DeleteOnSubmit(p);
    db.SubmitChanges();

    }