SharePoint / ASP.Net Development
Experiences from the field
Navigation
   RSS 2.0
Categories
Entries by Month

# Thursday, May 01, 2008

Introduction

The out-of-the-box Image Web Part can be used to display an image on a site. The web part has a property that specifies the web address of the image. For most site members, this is problematic – how do they get an image on the web site? And how do they determine the web address? For power users, these steps are understood, but are time consuming to complete.

The Image Upload Web Part will allow the site member to browse their local computer for the image. Once the image is selected, the web part will automatically upload the image to a location specified by an administrator and set the web address.

The result is a solution that works for both groups. Site members can display pictures from their computer and administrators can provide storage for those pictures with changing the permissions of their site and with minimal training.

More information available in the download or at the project's page on CodePlex.

ImageUploadv3.zip (.16 KB)
Thursday, May 01, 2008 1:19:20 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
# Wednesday, March 12, 2008

I am working on getting a community site up to host these articles as well as the code. My hope is that all interested developers will contribute their solution to the various Actions that can be selected in SharePoint designer.

This post is the first in a series. The series will discuss the porting steps as we presented in Seattle, but with the details filled in. (We had only 75 minutes to present, which is way too little.) Part 1 will discuss the virtual machine setup and the creation of the SharePoint Designer workflow that will be ported.

Virtual Machine Setup

When a workflow is created in SharePoint Designer, the site is updated with a few pieces that enable it to work. We want to ensure that we port all of these pieces, so we will be using two different web applications. The first at http://spdflow will be used for the SharePoint Designer workflow. The second at http://vsflow will host the Visual Studio workflow. Rather than use different port numbers for the web application, the hosts file (C:\WINDOWS\system32\drivers\etc\hosts) is updated with each of these host names.

The virtual machine will also have the necessary applications installed: SharePoint Designer 2007 and Visual Studio 2005 with the Office SharePoint Server 2007 SDK.

SharePoint Designer

