Sharepoint

HumblePie

Lifer
Oct 30, 2000
14,665
440
126
So I just moved over to a sharepoint job and frankly, don't know much about it. They knew that and still hired me because as a programmer I am damn good. I'm also fast at learning things. My problem is when I need to do something very specific and can't find any information I need. Either because it doesn't exist or I'm looking in the wrong place.

So right now I have some requirements I need to fill. I'm pretty much given creative choice in how to accomplish the requirements to a degree so I'm trying to ascertain the best method to do so. Here is what I have to do.


I need to create a webpage that can access sharepoint in who is currently authorized to view the page. I need to create a form that pulls information from a sharepoint list. Based off the person looking at the page, depends on whether they have the ability to change the information pulled from the sharepoint list and update the list what any changes they may type in.

I was kind of envisioning a form page of some sort similar to how a message board sort of works. Basically the page layout displays the data from the sharepoint list. If they are an acceptable user then they get access to a "edit" button. If the edit button appears they get access to a rich edit field box of some sort. They also need the ability to create hyper link items they type in similar to BBC code with url="www.google.com" My link /url stuff.

I was told to look into using infopath to create the form and then put the form into a sharepoint web part and "link" it all up. This might work, but I have no clue where to start finding the information for doing this. Anyone have any thoughts or links to a tutorial doing exactly this or damn close to what I want to accomplish?
 

Gunslinger08

Lifer
Nov 18, 2001
13,234
2
81
Your requirements are a little confusing, but it sounds like you could either use a data form web part (configured through SharePoint Designer) or a ListFieldIterator (in a custom web part). The ideal thing when working with SharePoint is to use as much out of the box functionality as possible. With these approaches you don't have to reinvent the wheel. Let me know if you have questions. I'm a full time SharePoint developer.
 

HumblePie

Lifer
Oct 30, 2000
14,665
440
126
Sent you a PM josh, but just incase I'll give a bit more detail.

1) I need to create a form submit page.
2) The form will be able to pull in data from a sharepoint list
3) The form can update or create new data items from that same sharepoint list
4) It needs to be able to authenticate user types so only those that have permission can edit
5) The page is a subpage that is link to by another page.
6) The other page needs to pass tokens or some other sort of information along so that the submit form page knows which data to pull from the sharepoint list.
7) When the form is in edit mode by an authenticated user, the person needs to be able to not only type in plain text but create hyper links.
8) The transformation on the page between viewing only mode and edit mode can not create a popup window or send the user to another page to do the editing. The form control must change from static display to an editable content field.


That is the requirements of what I'm trying to accomplish. I'm trying to find an online tutorial or example doing these things or close to it. I found a few almost similar sites, but damn near everything I try to reproduce doesn't work.

For reference I'm using MOSS 2007 and have Visual Studio 2008 to work with.
 

HumblePie

Lifer
Oct 30, 2000
14,665
440
126
Okay, here are some updates. What is really bugging me about sharepoint is finding an actual working solution for any problem I run into. Anyhow, here is what I've got going on.


I joined a team that is doing work for a customer who has a sharepoint site. They need some pages done and I am tasked with completing a couple of pages. I don't know really anything about sharepoint but I do know web programming, HTML, ASPX, and javascript. I know know quite a bit more Java, VB, C#, and C++ as these are the skills I've been using more often lately although not for web development.

I'm going to keep things a little bit simple here. One page I'm tasked with is creating a table using data from sharepoint lists. That by itself would not be to hard with all the fun controls built into sharepoint. However, they wanted the page to look just like their powerpoint slide with some modifications. That means just about every cell in the table has a special background, icons, formatting, and all sorts of stuff that sharepoint out of the box just doesn't offer. Not to mentioned data pulled from multiple lists but be pre-sorted and matched up with each other and then massaged into an actual HTML displayable format in some cases. Luckily the lists were small in terms of total items in the a given list.

So I started with what I knew. I made a basic ASPX page. In HTML I created a blank table within a form. Although the form wasn't needed because there is no postback with this page as of yet. I originally was in the middle of trying to get a new license for my new machine to install Visual Studio but I didn't exactly have time to wait on the approval process. So I looked into doing everything I could with javascript/ajax instead.

It took me awhile but I ended up finding and figuring out what I needed to do.



Here is the following basic code I came up with to do what I wanted. Basically I create a soap request and send it to one of Sharepoint's 2007 web data service object called lists.asmx.

Code:
function createSoapRequest(listName)
{	
	var soapRequest;
	soapRequest = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
	soapRequest += "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \
				    xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \
				    xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">";
	soapRequest += "<soap:Body>";
	soapRequest += "<GetListItems xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\">";
	soapRequest += "<listName>" + listName + "</listName>";
	soapRequest += "</GetListItems>";
	soapRequest += "</soap:Body>";
	soapRequest += "</soap:Envelope>";
	
	return soapRequest;
}

