Display SharePoint Documents On Your Company Internet Site
I was recently working on a small POC project. Basically I had an internal MOSS 2007 server site and an locally hosted public facing website. I wanted to have the ability to add files to various MOSS document libraries and then give outside website visitors the ability to view and download these documents. So, what I did was:
-
Created a document library in MOSS with Version and Content Approval enabled. I also added additional custom fields to the document library that could display along with the document on the public web.
-
Created a user control that I could drag to the public pages to display the documents and wired up the user control to access SharePoints webservices to rectrieve and display the document libraries specifics. (SEE CODE BELOW)
This is only a POC so bare with me. You should be able to follow the basics of what I am doing. Nothing is rocket science.
-
Create a new WebSite in Visual Studio.
-
Add a new web_reference. Point it at your SharePoint server (http://<Your SharePoint Server>/_vti_bin/List.asmx)
-
Add a new user control to your website. (SEE CODE BELOW)
-
Add a new webpage and drag on your user control to it. Run and enjoy.
Imports System.Net
Imports System.IO
Imports MOSS 'THIS IS YOUR WEB_REFERENCE
Partial Class SPDocuments
Inherits System.Web.UI.UserControl
'THIS IS THE KEY TO IT ALL. THIS USER MUST HAVE READ ONLY CREDENTIALS
'TO THE DOCUMENT LIBRARY. THAT WAY THE SEE THE LATEST PUBLISH DOCUMENT ONLY.
Dim networkCredential As New NetworkCredential("username", "password")
Private _DocumentLibraryID As String
Public Property DocumentLibraryID() As String
Get
Return _DocumentLibraryID
End Get
Set(ByVal value As String)
_DocumentLibraryID = value
End Set
End Property
Private _DocumentLibrary As String
Public Property DocumentLibrary() As String
Get
Return _DocumentLibrary
End Get
Set(ByVal value As String)
_DocumentLibrary = value
End Set
End Property
Private _FileServer As String
Public Property FileServer() As String
Get
Return _FileServer
End Get
Set(ByVal value As String)
_FileServer = value
End Set
End Property
Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
MyBase.OnInit(e)
If DocumentLibraryID Is Nothing Then
DocumentLibraryID = GetListID(DocumentLibrary)
Else
DocumentLibrary = GetListID(DocumentLibraryID)
End If
BindLiteral()
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
End If
End Sub
Private Sub BindLiteral()
'THE USER CREDENTIALS HERE SHOULD HAVE READ ONLY ACCESS ACCROSS THE LIST LIBRARY
'Declare and initialize a variable for the Lists Web service
Dim listService As MOSS.Lists = New MOSS.Lists()
'Authenticate the current user by passing their default
'credentials to the Web service from the system credential cache.
listService.Credentials = networkCredential
'Set the Url property of the service for the path to a subsite.
listService.Url = String.Format("http://{0}/_vti_bin/Lists.asmx", FileServer)
' Instantiate an XmlDocument object
Dim xmlDoc As System.Xml.XmlDocument = New System.Xml.XmlDocument()
' Assign values to the string parameters of the GetListItems method, using GUIDs for the listName and viewName
'variables. For listName, using the list display name will also work, but using the list GUID is recommended. For
'viewName, only the view GUID can be used. Using an empty string for viewName causes the default view
'to be used.
Dim listName As String = DocumentLibraryID
Dim viewName As String = ""
Dim rowLimit As String = "1000"
'Use the CreateElement method of the document object to create elements for the parameters that use XML.*/
Dim query As System.Xml.XmlElement = xmlDoc.CreateElement("Query")
Dim viewFields As System.Xml.XmlElement = xmlDoc.CreateElement("ViewFields")
Dim queryOptions As System.Xml.XmlElement = xmlDoc.CreateElement("QueryOptions")
'To specify values for the parameter elements (optional), assign CAML fragments to the InnerXml property of each element.*/
query.InnerXml = QueryCAML()
viewFields.InnerXml = "<FieldRef Name=""DocIcon"" /><FieldRef Name=""ProgId"" /><FieldRef Name=""FileRef"" /><FieldRef Name=""Public_x0020_Title"" /><FieldRef Name=""Public_x0020_Description"" /><FieldRef Name=""LinkFilename"" /><FieldRef Name=""Modified"" /><FieldRef Name=""Author"" /> "
queryOptions.InnerXml = ""
' Declare an XmlNode object and initialize it with the XML response from the GetListItems method. The last parameter specifies the GUID of the Web site containing the list. Setting it to null causes the Web site specified by the Url property to be used.
Dim nodeListItems As System.Xml.XmlNode = listService.GetListItems(listName, viewName, query, viewFields, rowLimit, queryOptions, Nothing)
nodeListItems.Normalize()
For Each node As System.Xml.XmlNode In nodeListItems
If node.Name = "rs:data" Then
For Each childNode As System.Xml.XmlNode In node.ChildNodes
If childNode.Name = "z:row" Then
'For i As Integer = 0 To childNode.Attributes.Count - 1
' strHTML += childNode.Attributes(i).Name & "<br />"
'Next
Dim strDocIcon As String = childNode.Attributes("ows_DocIcon").Value
Dim strLinkFilename As String = childNode.Attributes("ows_LinkFilename").Value
Dim strLinkFileRef As String = childNode.Attributes("ows_FileRef").Value.Replace(childNode.Attributes("ows_ProgId").Value, "")
Dim strLastModified As String = childNode.Attributes("ows_Modified").Value
'CUSTOM FIELD
Dim strPublicTitle As String = childNode.Attributes("ows_Public_x0020_Title").Value
'CUSTOM FIELD
Dim strPublicDescription As String = childNode.Attributes("ows_Public_x0020_Description").Value.Replace(childNode.Attributes("ows_ProgId").Value, "")
'Dim strBody As String = childNode.Attributes("ows_Body").Value
'strBody = System.Text.RegularExpressions.Regex.Replace(strBody, "<[^>]*>", "")
Dim ib As ImageButton = New ImageButton()
ib.ImageUrl = GetIcon(strDocIcon)
ib.CommandArgument = strLinkFilename
AddHandler ib.Click, AddressOf ImageButtonGetFile
Dim lb As LinkButton = New LinkButton()
lb.Text = strPublicTitle
lb.CommandArgument = strLinkFilename
AddHandler lb.Click, AddressOf LinkButtonGetFile
Me.phDocuments.Controls.Add(ib)
Me.phDocuments.Controls.Add(lb)
Me.phDocuments.Controls.Add(New HtmlGenericControl("br"))
End If
Next
End If
Next
End Sub
Private Function QueryCAML() As String
'Use this tool to build the CAML for you http://www.codeplex.com/SPCamlViewer
Dim oSb As New System.Text.StringBuilder
oSb.Append(" <OrderBy>")
oSb.Append(" <FieldRef Name=""Public_x0020_Title"" />")
oSb.Append(" </OrderBy>")
oSb.Append(" <Where>")
oSb.Append(" <And>")
oSb.Append(" <Eq>")
oSb.Append(" <FieldRef Name=""Publicly_x0020_Available"" />")
oSb.Append(" <Value Type=""Boolean"">1</Value>")
oSb.Append(" </Eq>")
oSb.Append(" <Eq>")
oSb.Append(" <FieldRef Name=""_ModerationStatus"" />")
oSb.Append(" <Value Type=""ModStat"">Approved</Value>")
oSb.Append(" </Eq>")
oSb.Append(" </And>")
oSb.Append(" </Where>")
Return oSb.ToString()
End Function
Private Sub ImageButtonGetFile(ByVal sender As Object, ByVal e As ImageClickEventArgs)
'THE USER CREDENTIALS HERE SHOULD HAVE READ ONLY ACCESS ACCROSS THE DOCUMENT LIBRARY
Dim ib As ImageButton = CType(sender, ImageButton)
GetFile(ib.CommandArgument)
End Sub
Private Sub LinkButtonGetFile(ByVal sender As Object, ByVal e As EventArgs)
'THE USER CREDENTIALS HERE SHOULD HAVE READ ONLY ACCESS ACCROSS THE DOCUMENT LIBRARY
Dim lb As LinkButton = CType(sender, LinkButton)
GetFile(lb.CommandArgument)
End Sub
Private Sub GetFile(ByVal strFileName As String)
Dim strURI As String = String.Format("http://{0}/{1}/{2}", FileServer, DocumentLibrary, strFileName)
Dim request As WebRequest = WebRequest.Create(New Uri(strURI))
request.Credentials = networkCredential
Dim webResponse As WebResponse = request.GetResponse()
Dim webStream As Stream = webResponse.GetResponseStream()
System.Web.HttpContext.Current.Response.ClearHeaders()
System.Web.HttpContext.Current.Response.ContentType = "application/octet-stream"
System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + strFileName)
Dim binaryReader As BinaryReader = New BinaryReader(webStream)
Dim buffer As Byte() = binaryReader.ReadBytes(webResponse.ContentLength)
System.Web.HttpContext.Current.Response.OutputStream.Write(buffer, 0, webResponse.ContentLength)
System.Web.HttpContext.Current.Response.Flush()
webResponse.Close()
webStream.Close()
End Sub
Private Function GetIcon(ByVal strDocIcon As String) As String
'THIS IS JUST FOR FANCY DISPLAY
Dim imgLocation As String = ""
Select Case strDocIcon
Case "doc", "rtf", "wps", "txt", "docx", "dot"
imgLocation = "~/images/word.png"
Case "xls", "csv", ".xlw", "xlt", "xlsx"
imgLocation = "~/images/excel.png"
Case "ppt", "pptx"
imgLocation = "~/images/powerpoint.png"
Case "pdf"
imgLocation = "~/images/pdf.png"
Case "zip", "rar", "gzip"
imgLocation = "~/images/zip.png"
Case Else
imgLocation = "~/images/default.png"
End Select
Return imgLocation
End Function
Function GetListID(ByVal strListName As String) As String
Dim strListID As String = ""
'THE USER CREDENTIALS HERE SHOULD HAVE READ ONLY ACCESS ACCROSS THE LIST LIBRARY
'Declare and initialize a variable for the Lists Web service
Dim listService As MOSS.Lists = New MOSS.Lists()
'Authenticate the current user by passing their default
'credentials to the Web service from the system credential cache.
listService.Credentials = networkCredential
'Set the Url property of the service for the path to a subsite.
listService.Url = String.Format("http://{0}/_vti_bin/Lists.asmx", FileServer)
' Instantiate an XmlDocument object
Dim xmlDoc As System.Xml.XmlDocument = New System.Xml.XmlDocument()
' Declare an XmlNode object and initialize it with the XML response from the GetListItems method. The last parameter specifies the GUID of the Web site containing the list. Setting it to null causes the Web site specified by the Url property to be used.*/
Dim nodeListItems As System.Xml.XmlNode = listService.GetListCollection()
nodeListItems.Normalize()
For Each node As System.Xml.XmlNode In nodeListItems
If node.Name = "List" AndAlso node.Attributes("Title").Value = strListName Then
strListID = node.Attributes("ID").Value
Exit For
End If
Next
Return strListID
End Function
Function GetListName(ByVal strListID As String) As String
Dim strListName As String = ""
'THE USER CREDENTIALS HERE SHOULD HAVE READ ONLY ACCESS ACCROSS THE LIST LIBRARY
'Declare and initialize a variable for the Lists Web service
Dim listService As MOSS.Lists = New MOSS.Lists()
'Authenticate the current user by passing their default
'credentials to the Web service from the system credential cache.
listService.Credentials = networkCredential
'Set the Url property of the service for the path to a subsite.
listService.Url = String.Format("http://{0}/_vti_bin/Lists.asmx", FileServer)
' Instantiate an XmlDocument object
Dim xmlDoc As System.Xml.XmlDocument = New System.Xml.XmlDocument()
' Declare an XmlNode object and initialize it with the XML response from the GetListItems method. The last parameter specifies the GUID of the Web site containing the list. Setting it to null causes the Web site specified by the Url property to be used.*/
Dim nodeListItems As System.Xml.XmlNode = listService.GetListCollection()
nodeListItems.Normalize()
For Each node As System.Xml.XmlNode In nodeListItems
If node.Name = "List" AndAlso node.Attributes("ID").Value = strListID Then
strListName = node.Attributes("Title").Value
Exit For
End If
Next
Return strListName
End Function
End Class
<div>
<pcoe:SPDocuments ID="SPDocuments1" runat="server" FileServer="<SERVER NAME>/<SITE NAME>" DocumentLibrary="<DOC LIB NAME>" />
</div>
Like I said this is only a POC I created to demostrate how it can be done. I am sure there are several ways to achomplish the same task. I would be interested in hearing them.