We will use SharePoint Designer to create a workflow. The workflow will perform the most popular actions -- collecting data, creating a task and writing to the history list. This is accomplished via the following steps:

  • In SharePoint Designer, open the site http://spdflow.
  • Click File | New | Workflow. The Workflow Designer wizard is displayed.
  • Name the workflow SPDFlow and attach it to the Announcements list. Leave the start options at the default, which is manually. (We'll be starting it often.)

  • Click on the Initiation button on the bottom
  • Add a Workflow Initiation Parameter named InitiationField with a default value of Barracuda. Then click OK

  • Back in the Workflow Designer wizard, Click Next.
  • In Step 1, click on the Conditions button and choose Compare Announcements field.

  • Choose the Modified By field and the account name of the current user.

  • Click on the Actions button and choose Collect Data from User.

  • Click on the "data" link to invoke the Custom Task Wizard.

  • Enter "Collect Data Task" for the task name and click Next

  • Click Add to create a field.

  • Name the field "TaskField" and enter a default value of "DeliverPoint"

  • Click Finish on the Custom Task Wizard. You will receive a warning about running instances, which can be ignored.
  • Click on the "this user" link in Step 1 Actions. Select the account name for the current user.

  • Click on the "Variable: collect" link in Step 1 Actions. Rather than put the data in a generically named variable called "collect," choose "Create a new variable" and name it "ListItemID"

  • Click on the Variables button at the bottom of the Workflow Designer form. Even though we did not choose the variable named "collect," it was created for us. Remove it, and any other unused variables, from the list.
  • Click Finish.

SharePoint Designer will save the workflow and associate it with the Announcements list. Test the workflow by returning to the browser and navigating to the Announcements list.

  • On the context menu of a list item, select Workflows

  • On the Workflows page in the Start a New Workflow section, click on the name of the workflow (SPDFlow)

  • The initiation form is displayed. Click Start

  • The Announcements list is displayed, with a new column on the far right. The column name matches the name of the workflow and the value is "In Progress"

  • Click on "In Progress" to display the Workflow Status page

  • In the middle of the page is the name of the task: CollectDataTask. Click on this link to display the task.

  • Click on Edit Item in the tool bar. This will display the custom task edit form for this workflow

  • Click on Complete Task

    At this point we have a workflow that was created in SharePoint Designer. The next post is this series will move us further along our path. Stay tuned!

Wednesday, March 12, 2008 5:33:00 AM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
# Tuesday, December 04, 2007

I added a new operation to the Barracuda Application Extension Download:

stsadm -o enumsitegallerytemplates -site <site collection url>

   Displays the names and identifiers of Site Definitions in the Site Template Gallery.

 

Barracuda StsAdm Extensions.wsp (8.01 KB)

Tuesday, December 04, 2007 5:26:08 PM (Central Standard Time, UTC-06:00)  #    Comments [1]  | 
# Tuesday, May 01, 2007

I found a particularly interesting comment on the Technet Script Center page for Scheduled Tasks:

Note that this class can only return jobs that are created using either a script or AT.exe. It cannot return information about jobs that are either created by or modified by the Scheduled Task wizard.

A search of the .Net Framework turned up empty. As far as I can tell, schtasks.exe is the way to go if you want the end-users to be able to change the default entry…


UPDATED June 14, 2007:   I used the Task Scheduler library from Code Project. 

Tuesday, May 01, 2007 5:12:06 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
# Wednesday, December 21, 2005
Wednesday, December 21, 2005 11:30:08 AM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
# Tuesday, August 30, 2005

Sometimes, it seems that the .MDB file will live forever. I recently had to convert some DDL so it would work against the Jet data engine. (Jet does not use ANSI SQL.) In the depths of the MSDN archive was a very useful reference series: Fundamental Microsoft Jet SQL for Access 2000. This page links to two more -- titled Intermediate and Advanced.

Tuesday, August 30, 2005 3:36:08 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
# Saturday, August 27, 2005

If you are using active generation of templates, here is a build script that invokes CodeSmith:

<?xml version="1.0" encoding="unicode"?>
<project name="nant" default="compile" xmlns="http://nant.sf.net/schemas/nant.xsd">
 <property name="CodeSmith" value="cs.exe" />

 <target name="compile" depends="genruntime" description="Compile entire solution">
  <solution solutionfile="src\project.sln" configuration="release">
   <webmap>
    <map url="http://localhost/ProjectWeb" path="src\ProjectWeb" />
   </webmap>
  </solution>
 </target>
 <target name="genruntime" description="Generate O/R Classes for the runtime library">
  <exec program="${CodeSmith}" basedir="tools\codesmith" workingdir="src\ProjectWeb.Runtime">
   <arg value="/t: Templates\ClassGenerator.cst" />
   <arg value="/ps: ORClasses.xml" />
  </exec>
 </target>

This script was influenced by Mike Roberts' article How to setup a .NET Development Tree. (Thanks Mike!) I use a property to alias the CodeSmith command (cs.exe) because I kept thinking csc (which compiles C# code).

Saturday, August 27, 2005 11:15:59 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
# Monday, August 22, 2005

Do you have an ASP.Net application that will run in an Application Pool with a specific identity? Before you enter the user account in the Identity tab of the Application Pool properties dialog, you should add the account to the local group IIS_WPG. If you forget, you get permission issues. And permission issues are the hardest to fix, imho.

(I am sure you can guess why I am blogging this...)

Monday, August 22, 2005 11:58:52 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
# Sunday, August 14, 2005

I had to move an extranet application, including the databases, to a new server. The application has just over 300 sites, so of course I had to write code! There is a lot of file copies, but the script does include one interesting piece: creating a database on a server and creating an empty database.

The solution was written in VBScript and runs on a Windows XP machine. The script uses SQL-DMO to perform the database admin steps. I am including the script below as an example.

Now, I am sure that many of you will have an opinion about the code. That is fine. But do not flame about database best practices -- I am simply moving an existing application with specific requirements. And do not flame about the hungarian notation -- VB Script does not have strong typing and the entire script is almost 400 lines. Feel free to flame anything else. ;-)