function getListItems(listName)
{
	var xmlhttp = new XMLHttpRequest();
	var soapRequest = createSoapRequest(listName);
	
	xmlhttp.open("POST", "_vti_bin/lists.asmx?op=GetListItems", false);
	xmlhttp.setRequestHeader("Content-Type","text/xml; charset=utf-8");
	xmlhttp.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/GetListItems");
	xmlhttp.setRequestHeader("Content-Length", soapRequest.length);
	xmlhttp.send(soapRequest);
	
	// Un comment the alert below for debugging
	//alert(xmlhttp.responseText);
	
	return (xmlhttp.responseXML);
}

function getListItems(nameOfList)
{
	var xmlDoc = new XMLHttpRequest();
		
	xmlDoc = getListItems(nameOfList);

        return xmlDoc;
}

This is pretty simple code but it took me awhile to figure out. Basically I ask the lists.asmx object to give me all the items of a list based on the name of the list. I could have also used the internal GUID assigned to that list, but this is much simpler if your lists have strong naming conventions anyhow.

So I use the above code to grab data from various lists based off the name of the list I provide. Then I pull out the fields from the data I really need. All the fields start with "ows_" So here is the code I used to build an array with parsed data returned from a sharepoint list.


Code:
function getDatalist(xmlDoc, fieldsToUse)
{
	var dataList = new Array();
		
	// The items are returned in the node 'z:row', so we grab this.
	var xmlNode = xmlDoc.getElementsByTagName("z:row");
	
	// allocate the multi dimensional array
	for (i = 0; i < xmlNode.length; i++)
	{
		dataList[i] = new Array(fieldsToUse.length);
	}
	
	// Now we work through the children of the z:row node to grab the required data.
	for (i = 0; i < xmlNode.length; i++) 
	{
		// Loop through the current zrow node for all the field columns to use
		for (j = 0; j < fieldsToUse.length; j++)
		{
			dataList[i][j] = xmlNode[i].getAttribute(fieldsToUse[j]);
		}
	}
	
	return dataList;
}

// xmlDoc was the xml response returned from the function getListItems
function buildDataList(xmlDoc) 
{
        var fieldsToUse = new Array();

	fieldsToUse[0] = "ows_Title";
	fieldsToUse[1] = "ows_Definition";
	fieldsToUse[2] = "ows_Description";
	fieldsToUse[3] = "ows_Endstate";
	fieldsToUse[4] = "ows_ID";

	var dataList = getDatalist(xmlDoc, fieldsToUse);	
}


So now I have a multi dimensional array populated with the data fields I need from the list. With this I can use the data to build my table. So I do so. In the end everything works and runs great.






That was all a few weeks ago and now I need to do more things. One of the things I had just had to do was allow a few Sharepoint controls to function on my page. Well this wasn't something as simple as putting in a few sharepoint controls tags in the html with Sharepoint Designer 2007. On top of that, the customer liked the look and feel of the page I made, which mimicked closely what their power point slide of the information was.

Basically the conclusion I came to after a bunch of research was to use a master page. The problem is we only have master pages that came with sharepoint out of the box (also called OOB) and a couple of added fancy ones from codeplex. After long discussions with the customer (who is not tech savvy at all) we decided to just add at the top the sharepoint "banner" and controls we have from the default master page setup we use. What I needed was a minimal master page that stripped out all the rest of the junk they didn't want.

Lo and behold, that was not nearly as simple as I would have thought. I tried to create a basic master page and add in items I wanted, but I was getting broken sharepoint part links all over the place. Even when I wasn't, if I tried to view any page I would make from the master page I would get the sharepoint error page. This was getting frustrating because I could see my page working on Sharepoint designer, but it wouldn't work when I tried to view it through a browser.

I finally ended up finding this on MSDN

http://msdn.microsoft.com/en-us/library/aa660698(v=office.12).aspx

It took awhile since I was finding links to the old version of that page which no longer exists.

So what I did was open up a new text document in notepadd++. I renamed it to minimalMaster.master and then copy/pasted the code from the above link into my master page. I saved it off and uploaded my master page to the sharepoint site. I looked at it in Designer and it seemed to be working (although previous attempts did the same thing). So I created a new page from that master page and looked at the new page in my IE8 browser. It worked!

It didn't have all the controls I wanted across the top, but the code from MSDN actually worked. Which is way more than I can say for every other thing I researched on google. Finding actual working code so far to sharepoint 2007 to do what I want has been a real pain in the ass. Most of these forums, blogs, and other shit have you so far down in the weeds that the code snippets don't just work unless you know exactly how to plug them in. And not even then do they work! There is some bad code out there you have to debug and that may not be worth the effort. Truthfully when it comes to programming this goes for a ton of things and not just sharepoint, but you get my frustration. When I did find more detailed tutorials, they are for real simple things that I can figure out within minutes of playing around. Either the scope of the help is too high or too low.

Anyhow, I then took to looking at my default.master page I had on the site and stripping out each sharepoint control in the top banner and placing them one by one in my minimalMaster page. Each one worked just fine and was reflected within the page I created off of my minimalMaster.

Here is the minimalMaster.master page that I ended up creating.
Code:
<&#37;-- Identifies this page as a .master page written in Microsoft Visual C# and registers tag prefixes, namespaces, assemblies, and controls. --%>
<%@ Master language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Register Tagprefix="SPSWC" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.Publishing.Navigation" Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="wssuc" TagName="Welcome" src="~/_controltemplates/Welcome.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="DesignModeConsole" src="~/_controltemplates/DesignModeConsole.ascx" %>
<%@ Register TagPrefix="PublishingVariations" TagName="VariationsLabelMenu" src="~/_controltemplates/VariationsLabelMenu.ascx" %>
<%@ Register Tagprefix="PublishingConsole" TagName="Console" src="~/_controltemplates/PublishingConsole.ascx" %>
<%@ Register TagPrefix="PublishingSiteAction" TagName="SiteActionMenu" src="~/_controltemplates/PublishingActionMenu.ascx" %>
<%-- Uses the Microsoft Office namespace and schema. --%>
<html>
	<SharePoint:RobotsMetaTag runat="server"/>

	<%-- The head section includes a content placeholder for the page title and links to CSS and ECMAScript (JScript, JavaScript) files that run on the server. --%>
	<head runat="server">
		<asp:ContentPlaceHolder runat="server" id="head">
			<title>
				<asp:ContentPlaceHolder id="PlaceHolderPageTitle" runat="server" />
			</title>
		</asp:ContentPlaceHolder>
		
		<Sharepoint:CssLink runat="server"/>
		<asp:ContentPlaceHolder id="PlaceHolderAdditionalPageHead" runat="server" />
	</head>

	<%-- When loading the body of the .master page, SharePoint Server 2007 also loads the SpBodyOnLoadWrapper class. This class handles .js calls for the master page. --%>
	<body scroll="yes" onload="javascript:if (typeof(_spBodyOnLoadWrapper) != 'undefined') _spBodyOnLoadWrapper();">
		
		<%-- The SPWebPartManager manages all of the Web part controls, functionality, and events that occur on a Web page. --%>
		<form runat="server" onsubmit="return _spFormOnSubmitWrapper();">
			<WebPartPages:SPWebPartManager runat="server" id="WebPartManager"/>
			<div style="background: white;">
			<TABLE class="ms-main" CELLPADDING=0 CELLSPACING=0 BORDER=0 width="100%">
				<tr>
					<td>
						<asp:ContentPlaceHolder id="PlaceHolderGlobalNavigation" runat="server">
							<table CELLPADDING=0 CELLSPACING=0 BORDER=0 WIDTH="100%">
								<tr>
						 			<td colspan=4 class="ms-globalbreadcrumb">
										<span id="TurnOnAccessibility" style="display:none">
								 			<a href="#" class="ms-skip" onclick="SetIsAccessibilityFeatureEnabled(true);UpdateAccessibilityUI();return false;">
												<SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,master_turnonaccessibility%>" EncodeMethod="HtmlEncode"/>
											</a>
										</span>
										<a href="javascript:;" onclick="javascript:this.href='#mainContent';" class="ms-skip" AccessKey="<%$Resources:wss,maincontent_accesskey%>" runat="server">
											<SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,mainContentLink%>" EncodeMethod="HtmlEncode"/>
										</a>
					 					
					 					<table cellpadding=0 cellspacing=0 height=100% class="ms-globalleft">
									   		<tr>
												<td class="ms-globallinks" style="padding-top: 2px;" height=100% valign=middle>
						 							<div>
						  								<span id="TurnOffAccessibility" style="display:none">
															<a href="#" class="ms-acclink" onclick="SetIsAccessibilityFeatureEnabled(false);UpdateAccessibilityUI();return false;">
																<SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,master_turnoffaccessibility%>" EncodeMethod="HtmlEncode"/>
															</a>
						  								</span>
						  								<asp:ContentPlaceHolder id="PlaceHolderGlobalNavigationSiteMap" runat="server">
															<asp:SiteMapPath SiteMapProvider="SPSiteMapProvider" id="GlobalNavigationSiteMap" RenderCurrentNodeAsLink="true" SkipLinkText="" NodeStyle-CssClass="ms-sitemapdirectional" runat="server"/>
						  								</asp:ContentPlaceHolder>
						  							</div>
						 						</td>
					   						</tr>
						 				</table>
					 					
					 					<table cellpadding="0" cellspacing="0" height=100% class="ms-globalright">
					  						<tr>
						  						<td valign="middle" class="ms-globallinks" style="padding-left:3px; padding-right:6px;">
						  							<SharePoint:DelegateControl runat="server" ControlId="GlobalSiteLink0"/>
						  						</td>
						  						
					  							<td valign="middle" class="ms-globallinks">
													<wssuc:Welcome id="IdWelcome" runat="server" EnableViewState="false">
													</wssuc:Welcome>
					  							</td>
					  							
					  							<td style="padding-left:1px;padding-right:3px;" class="ms-globallinks">
					  								|
					  							</td>
					  							
											  	<td valign="middle" class="ms-globallinks">
													<table cellspacing="0" cellpadding="0">
							 							<tr>
							  								<td class="ms-globallinks">
																<SharePoint:DelegateControl ControlId="GlobalSiteLink1" Scope="Farm" runat="server"/>
															</td>
							  								<td class="ms-globallinks">
																<SharePoint:DelegateControl ControlId="GlobalSiteLink2" Scope="Farm" runat="server"/>
															</td>
							 							</tr>
													</table>
						  						</td>
						  						
						  						<td valign="middle" class="ms-globallinks">&nbsp;
													<a href="javascript:TopHelpButtonClick('NavBarHelpHome')" AccessKey="<%$Resources:wss,multipages_helplink_accesskey%>" id="TopHelpLink" title="<%$Resources:wss,multipages_helplinkalt_text%>" runat="server"><img align='absmiddle' border=0 src="/_layouts/images/helpicon.gif" alt="<%$Resources:wss,multipages_helplinkalt_text%>" runat="server"></a>
						 						</td>
						  					</tr>
										</table>
									</td>
					   			</tr>
				   			</table>
						</asp:ContentPlaceHolder>
					</td>
				</tr>
				<tr>
				 	<td class="ms-globalTitleArea">
				 		<table width=100% cellpadding=0 cellspacing=0 border=0>
				   			<tr>
								<td id="GlobalTitleAreaImage" class="ms-titleimagearea">&nbsp;</td>
								
								<td class="ms-sitetitle" width=100% align="left">
					  				<asp:ContentPlaceHolder id="PlaceHolderSiteName" runat="server">
										<h1 class="ms-sitetitle">
						   					<SharePoint:SPLinkButton runat="server" NavigateUrl="~site/" id="onetidProjectPropertyTitle">
							 					<SharePoint:ProjectProperty Property="Title" runat="server" />
						   					</SharePoint:SPLinkButton>
					  					</h1>
					  				</asp:ContentPlaceHolder>
								</td>
								
								<td style="padding-top:8px;" valign=top>
					  				<asp:ContentPlaceHolder id="PlaceHolderSearchArea" runat="server">
										<SharePoint:DelegateControl runat="server" ControlId="SmallSearchInputBox"/>
					  				</asp:ContentPlaceHolder>
								</td>
				   			</tr>
				  		</table>
				 	</td>
				</tr>
				
				<tr>
				 	<td id="onetIdTopNavBarContainer" WIDTH=100% class="ms-bannerContainer">
						<asp:ContentPlaceHolder id="PlaceHolderTopNavBar" runat="server">
							<table class="ms-bannerframe" border="0" cellspacing="0" cellpadding="0" width="100%">
					   			<tr>
									<td nowrap valign="middle"></td>
									
									<td class=ms-banner width=99% nowrap ID="HBN100">
										<asp:ContentPlaceHolder id="PlaceHolderHorizontalNav" runat="server">
											<SharePoint:AspMenu
											ID="TopNavigationMenu"
											Runat="server"
											DataSourceID="topSiteMap"
											EnableViewState="false"
											AccessKey="<%$Resources:wss,navigation_accesskey%>"
											Orientation="Horizontal"
											StaticDisplayLevels="2"
											MaximumDynamicDisplayLevels="1"
											DynamicHorizontalOffset="0"
											StaticPopoutImageUrl="/_layouts/images/menudark.gif"
											StaticPopoutImageTextFormatString=""
											DynamicHoverStyle-BackColor="#CBE3F0"
											SkipLinkText=""
											StaticSubMenuIndent="0"
											CssClass="ms-topNavContainer">
												<StaticMenuStyle/>
												<StaticMenuItemStyle CssClass="ms-topnav" ItemSpacing="0px"/>
												<StaticSelectedStyle CssClass="ms-topnavselected" />
												<StaticHoverStyle CssClass="ms-topNavHover" />
												<DynamicMenuStyle  BackColor="#F2F3F4" BorderColor="#A7B4CE" BorderWidth="1px"/>
												<DynamicMenuItemStyle CssClass="ms-topNavFlyOuts"/>
												<DynamicHoverStyle CssClass="ms-topNavFlyOutsHover"/>
												<DynamicSelectedStyle CssClass="ms-topNavFlyOutsSelected"/>
											</SharePoint:AspMenu>
											<SharePoint:DelegateControl runat="server" ControlId="TopNavigationDataSource">
												<Template_Controls>
													<asp:SiteMapDataSource
													ShowStartingNode="False"
													SiteMapProvider="SPNavigationProvider"
													id="topSiteMap"
													runat="server"
													StartingNodeUrl="sid:1002"/>
												</Template_Controls>
											</SharePoint:DelegateControl>
										</asp:ContentPlaceHolder>
									</td>
	
									<td class=ms-banner>&nbsp;&nbsp;</td>
									
									<td valign=bottom align=right style="position:relative;bottom:0;left:0;">
						 				<table cellpadding=0 cellspacing=0 border=0>
						  					<tr>
						   						<td>
													<table height=100% class="ms-siteaction" cellpadding=0 cellspacing=0>
							 							<tr>
								   							<td class="ms-siteactionsmenu" id="siteactiontd">
								   								<SharePoint:SiteActions runat="server" AccessKey="<%$Resources:wss,tb_SiteActions_AK%>" id="SiteActionsMenuMain"
																PrefixHtml="&lt;div&gt;&lt;div&gt;"
																SuffixHtml="&lt;/div&gt;&lt;/div&gt;"
																MenuNotVisibleHtml="&amp;nbsp;">
																	<CustomTemplate>
																		<SharePoint:FeatureMenuTemplate runat="server"
																		FeatureScope="Site"
																		Location="Microsoft.SharePoint.StandardMenu"
																		GroupId="SiteActions"
																		UseShortId="true">
																			<SharePoint:MenuItemTemplate runat="server" id="MenuItem_Create"
																				Text="<%$Resources:wss,viewlsts_pagetitle_create%>"
																				Description="<%$Resources:wss,siteactions_createdescription%>"
																				ImageUrl="/_layouts/images/Actionscreate.gif"
																				MenuGroupId="100"
																				Sequence="100"
																				UseShortId="true"
																				ClientOnClickNavigateUrl="~site/_layouts/create.aspx"
																				PermissionsString="ManageLists, ManageSubwebs"
																				PermissionMode="Any" />
																			<SharePoint:MenuItemTemplate runat="server" id="MenuItem_EditPage"
																				Text="<%$Resources:wss,siteactions_editpage%>"
																				Description="<%$Resources:wss,siteactions_editpagedescription%>"
																				ImageUrl="/_layouts/images/ActionsEditPage.gif"
																				MenuGroupId="100"
																				Sequence="200"
																				ClientOnClickNavigateUrl="javascript:MSOLayout_ChangeLayoutMode(false);"/>
																			<SharePoint:MenuItemTemplate runat="server" id="MenuItem_Settings"
																				Text="<%$Resources:wss,settings_pagetitle%>"
																				Description="<%$Resources:wss,siteactions_sitesettingsdescription%>"
																				ImageUrl="/_layouts/images/ActionsSettings.gif"
																				MenuGroupId="100"
																				Sequence="300"
																				UseShortId="true"
																				ClientOnClickNavigateUrl="~site/_layouts/settings.aspx"
																				PermissionsString="EnumeratePermissions,ManageWeb,ManageSubwebs,AddAndCustomizePages,ApplyThemeAndBorder,ManageAlerts,ManageLists,ViewUsageData"
																				PermissionMode="Any" />
																		</SharePoint:FeatureMenuTemplate>
																	</CustomTemplate>
																</SharePoint:SiteActions>
															</td>
							 							</tr>
													</table>
						   						</td>
						  					</tr>
						 				</table>
									</td>
					  			</tr>
					  		</table>
						</asp:ContentPlaceHolder>
				 	</TD>
				</TR>
			</table>
			</div>
			<%-- The PlaceHolderMain content placeholder defines where to place the page content for all the content from the page layout. The page layout can overwrite any content placeholder from the master page. Example: The PlaceHolderLeftNavBar can overwrite the left navigation bar. --%>
			<asp:ContentPlaceHolder id="PlaceHolderMain" runat="server" />
			<asp:Panel visible="false" runat="server">
				<%-- These ContentPlaceHolders ensure all default SharePoint Server pages render with this master page. If the system master page is set to any default master page, the only content placeholders required are those that are overridden by your page layouts. --%><asp:ContentPlaceHolder id="PlaceHolderTitleBreadcrumb" runat="server"/><asp:ContentPlaceHolder id="PlaceHolderPageTitleInTitleArea"  runat="server"/><asp:ContentPlaceHolder id="PlaceHolderLeftNavBar" runat="server"/><asp:ContentPlaceHolder ID="PlaceHolderPageImage" runat="server"/><asp:ContentPlaceHolder ID="PlaceHolderBodyLeftBorder" runat="server"/><asp:ContentPlaceHolder ID="PlaceHolderNavSpacer" runat="server"/><asp:ContentPlaceHolder ID="PlaceHolderTitleLeftBorder" runat="server"/><asp:ContentPlaceHolder ID="PlaceHolderTitleAreaSeparator" runat="server"/><asp:ContentPlaceHolder ID="PlaceHolderMiniConsole" runat="server"/><asp:ContentPlaceHolder id="PlaceHolderCalendarNavigator" runat ="server" /><asp:ContentPlaceHolder id="PlaceHolderLeftActions" runat ="server"/><asp:ContentPlaceHolder id="PlaceHolderPageDescription" runat ="server"/><asp:ContentPlaceHolder id="PlaceHolderBodyAreaClass" runat ="server"/><asp:ContentPlaceHolder id="PlaceHolderTitleAreaClass" runat ="server"/><asp:ContentPlaceHolder id="PlaceHolderBodyRightMargin" runat="server" /></asp:Panel>
		</form>
	</body>