Sub CreateDB(DBServer, SiteName)
    Dim oDBDataFile, sDataPath, oDBLogFile, sLogPath
    Dim oSvr, oDB

    Set oSvr = CreateObject("SQLDMO.SQLServer")
    oSvr.Connect DBServer, "user", "password" ' Could use WinNT login

    Set oDB = CreateObject("SQLDMO.Database")
    Set oDBDataFile = CreateObject("SQLDMO.DBFile")
    Set oDBLogFile = CreateObject("SQLDMO.LogFile")

    'Set new database name
    oDB.Name = SiteName

    'Define the PRIMARY data file.
    oDBDataFile.Name = SiteName
    sDataPath = oSvr.Registry.SQLDataRoot & "\DATA\" & SiteName & ".mdf"
    oDBDataFile.PhysicalName = sDataPath
    oDBDataFile.PrimaryFile = True
    oDBDataFile.Size = 2 'Set initial size (optional)

    oDBDataFile.FileGrowthType = SQLDMOGrowth_MB 'fixed size - other options available
    oDBDataFile.FileGrowth = 1

    'Add the DBFile object
    oDB.FileGroups("PRIMARY").DBFiles.Add oDBDataFile

    'Define the database transaction log.
    oDBLogFile.Name = SiteName & "Log"
    sLogPath = oSvr.Registry.SQLDataRoot & "\DATA\" & oDBLogFile.Name & ".ldf"
    oDBLogFile.PhysicalName = sLogPath
    oDBLogFile.Size = 2
    oDB.TransactionLog.LogFiles.Add oDBLogFile

    'Create the database as defined.
    oSvr.Databases.Add oDB
    
    'Add a user to the database
    Set oUser = CreateObject("SQLDMO.User")
    oUser.Login = "ExNet"
    oUser.Role = "db_owner" ' Make sure this is appropriate for you!
    oDB.Users.Add(oUser)
    

    ' Now, build the schema from the file of SQL statements
    Const ForReading = 1, ForWriting = 2
    Dim oFSO, oFile, sFile, sCmdBatch
    
    SET oFSO = CreateObject("Scripting.FileSystemObject")

    sFile = "C:\Visual Studio Projects\ExNetMove\CreateDatabase2_05.sql"
    SET oFile = oFSO.OpenTextFile(sFile, ForReading)

    sCmdBatch = oFile.ReadAll
    
    oDB.ExecuteImmediate sCmdBatch, SQLDMOExec_ContinueOnError    

    oFile.Close

End Sub

Sunday, August 14, 2005 11:00:32 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
# Thursday, August 11, 2005

I don't have the time for a full review, but the book Building ASP.Net Server Controls by Dale Michalk and Rob Cameron has been very helpful for a long time.

If you are interested in writing server controls (and remember, Web Parts are server controls) this book is for you. The authors start out with very basic "write" statements, but they progress into a sophisticated control -- one that includes templates, CSS styling and data binding.

Thursday, August 11, 2005 12:16:49 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
# Friday, March 04, 2005

Full Source
Full Source is an Internet Explorer menu extension which displays the source Internet Explorer is displaying, directly from the Internet Explorer object model. This is useful wherever javascript is dynamically writing HTML into the DOM, or where XSLT has been used to generate HTML.

If you have ever looked at the source of a list edit form, you'll know that you need this utility!

Their other utility (Toggle Borders) is neat as well.

Friday, March 04, 2005 2:28:03 PM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
# Monday, January 31, 2005

I wrote in my previous post that you should use http to access web part resources. Well guess what -- there is more to it.

If your WSS site is running with anonymous access off, then the attempt to get the resource will fail with a 401 Unauthorized error. This happens because web requests made in code will perform an anonymous GET.

In my specific case, I was attempting to read an XSLT file from the resource directory by passing the URL to the file. To solve the security issue, the Load() method on the XslTransform object needs a security resolver. The code necessary for this (which I copied from the .Net SDK):

' Build the URI to the resource
Dim resourceURI As Uri = New Uri(ClassResourcePath)
Dim xslPath As String = Path.Combine(resourceURI.ToString(), "filename.xsl")