</html>

So now my next hurdle was to add my ASPX page content into a page created from the master page. So from sharepoint designer, when I right click on my master page I select the new from option. I get a new ASPX page with only the sharepoint link at the top which looks like this.

Code:
<%@ Page masterpagefile="_catalogs/masterpage/minimalMaster.master" language="C#" inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" meta:progid="SharePoint.WebPartPage.Document" meta:webpartpageexpansion="full" %>

All in all, not very useful yet. After a bit of research I figured out what I needed to do. I had to add a sharepoint content place holder control on the page folllowed by a sharepoint web zone control. This way I could add sharepoint webparts into the zone. To do this I had to add the following on my page after the above.

Code:
<asp:Content ID="Content1" ContentPlaceHolderID="PlaceHolderMain" Runat="Server">
</asp:Content>

That is the content holder so the sharepoint website can manage what goes inside it on this page to a degree. I had to use "PlaceHolderMain" to make it match up to the content place holder ID field on my master page. This way the sharepoint site knows where to put the contents of this aspx page I have within the scope of the master page.

Using Sharepoint designer, I look at my ASPX in design mode. I click on the section of the page that shows my content area. I then go to my webparts control panel in designer and click on the button that says. New Webpart zone. I configure my webpart zone through the wizard that pops up.

Now the next part I had to learn was a bit trickier. I couldn't do what I wanted to do that easily in designer, but through my IE8 browser.

So open my browser and go look at my so far basic ASPX page based off my minimalMaster page with only a single web part zone. Since I have sharepoint controls now on this page I can click on the button that states, "Site Actions"

From there I can click on the open to edit my page within IE8. So I click on edit and see my page view change to an edit mode. I click on the button that appears in the webpart zone I have to add new web parts. I do so and then select from the wizard list that appear a "Content Editor Web Part" to use as my webpart for this page.

By itself the "Content Editor Web Part" (CEWP) is blank with nothing in it. However, you can insert HTML code or rich text and it will be displayed. So to get my table displayed in this webpart I did the following.

While still in edit mode for the web page in IE8, I click on the CEWP edit->modify menu option. I get a menu that appears with several options to choose from. I click on the button in the menu that says Insert HTML.

Using my previous ASPX I copy all my HTML code from that page minus a few things. This is because the master page already provides those HTML tags and you can't use them again. So you can not have a <HTML> or <HEAD> or <BODY> tag. Even form tags need to be redone somewhat. However, things within those tags can still be used including links to javascript or CSS files.

I did find a few more annoying quirks though in getting my table to display properly. I'm not going to give the exact HTML I used, but I'll give a small piece for simplicity and demonstration of the problem I ran into. I used the following HTML in my CEWP.

Code:
<link href="style.css" rel="stylesheet" type="text/css" media="screen" />
<script type="text/javascript" src="ScriptsLibrary/buildMyTable.js"></script>