' Create a secure resolver with default credentials.
Dim resolver as XmlUrlResolver = new XmlUrlResolver()
Dim sResolver as XmlSecureResolver = new XmlSecureResolver(resolver, xslPath)
sResolver.Credentials = CredentialCache.DefaultCredentials

' Get the xsl file
Dim trn As XslTransform = New XslTransform
trn.Load(xslPath, sResolver)

Monday, January 31, 2005 2:14:25 PM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
# Friday, January 21, 2005

I've left pieces of this here and here. But perhaps a little code would help. :)

Public Class MyWebPart
Inherits Microsoft.SharePoint.WebPartPages.WebPart

Private Const TRACE_CLASS_ID As String = "MyWebPart"

Protected Overrides Sub RenderWebPart(ByVal output as System.Web.UI.HtmlTextWriter)
Dim TRACE_CATEGORY As String = TRACE_CLASS_ID + "RenderWebPart"

Try
Context.Trace.Write(TRACE_CATEGORY, "Trying something")
' Do something here

' pretend there is a variable
Context.Trace.Write(TRACE_CATEGORY, "variable value: " + variable)

output.Write("you html code goes here")

Catch ex As Exception
Context.Trace.Warn(TRACE_CATEGORY, ex.ToString)
End Try

End Sub

Friday, January 21, 2005 12:35:56 PM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
# Monday, January 03, 2005

UPDATE: John points out “It should be noted that when you change the setting to CT with UIiB, an automatic Full or Incremental (depending upon the presence of a timestamp column) is executed to re-sync the table data with the FT Catalog.“  I missed this when I posted, but new visitors should be aware of this. Thanks John!


John Kane came across my post on the forums at Joel on Software about full-text indexing on SQL Server. I suggested that I could post a script that sets all of the tables in an index to background change tracking, but I never did make that post.

So, here is a T-SQL script that will check every table in every catalog in the current database:

DECLARE @FTCatID smallint, @FTPath nvarchar(260), @FTStatus int
DECLARE @FTName sysname, @FTNbrTbls int DECLARE @csr_FT CURSOR

DECLARE @FTTOwner sysname, @FTTName sysname, @FTTIndex sysname
DECLARE @FTTColid int, @FTTActive int, @FTTCat sysname
DECLARE @csr_FTT CURSOR

-- Get all the catalogs in the current database
EXEC sp_help_fulltext_catalogs_cursor @csr_FT OUTPUT
FETCH NEXT FROM @csr_FT INTO @FTCatID, @FTName, @FTPath, @FTStatus, @FTNbrTbls
WHILE (@@FETCH_STATUS = 0)
BEGIN

-- Get all the tables in this catalog

print @FTName
EXEC sp_help_fulltext_tables_cursor @csr_FTT OUTPUT, @FTName
FETCH NEXT FROM @csr_FTT INTO @FTTOwner, @FTTName, @FTTIndex, @FTTColid, @FTTActive, @FTTCat

WHILE (@@FETCH_STATUS = 0)
BEGIN

print ' ' + @FTTName
EXEC sp_fulltext_table @FTTName, 'Start_change_tracking'
EXEC sp_fulltext_table @FTTName, 'Start_background_updateindex'

FETCH NEXT FROM @csr_FTT INTO @FTTOwner, @FTTName, @FTTIndex, @FTTColid, @FTTActive, @FTTCat

END

CLOSE @csr_FTT

DEALLOCATE @csr_FTT

FETCH NEXT FROM @csr_FT INTO @FTCatID, @FTName, @FTPath, @FTStatus, @FTNbrTbls END

CLOSE @csr_FT
DEALLOCATE @csr_FT

 

If your server is setup like mine, you might have multiple databases on the server. If you want to run the above script on all the databases, here is a VBScript to do so:

dim oServer, oDB, oFS, oFile
dim sCmdBatch

Set oFS = CreateObject("Scripting.FileSystemObject")
Set oFile = oFS.OpenTextFile("FT_change_tracking.sql")
sCmdBatch = oFile.ReadAll

Set oServer = CreateObject("SQLDMO.SQLServer")