<table cellspacing="0" cellpadding="0" id="myTable">	
	<tr id="headerRow" />
	<tr id="mainBodyRow" />
	<tr id="footerRow" />
</table>

I basically had javascripts building my table based off the data from the lists I pulled from sharepoint and using a CSS to style it like the power point slide. At first nothing was working. When I went back into the HTML editor for the wep part, I noticed that my TR elements were being removed. It seems that in a CEWP you can't have a blank TR element along with a few others I discovered. GRR. Why isn't this shit documented? Annoying has heck. So I had to adjust my code to the following.

Code:
<link href="style.css" rel="stylesheet" type="text/css" media="screen" />
<script type="text/javascript" src="ScriptsLibrary/buildMyTable.js"></script>

<table cellspacing="0" cellpadding="0" id="myTable">	
	<tr id="headerRow"><div id="PlaceHolder"></div></tr>
	<tr id="mainBodyRow"><div id="PlaceHolder"></div></tr>
	<tr id="footerRow"><div id="PlaceHolder"></div></tr>
</table>

Now my TR elements all had a DIV tag within them which kept sharepoint from auto stripping those out from the HTML editor before even being saved off for the page. Stupid editor.



So now everything with that page is working as the customer wants. I'm now really pushing forward on the next page, the one I described above. There are several things to note though. First, the table page I created already displays data from sharepoint lists, but it only displays. I have hyper links within my table being generated that right now send the user that clicks on them to the exactly sharepoint list view of that piece of data they click on within the table. Again, the customer who is requesting this page does not want to look at a sharepoint list view. They want something that looks like another one of their power point slides. So that is what I need to make for him. He wants this page to be displayed and contain the all the sharepoint list info for any item hyper linked in the table. which conceptually is no biggie to think of how to do.