WScript.Echo "Connecting..."
oServer.LoginSecure = True
oServer.Connect "servername"

On Error Resume Next

For Each oDB in oServer.Databases
    WScript.Echo "Database: " & oDB.Name
    oDB.ExecuteImmediate sCmdBatch
Next

Monday, January 03, 2005 3:22:39 PM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
# Thursday, August 12, 2004

I often use a web page to convert C# code to VB to help me understand it. Sometimes, that is overkill when trying to understand a keyword or two.

MSDN has this page to help in this situation: Keywords Compared in Different Languages

Thursday, August 12, 2004 9:42:12 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
# Tuesday, June 08, 2004

I've previously pointed to a web site that will convert a C# snippet to VB.  It stumbled on this code, so I had to RTFM (!!!).  Since it involved more than a few minutes, I'm posting it for future reference:

if ( dataSource is IEnumerable )

Converts to

If TypeOf dataSource Is IEnumerable

Tuesday, June 08, 2004 10:04:23 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
# Friday, May 21, 2004

Another thing I discovered...

Defining a relation/contraint between two tables in the DataSet designer does not always create the DataRelation in the resulting DataSet object.

Friday, May 21, 2004 9:00:28 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 

I use strongly-typed datasets. I like the intellisense and it IsXXXNull methods. And I bind them to data grids. Everything is good.

When acting on a datagrid in ItemCreated or ItemCommand, it is common to access the underlying data. This is acheived via e.Item.DataItem. When a grid is bound to a DataSet or DataTable, this property returns a DataRowView. My lovely, strongly-typed object is gone. :(

I needed to build a page that displayed hierarchical data. So, instead of binding my grid to a DataTable, I was binding to a GetChildRows method, which is a DataRow(). My strongly-typed DataRow is back!!!

To get the strongly-type datarow without a relation, bind to dataSet.dataTable.Rows.

Friday, May 21, 2004 8:58:52 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
# Wednesday, May 05, 2004

I need to bind a dropdown list control to some data from an XML document. Initially, I tried to specify the DataSource as a node list and the DataText & DataValue properties to “@attribute_name”. No luck.

Thanks to the internet, I found the ASP.NET DropDownList XML Binder Class from the XML for ASP.Net site. This class is written to read an XML file from the specified path and create the ListItems that are added to the control.  It's not databinding in the same sense as ASP.Net, but it works!

The class uses an XMLTextReader. Since I already have a document, I can use the XMLNodeReader and I'm done. 

Wednesday, May 05, 2004 11:39:55 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
# Thursday, March 04, 2004
While I can understand code written in C#, I still feel more comfortable in VB. To fill in the blanks, I use the converter page at Clarity Consulting to help with the translation. Thanks Clarity Consulting!
Thursday, March 04, 2004 12:44:29 AM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
# Tuesday, March 02, 2004
Tuesday, March 02, 2004 8:47:00 PM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
# Sunday, April 27, 2003
I came across an ASP Table Editor utility at 2eNetWorX. I have hacked together pages to execute SQL statements numerous times, so I know that this type of utility is extremely valuable. There are many other utilities on this site.
Sunday, April 27, 2003 6:39:27 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
# Monday, April 07, 2003
I couldn't believe it! If I'm not the last one, then try d.setDate(d.getDate()+1). At least now I wrote it down so I can find it when I need it again.
Monday, April 07, 2003 8:47:22 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
# Wednesday, February 12, 2003
I'm reading about how to wring performance from MSXML and I ran across this nugget from the MSXML4 page on MSDN:
Additionally, MSXML 4.0 provides the new, faster XML parser and a substantially improved XSLT engine. You can use the new parser with DOM by setting the NewParser property to True. The new parser does not yet support asynchronous DOM load or DTD validation. However, everything else functions the same way as with the old parser, only faster. In our tests, MSXML showed about 2x better performance for pure parsing, and more than 4x better performance for XSLT transformation.
Wednesday, February 12, 2003 5:33:00 AM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
Search

Powered by: newtelligence dasBlog 2.2.8279.16125

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010, Paul Schaeflein

Send mail to the author(s) E-mail