My basic premise is to create another new page from my minimalMaster page. I need to add a form though as my webpart. This form will contain several text edit fields. What I need though to do is the following.

1) Pass data from my table page to this new form page. The data passed will be the info of which data item in the sharepoint list to be displayed on the form page. I need to figure out how to do this correctly. I am used to using tokens with ASPX for a normal webform. This may not be the case if I stick with sharepoint and use an infopath form.

2) I need at the top of the form a way to switch to different sharepoint data within the list. For example, I have a list of employees. The form displays all the data for a given employee. Which employee it displays data for initially is passed from the table page. However, at the top I'm going to include a drop down combo box that allows the user to select a different employee to be displayed in the form.

3) By default, the form has text fields that are not edit-able. Instead I need to check the permissions of the current user using the form. If they are allowed to edit, for example the current information for a given employee, they will see a button that allows them to a particular text field on the form to edit-able.

I'm not sure what is the best way to accomplish the form page personally at the moment. any help would be appreciated.
 
Last edited:

HumblePie

Lifer
Oct 30, 2000
14,665
440
126
Well, made some progress on my own again. Got quite a bit done of what I wanted to do. Still stuck on a small issue though.

The customer wants to lock down individual items in a sharepoint list permission wise.

For example I have a list of say employees. They want only certain groups or certain individuals to be able to edit or have control of specific employee data.

Not a big deal really to implement this through sharepoint. I create a few new user groups. Assign individuals to the groups. Then I go to the list I want. I manage each individual item in the list and assign permissions for each group or person. Very simple to do that.

So if I am using sharepoint views and such only to read, or edit, or create items in a list it is controlled by the permissions I set.

However, I have a specialized page I created that is made to show a single item in the list. For example it shows one employee's data for a given list. The user wants this page to be their "input" page. Which is fine. The problem is trying to get who has permissions for this list item.

Now I figured out how to get the current user who is looking at my page easy enough using JQuery and JQuery.SpServices.

Here is the bit of code I have.

Code:
<div>
	<table>
		<tr>
			<td><p>login: </p></td>
			<td><p id="login"></p></td>
		</tr>
		<tr>
			<td><p>name: </p></td>
			<td><p id="name"></p></td>
		</tr>
		<tr>
			<td><p>email: </p></td>
			<td><p id="email"></p></td>
		</tr>
		<tr>
			<td><p>group: </p></td>
			<td><p id="group"></p></td>
		</tr>
	</table>
</div>
<div id="divid"></div>

<script type="text/javascript"> 

function getLogin()
{
	var userLogin = $().SPServices.SPGetCurrentUser({
		fieldName: 'Name',
		debug: true  
	});
	return userLogin;
}

function getFullName()
{
	var userFullName = $().SPServices.SPGetCurrentUser({
		fieldName: "Title",
		debug: true 
	});
	return userFullName;
}

function getJobTitle()
{
	var userJobTitle = $().SPServices.SPGetCurrentUser({
		fieldName: "JobTitle",
		debug: false
	});
	return userJobTitle;
}

function getUserEmail()
{
	var userEmail = $().SPServices.SPGetCurrentUser({
		fieldName: 'EMail',
		debug: false  
	});
	return userEmail;
}

function getGroup()
{
	var xmlDoc = new XMLHttpRequest();
	$().SPServices({
		operation: "GetGroupCollectionFromUser",
		userLoginName: getLogin(),
		async: false,
		completefunc: function(xData, Status)
		{
			xmlDoc = xData.responseXML;
			//alert(xData.responseText);
		}
	});
	var xmlNode = xmlDoc.getElementsByTagName("Group");
        // should loop through multiple groups since a person may belong to more than one.
	return (xmlNode[0].getAttribute("Name"));
}

$('#login').text(getLogin());  
$('#name').text(getFullName());
$('#email').text(getUserEmail());
$('#group').text(getGroup());

$('#divid').html('Working...').SPServices({
	operation: "GetPermissionCollection",
	objectName: 'Major Objectives',
	objectType: "List",
	completefunc: function (xData, Status)
	{
		var out = "<ul>";
		$(xData.responseXML).find("Permission").each(function ()
		{
			if ($(this).attr("MemberIsUser") === "True")
			{
				out += "<li>User: " + $(this).attr("UserLogin") + "</li>";
			}
			else
			{
				out += "<li>Group: " + $(this).attr("GroupName") + "</li>";
			}
			
			var readmask = 0x0000000000000001;
			var addmask = 0x0000000000000002;
			var editmask = 0x0000000000000004;
			var deletemask = 0x0000000000000008;
			out += "<li>Mask: " + $(this).attr("Mask") + "</li>";
			var canread = readmask & $(this).attr("Mask").toString(16) > 0 ? "Yes" : ($(this).attr("Mask").toString(16) < 0 ? "Yes" : "No");
			var canadd = addmask & $(this).attr("Mask").toString(16) > 0 ? "Yes" : ($(this).attr("Mask").toString(16) < 0 ? "Yes" : "No");
			var canedit = editmask & $(this).attr("Mask").toString(16) > 0 ? "Yes" : ($(this).attr("Mask").toString(16) < 0 ? "Yes" : "No");
			var candelete = deletemask & $(this).attr("Mask").toString(16) > 0 ? "Yes" : ($(this).attr("Mask").toString(16) < 0 ? "Yes" : "No");
			out += "<li>Can Read: " + canread + "</li>";
			out += "<li>Can Add: " + canadd + "</li>";
			out += "<li>Can Edit: " + canedit + "</li>";
			out += "<li>Can Delete: " + candelete + "</li>";
			out += "<br/>";
		});
		out += "</ul>";
		$('#divid').html(out);
	}
});
</script>


This code shows me who is currently accessing the current page. It gives me their login and the groups they belong to. I can also use the Permissions.asmx web service by Sharepoint (although I'm calling functions through JQuery to do it for me) to access the permissions for an entire list.

I'm stuck on trying to figure out permissions for a single item in a list. I can set individual list item permissions in sharepoint. I just haven't figured out how to access those permissions from sharepoint.
 

HumblePie

Lifer
Oct 30, 2000
14,665
440
126
Gah nevermind. Found out there is no way to retreive item level permissions in sharepoint after finally finding a site to state that.

http://www.codefornuts.com/2009/05/item-level-security-with-sharepoint-web.html


So I have to create my own web service to do that.

Or I can use bamboo to use roll-up list collections and break my big list into smaller lists. This is going to be a fun conversation I'm going to have with the customer later :(
 

HumblePie

Lifer
Oct 30, 2000
14,665
440
126
Nice of you to keep updating this HumblePie. Maybe someone will find it useful in the future.

Thanks. I figure that if it's been a pain in the ass for me then I know it must be for others. All the code I put above works just fine as I use it myself right now. Or a more complicated variation for the data and pages I'm dealing with.

I think I'll post a few more general code bits, that actually work and can be plugged in anywhere like I did above, for my more recent things. I'm no sharepoint guru by any stretch of the imagination, but I've learned quite a lot in a short period of time about it.
 

Gunslinger08

Lifer
Nov 18, 2001
13,234
2
81
Hey HumblePie, I'm sorry I haven't responded sooner - life has been really busy lately.

If you can write actual C# code for this form, it's pretty easy to determine if the current user has view or edit permissions:

bool hasPermissions = false;
SPUser user = SPContext.Current.Web.CurrentUser;

SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPListItem li = this.GetListItem(); // go out to your list and get the item by ID
hasPermissions = li.DoesUserHavePermissions(user, SPBasePermissions.EditListItems);
});