Labels: InfoPath
Using [Today] in a Calculated Formula (Birthday Lists)
Posted by milap shah on Tuesday, October 13, 2009It is possible to use "Today" in a function as a reference to today's date
doesn't involve very much effort or complexity.
- First, create a new column in your list with the column name of "Today".
Click "OK". (It doesn't matter what type of column or data it is, this is
just a place holder and will be removed later).
Create column called Today… I also created a column called DOB (date field) where I will enter the birth date. - Next, create a column with the data where you would like to use "Today" as a
reference to today's date. The column type should be "Calculated". In the
formula field, create your formula using "Today" as if it held the column date/time.
SharePoint will calculate the formula based on the assumption that you will
be using "Today" as a reference to the new column you just created.
I created a column called MonthCheck with the formula shown below:
=IF(MONTH([Today])=MONTH([DOB]),"Birthday","NotBirthday") - Next, edit the new column named "Today" that you created in the first step.
On the very bottom of the page, click "Delete", to delete the column. In
your formula, SharePoint will keep the reference to "Today" but it will
change from referencing your column, to a reference to the current date. - Now you can create your new view in the list to display “This Month's Birthdays”. Just apply a filter to Show only when the following is true: MonthCheck is equal to Birthday
I've also created a BirthDay Column (Capitalized the “D” to note the difference) as well that is a calculated column: =DATE(YEAR(Today),MONTH(DOB),DAY(DOB))
You can then create a view to display Today's Birthdays by filtering to Show only when the following is true: BirthDay is equal to [Today]
This can be used in any of the Date and Time functions, but I haven't tested
it beyond that.
Notes:
If you want to edit the formula (CheckMonth) containing "Today" SharePoint will not let
you, and will give you the same error about not using Today or Me in a
function. To get passed this problem you have to temporarily create another
Today column (and then delete it again).
The same functionality will also work with [Me].
Just Develop your UserControl and then put it in LayOuts/ControlTemplate/YourCompanyfolder and then load it in CreateChildControls method of the webpart as below.
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls.WebParts;
using System.ComponentModel;
using System.Web.UI;
using UserControls;
public class WebPart2:WebPart
{
[WebBrowsable(true)]
[WebDescription("User Control Path")]
[WebDisplayName("User Control Name")]
[Category("Custom Properties")]
[Personalizable(PersonalizationScope.User)]
public string UserControlPath { get; set; }
[WebBrowsable(true)]
[WebDisplayName("Display All Lists")]
[WebDescription("Display All Lists")]
[Category("Custom Properties")]
[Personalizable(PersonalizationScope.User)]
public string SiteURL { get; set; }
private TestUC control;
protected override void CreateChildControls()
{
TestUC control = (TestUC)Page.LoadControl(UserControlPath);
control.SiteURL = SiteURL;
Controls.Add(control);
}
}
To Deploy WebParts we need 5 files
manifest.xml(Solution File)
<?xml version="1.0" encoding="utf-8" ?><Solution xmlns="http://schemas.microsoft.com/sharepoint/" SolutionId="EB89EA67-0162-4e03-82D3-3BCDE734A628">
<FeatureManifests>
<FeatureManifest Location="WebPartFeature\Feature.xml"></FeatureManifest>
</FeatureManifests>
<Assemblies>
<Assembly DeploymentTarget="GlobalAssemblyCache" Location="HelloWorldWebPart.dll">
<SafeControls>
<SafeControl Assembly="TestWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=240340c0f00bc06a" Namespace="TestWebPart" TypeName="*" Safe="True"/>
</SafeControls>
</Assembly>
<Assembly DeploymentTarget="GlobalAssemblyCache" Location="UserControls.dll">
<SafeControls>
<SafeControl Assembly="UserControls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=240340c0f00bc06a" Namespace="UserControls" TypeName="*" Safe="True"/>
</SafeControls>
</Assembly>
</Assemblies>
<TemplateFiles>
<TemplateFile Location="Features\WebPartFeature\WebPart1.webpart"/>
<TemplateFile Location="Features\WebPartFeature\WebPart2.webpart"/>
<TemplateFile Location="ControlTemplates\WebPartFeature\UserEntry.ascx"/>
</TemplateFiles>
</Solution>
Feature.xml
<?xml version="1.0" encoding="utf-8" ?><Feature xmlns="http://schemas.microsoft.com/sharepoint/" Scope="Site"
Id="EF6F3009-E4A4-480e-B84A-4B6E9AD90313" SolutionId="EB89EA67-0162-4e03-82D3-3BCDE734A628" ActivateOnDefault="True" Title="TestWebPartFeature"
Description="TestWebPartFeature" Hidden="FALSE">
<ElementManifests>
<ElementManifest Location="elements.xml"/>
</ElementManifests>
</Feature>
elements.xml
<?xml version="1.0" encoding="utf-8"?><Elements Id="66fb994b-4f3e-4106-8027-d0c08923392a" xmlns="http://schemas.microsoft.com/sharepoint/" >
<Module Name="WebParts" List="113" Url="_catalogs/wp">
<File Path="WebPart1.webpart" Url="WebPart1.webpart" Type="GhostableInLibrary" />
<File Path="WebPart2.webpart" Url="WebPart2.webpart" Type="GhostableInLibrary" />
</Module>
</Elements>
WebPart1.webpart
<?xml version="1.0" encoding="utf-8"?><webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<!--
The following Guid is used as a reference to the web part class,
and it will be automatically replaced with actual type name at deployment time.
-->
<type name="TestWebPart.HelloWorldWebPart, HelloWorldWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=240340c0f00bc06a" />
<importErrorMessage>Cannot import HelloWorld Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">HelloWorld Web Part</property>
<property name="Description" type="string">HelloWorld Description</property>
<property name="SiteUrl" type="string">http://amishah:1982/</property>
</properties>
</data>
</webPart>
</webParts>
DDF File
; ** UluruServer_SharedService.wsp **.OPTION EXPLICIT ; Generate errors
.Set CabinetNameTemplate=TestUserControlWebParts.wsp
.set DiskDirectoryTemplate=CDROM ; All cabinets go in a single directory
.Set CompressionType=MSZIP;** All files are compressed in cabinet files
.Set UniqueFiles="ON"
.Set Cabinet=on
.Set DiskDirectory1=""
.Set MaxDiskSize=CDROM
manifest.xml manifest.xml
HelloWorldWebPart.dll HelloWorldWebPart.dll
UserControls.dll UserControls.dll
WebPartFeature\elements.xml WebPartFeature\elements.xml
WebPartFeature\Feature.xml WebPartFeature\Feature.xml
WebPartFeature\WebPart1.webpart Features\WebPartFeature\WebPart1.webpart
WebPartFeature\WebPart2.webpart Features\WebPartFeature\WebPart2.webpart
UserEntry.ascx ControlTemplates\WebPartFeature\UserEntry.ascx
This time we're talking about how to deploy web parts as a feature. Now, deploying custom web parts the manual way is a bit of a pain - the following things are required for the web part to be used:-
- the assembly containing the compiled web part class to be in the GAC (or site bin with appropriate CAS policy)
- a SafeControls entry in the site web.config to tell SharePoint this control is administrator-approved
- the .webpart (or .dwp) file which contains the web part definition (configuration) to be uploaded to the site's web part gallery
Assuming the user has appropriate permissions, the web part can then be added to a WebPartZone on a web part page. The first thing to say is that there are 2 ways of automating this process:-
- use VSeWSS to create a feature to deploy the web part - simply hit F5 to deploy to your local server; this also generates a SharePoint solution package (.wsp) which can be deployed to other environments.
- create a feature 'manually' by creating the files (e.g. feature.xml, elements file etc.) by hand
Both methods will take care of the 3 steps listed above, so that the files are copied and the SafeControls entry is added. I can't emphasise enough how simple VseWSS makes this process. Additionally, VSeWSS apparently allows simple debugging when F5 is hit, but I had to copy the .pdb file to the hidden folders in the GAC hierarchy to enable this. See my article on how to debug feature receivers for more information.
However, use of VSeWSS typically means there is slightly less control over the deployment options, since the tool writes the files for you and not all of the options are exposed for you to modify (I go into more detail on this in Creating lists with VSeWSS). As an example, VSeWSS will deploy web part assemblies to the GAC (with full trust), but some SharePoint admins prefer assemblies to run from private bin folders instead to isolate any harm they might do. Hence, there are some occasions where you might want to use the second option and create the feature yourself. The remainder of this article illustrates this process, using the example of a web part which should be deployed to a bin folder.
Once the webpart has been developed, we need to create the manifest file, specifying the feature details, assembly, SafeControls entry, and webpart definition file (.webpart):-
Then, we need the feature.xml file which points to the elements file and tells the framework there is another file to process (that being the .webpart file):-
The elements.xml file should look something like:-
Finally, a .webpart file should be generated to define the metadata and default property values of the webpart.
I place this in a folder underneath my feature files alongside the .dll file containing the compiled assembly.
Assuming all the files are in the right place, the solution file (.wsp) can be built using makecab.exe. This solution can now be deployed, thus taking care of the manual steps for webpart deployment. Once this process is familiar (and you have existing files to copy for the next time) this process is quite straightforward.
[UPDATE 22 November 2007 : for bin deployments, the .dll should be at the root of the .wsp file - if it is in a subfolder, it will be deployed to a subfolder of the bin directory which we do not want. See this article's comments for more details.]
Note the DeploymentTarget="WebApplication" instruction in the manifest.xml file. This ensures the assembly is deployed to the application bin folder rather than the GAC. Now, most web parts will require additional CAS policy to obtain the permissions to execute - your assembly will now have the default trust level of WSS_Minimal, so any file io, database or web service access will probably fail. I hope to cover the entries for this in a future article.
So the webpart should now be in the Web Part Gallery and ready to be added to a page.
One thing I also want to discuss is the different ways of adding a webpart to a page. These are:-
- adding the webpart to a WebPartZone (possible in a feature by use of AllUsersWebPart element)
- adding the webpart to the HTML markup of a page layout by dragging from SPD
The main thing to note is that if you want to be able to update webpart configuration as part of updating the page layout itself, the webpart should not be in a WebPartZone. If so, the webpart properties are stored in webpart storage, and updating a page layout (either via a feature or manually uploading to the Master Page Gallery) will not change any web part properties. However, note that web part properties can only be edited by a user if the part is in a WebPartZone. This confused me for a while, and is an important facet of the webpart architecture to be aware of.
Microsoft ASP.NET AJAX 1.0: A Background
Microsoft ASP. NET AJAX 1.0 lets developers build Web 2.0 sites using the latest Ajax techniques.
ASP.NET AJAX extends ASP.NET 2.0 and makes several new tools and techniques available to help you build applications more quickly:
- Extensions to JavaScript. ASP.NET AJAX extends the JavaScript library to bring standard object oriented concepts to JavaScript. It brings a formal type declaration system, with support for inheritance. It also provides a significant number of out of the box types, including types such as Sys.Net.WebRequest for working with web services. Finally, it helps to abstract some cross-browser issues such as XML element traversal. This makes it much easier to create robust JavaScript libraries and frameworks which are commonly needed by rich internet applications.
- ASP.NET Control Extenders. Extenders are additional ASP.NET controls which can extend the functionality of existing controls with additional Ajax capabilities. A common example is an extender which allows existing textbox controls to have autocomplete functionality with no modification to the extended control. (The autocomplete extender is included with the ASP.NET AJAX Control Toolkit.)
- UpdatePanels. UpdatePanels allow your existing ASP.NET controls and web parts to achieve the fluid, no-postback updates of Ajax-based applications with minimal re-coding of your control or part. Quite simply, controls within the UpdatePanel control which ordinarily would post back to update their data will now be routed through an Ajax-style callback, resulting in a silent update back to the server. This makes your application “postback” much less, making interaction with your control more seamless.
With Microsoft ASP.NET AJAX 1.0, you can build more dynamic applications that come closer to the rich style of interruption-free interaction you may see in standard client applications.
Microsoft ASP.NET AJAX 1.0 and SharePoint
Windows SharePoint Services version 3 builds much more directly on top of ASP.NET 2.0; therefore, many of the capabilities of ASP.NET AJAX work directly with SharePoint.
However, in a few cases there are some compatibility issues between ASP.NET AJAX and SharePoint which are anticipated to be addressed in the first service pack of Windows SharePoint Services. For this reason, until that first Service Pack of Windows SharePoint Services, we are unable to offer formal support through Microsoft Product Support Services for usage of ASP.NET AJAX within a SharePoint Web site. This post is intended to provide developers with some guidelines for evaluating ASP.NET AJAX and WSS3.0.
Specifically, there are some limitations on usages of the UpdatePanel in your web parts and controls. Some approaches are described below to address these limitations, but these are workarounds and as such may cause other issues in your application.
Here are some common scenarios in SharePoint you should be able to achieve with Microsoft ASP.NET AJAX 1.0:
- Building a more powerful, re-usable JavaScript libraries you can use in your web controls and parts
- Enabling your web services to render via JSON, resulting in easier usage in JavaScript/Ajax Applications
- Building a web part that takes advantage of Extender technology to provide richer interaction styles, such as autocomplete on a textbox.
- Using an UpdatePanel in your web part or control for more fluid, no postback interaction. (this will require some workarounds, however.)
Adding Microsoft ASP.NET AJAX Technology to SharePoint Pages
To extend your SharePoint site with Microsoft ASP.NET AJAX 1.0, you’ll need to perform a few steps.
- First, you will need to download and install ASP.NET AJAX on servers in your farm.
- Second, you need to extend web.config with some settings to enable ASP.NET AJAX technology.
- Third, you will need to add the ASP.NET AJAX Script Manager into your master page to enable scenarios such as Extenders or UpdatePanels.
Installing ASP.NET AJAX on servers in your farm
You will want to install the full "ASP.NET 2.0 AJAX Extensions 1.0" from ajax.asp.net.
Extending SharePoint web.config files with Microsoft ASP.NET AJAX 1.0
Extending SharePoint web.config files with ASP.NET AJAX requires that you interleave some Ajax registration entries in-line with WSS registration entries. To do this you will need to edit your SharePoint web.config file, typically in a directory like c:\inetpub\wwwroot\wss\virtualdirectories\80.
1. Add a <sectionGroup>element to the <configSections>tag:
<configSections>
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere" />
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
</sectionGroup>
</sectionGroup>
</sectionGroup>
</configSections>
2. Add a <controls> section as a child of the <system.web>/<pages> tag:
<pages>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</controls>
</pages>
3. Add the following tag to the <assemblies> tag, within <compilation>:
<assemblies>
<add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</assemblies>
4. Add some new registrations to the end of the <httpHandlers> section:
<httpHandlers>
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
</httpHandlers>
5. Add a new registration to the HttpModules section, beneath any existing registrations:
<httpModules>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>
6. Add a SafeControl entry for the System.Web.UI namespace from Microsoft Ajax Extensions, within the <SharePoint>/<SafeControls>section:
<SafeControls>
<SafeControl Assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Namespace="System.Web.UI" TypeName="*" Safe="True" />
</SafeControls>
7. Finally, add the following configuration tags at the bottom of web.config, near the bottom before the end <configuration> tag:
<system.web.extensions>
<scripting>
<webServices>
<!-- Uncomment this line to enable the authentication service. Include requireSSL="true" if appropriate. -->
<!--
<authenticationService enabled="true" requireSSL = "true|false"/>
-->
<!-- Uncomment these lines to enable the profile service. To allow profile properties to be retrieved and modified in ASP.NET AJAX applications, you need to add each property name to the readAccessProperties and writeAccessProperties attributes. -->
<!--
<profileService enabled="true"
readAccessProperties="propertyname1,propertyname2"
writeAccessProperties="propertyname1,propertyname2" />
-->
</webServices>
<!--
<scriptResourceHandler enableCompression="true" enableCaching="true" />
-->
</scripting>
</system.web.extensions>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules>
<add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</modules>
<handlers>
<remove name="WebServiceHandlerFactory-Integrated" />
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode"
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</handlers>
</system.webServer>
Adding a ScriptManager into a SharePoint MasterPage
Many components of ASP.NET AJAX require the inclusion of a .NET ScriptManager control within a page.
Although it may be possible in some cases to dynamically insert a script manager from within a control, in many cases the control may not be able to insert the script manager early enough in the page lifecycle depending on how the control is used, making this tricky to get right. Also, the control implementer will need to ensure that multiple instances of their control (or other controls) do not result in the addition of multiple script managers within the page. For these reasons, dynamic insertion of a ScriptManager control from another control is not recommended.
To statically embed a script manager into a page, it is recommended that you add the ScriptManager into the master page of a site.
To do this, open up the master page for your site. Typically, this will be located at <site url>/_catalogs/masterpage. You can edit this file by opening it in an editor such as Microsoft SharePoint Designer, or directly in Notepad by opening your master page library via DAV (typically \\server\<pathtosite>\_catalogs\masterpage.)
Add the following into the markup of your page. A recommended location is right beneath the WebPartManager registration (search for <WebPartPages:SPWebPartManager id="m" runat="Server" />):
<asp:ScriptManager runat="server" ID="ScriptManager1"></asp:ScriptManager>
Using UpdatePanels within SharePoint
UpdatePanels are a very useful addition to ASP.NET AJAX, and represent the simplest way to convert existing, standard ASP.NET controls and parts to take advantage of Ajax techniques. However, there are some changes within Windows SharePoint Services which may get in the way of working with ASP.NET AJAX.
Windows SharePoint Services JavaScript has a “form onSubmit wrapper” which is used to override the default form action. This work is put in place to ensure that certain types of URLs, which may contain double byte characters, will fully work across most postback and asynchronous callback scenarios. However, if your scenarios do not involve double byte character URLs, you may successful disable this workaround and gain the ability to use ASP.NET AJAX UpdatePanels.
To do this, you may need to register a client startup script which disables this workaround, in addition to resetting the default form action:
<script type='text/javascript'>_spOriginalFormAction = document.forms[0].action; _spSuppressFormOnSubmitWrapper=true;</script>
This script may be directly embedded in the page, or could be emitted by a control that uses the UpdatePanel. The following is an example of a very simple ASP.NET Web Part which uses UpdatePanel capabilities:
using System;
using System.Collections;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI;
namespace MS.Samples
{
public class AjaxUpdatePanelPart : WebPart
{
private Label label;
private TextBox textBox;
protected override void CreateChildControls()
{
base.CreateChildControls();
this.EnsureUpdatePanelFixups();
UpdatePanel up = new UpdatePanel();
up.ID = "UpdatePanel1";
up.ChildrenAsTriggers = true;
up.UpdateMode = UpdatePanelUpdateMode.Conditional;
this.Controls.Add(up);
this.textBox = new TextBox();
this.textBox.ID = "TextBox";
up.ContentTemplateContainer.Controls.Add(this.textBox);
this.label = new Label();
this.label.Text = "Enter your name.";
up.ContentTemplateContainer.Controls.Add(this.label);
Button button = new Button();
button.Text = "Say Hello";
button.Click += new EventHandler(HandleButtonClick);
up.ContentTemplateContainer.Controls.Add(button);
}
private void HandleButtonClick(object sender, EventArgs eventArgs)
{
this.label.Text = "Hello " + this.textBox.Text;
}
private void EnsureUpdatePanelFixups()
{
if (this.Page.Form != null)
{
string formOnSubmitAtt = this.Page.Form.Attributes["onsubmit"];
if (formOnSubmitAtt == "return _spFormOnSubmitWrapper();")
{
this.Page.Form.Attributes["onsubmit"] = "_spFormOnSubmitWrapper();";
}
}
ScriptManager.RegisterStartupScript(this, typeof(AjaxUpdatePanelPart), "UpdatePanelFixup", "_spOriginalFormAction = document.forms[0].action; _spSuppressFormOnSubmitWrapper=true;", true);
}
}
}
Output Caching and ASP.NET AJAX
ASP.NET AJAX infrastructure is not compatible with output caching features. This output caching infrastructure is a featured component of managed content pages such as those supported by web content management features in Microsoft Office SharePoint Server. For this reason, many scenarios which involve output cached features may not be able to take advantage of components like UpdatePanel. However, you will be able to successfully use other ASP.NET AJAX features, such as the JavaScript library, combined with your output cached pages.
Compatibility with output caching is targeted for a future release of ASP.NET AJAX infrastructure.
Sharepoint features, webparts, and files are deployed using a solutions file with the extension wsp. The wsp files are actually just a “.cab” file, which is the native Windows archive format. The content of the solutions file must follow a particular schema. Unfortunately, the schema and relationships are not very well documented. The following is an attempt to clear up the confusion.
The Hive
Let’s start backwards from the deployment and look at the hive. The hive is where SharePoint files are installed. When we deploy a solution package using the stsadm.exe command:
stsadm -o addsolution -filename MyFeature.wsp
The stsadm command copies the files from the WSP to the hive. By default, the hive is located in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12 on the WSS server.
Typically, when you create a new WSS project, you want to replicate the directory structure of the hive in your project. The reason will become apparent later when we create the solution. In addition, if you plan to use a tool like wspbuilder, the tool expects you to organize the directory in the same manner as the hive.
The Solutions File
Next, we look at the solution, which has an extension of “.wsp”. The solutions file contains everything needed to deploy your software. The solutions file is just a cab file, so we can open it by changing the extension from “.wsp” to “.cab” and then double-click on it.
Here’s an example of the content of a WSP file:
Manifest.xml MyFeature\Feature.xml ControlTemplates\MyFeatureForm.ascx MyFeature.dllNotice the Manifest.xml file at the beginning. A solution file may hold a variety of different files, but it always has a manifest.xml file. This manifest file list what is in the solutions file. Let’s examine the manifest.xml next.
Manifest.xml file and how it relates to the WSP file
The manifest.xml file specifies how the WSP file is put together. Here’s what the manifest.xml file for the above solutions file looks like:
<Solution SolutionId="4AFC9950-F354-4439-B941-51377E854F2B" xmlns="http://schemas.microsoft.com/sharepoint/"> <FeatureManifests> <FeatureManifest Location="MyFeature\Feature.xml"/> </FeatureManifests> <TemplateFiles> <TemplateFile Location="ControlTemplates\MyFeatureForm.ascx"/> </TemplateFiles> <Assemblies> <Assembly DeploymentTarget="GlobalAssemblyCache" Location="MyFeature.dll"/> </Assemblies> </Solution>
This manifest tells us that this WSP has an Assembly (the dll), a user control (ascx), and a feature.xml file. There may be additonal files in the WSP. You can even embed a movie into the WSP. But unless the file is specified in the manifest, the installer will skip over it during installation.
The root element of the manifest is always <Solution>. The solution ID is a GUID that uniquely identifies your solution (the deployment package) to SharePoint. When you create a new package, you must always create a new GUID. The other elements specify what is in the WSP file and where to find them via the location attribute. The location is the most confusing part. When I first programmed SharePoint, I thought the location must either closely follow the 12 hive’s file structure or the location must be totally independent of the 12 hive. It turns out that both assumptions are false. The location does actually follow the 12 hives, but the root location will change according to the element type.
Let’s examine the element <FeatureManifest>, the location is based on root of the FEATURES at 12\TEMPLATE\FEATURES. If we deploy this WSP, the location tells it to look for the feature.xml file in MyFeature directory in the WSP file and deploy it to 12\TEMPLATE\FEATURES\MyFeature\feature.xml.
If we take a look at the element <TemplateFile> for the control “MyFeatureForm.ascx”, the location is based on the root of the TEMPLATE, which is at 12\TEMPLATE. If you examine 12\TEMPLATE in the hive, you’ll notice that there is already a CONTROLTEMPLATES and there is already a list of controls there. When we deploy, the manifest will tell the installer that the file MyFeatureForm.ascx is located in ControlTemplates directory in the WSP and that the MyFeatureForm.ascx should be deployed to 12\TEMPLATE\CONTROLTEMPLATES\MyFeatureForm.ascx.
Finally, the <Assembly> element specifies where the DLL is located. The root for this element is the web application bin file if you specify DeploymentTarget=”WebApplication”, and the GAC if you specify DeploymentTarget=”GlobalAssemblyCache”. Hopefully by now, you can guess how this works. In the above example, the <Assembly> element tells the installer to look in the root of the WSP file for the MyFeature.dll and deploy it to the GAC, which is typically located in C:\Windows\System32\Assembly on most systems.
The following is a small table listing the element and where the root of the location in the hive.
| Manifest Element | Location’s Root |
| ApplicationResourceFile | 12\Resources |
| Assembly | Web Application bin or GAC |
| FeatureManifest | 12\TEMPLATE\FEATURES |
| ResourceFile | 12\TEMPLATE\FEATURES |
| RootFile | 12 |
| SiteDefinitionManifest | 12\TEMPLATE\SiteTemplates |
| TemplateFile | 12\TEMPLATE |
| WebTempFile | 12\TEMPLATE |
<TemplateFile Location="ControlTemplates\MyFeatureForm.ascx"/>to
<TemplateFile Location="ControlTemplates\MyProject\MyFeatureForm.ascx"/>Keep in mind that not all combination makes sense or is valid. Features are always limited to one layer deep. If you try to specify location=”MyProject\MyFeature\feature.xml” for a FeatureManifest element, you will get an error message that you cannot go beyond one level deep. In additon, specifying location=”Myproject\MyFeature.dll” doesn’t make sense either because you’ll end up with a subdirectory inside the GAC.
Generating the WSP using a DDF file
While the manifest determines what’s in the WSP file, you still have to create the WSP file itself. Technically, you can manually build the WSP file by hand, but you can use a diamond definition file to build it for you during a compile. A DDF is basically an instruction file for building WSP files. Let’s examine the DDF file used to build the WSP example. This DDF file is placed in the root of the project folder.
; ** sample_wsp.wsp **
.OPTION EXPLICIT ; Generate errors
.Set CabinetNameTemplate=sample_wsp.wsp
.set DiskDirectoryTemplate=CDROM ; All cabinets go in a single directory
.Set CompressionType=MSZIP;** All files are compressed in cabinet files
.Set UniqueFiles="ON"
.Set Cabinet=on
.Set DiskDirectory1=Package
.Set MaxDiskSize=CDROMPackage\sample.dll Package\sample.dllConfig\PowerShell\Registration\cmdlets.xml Config\PowerShell\Registration\cmdlets.xml
The first important line is “CabinetNameTemplate”, which specifies what the outfile file name is going to be. The entry “DiskDirectoryTemplate” may look a bit odd, but it tells the builder where to put the output file. In this case, we say “..\Deployment”. The path is relative to the project’s home directory, so this will generate a Deployment directory into the your Visual Studio’s solution file’s directory and put the WSP file there. The idea is when you compile, all of the WSP file for all projects in the solution will end up in the same deployment directory.The rest of the DDF handles the adding of files to the WSP archive. You specify the file using a path relative to your project’s root. In the above example, the first file written is manifest.xml and it expects the file to be in the root of the project.
For the assembly, you recall the location for the Assembly in the manifest was location=”MyFeature.dll”. The manifest expects this file to be in the root of the WSP. In your Visual Studio, the path is bin\Release\MyFeature.dll, so the builder will grab the file from your bin directory and add it to the WSP’s root.
The next command is new to us, it said “.SET DestinationDir”. This is because the next item written is feature and the manifest expects it at “MyFeature\Feature.xml”. What we are doing is setting the write directory to “MyFeature” by setting the DestinationDir. Now all files will be written to the MyFeature directory, including the “12\TEMPLATE\FEATURES\MyFeature\feature.xml”.
Finally, we write the user control file. The TemplateFile location in our manifest specifies that it will be located at “ControlTemplates\MyFeatureForm.ascx”. We will use DestinationDir to set it to “ControlTemplates” and then write the user control, which is located in our project at “12\TEMPLATE\ControlTemplates\MyFeatureForm.ascx”.
The DDF file only define how the WSP is build. A utility call makecab does the actualy work. It reads the DDF file, copies the files in the DDF into the wsp. One way to have the files generated automatically is to add a script to the post compile event of your project.
cd "$(ProjectDir)" MakeCab /f Package.ddfNow when you compile your project, the event script will run and generate the WSP file.
Conclusion
With tools like WSPBuilder, you can now generate WSP file without fooling around DDF and Manifest files. However, it is still good to understand how the underlying mechanism works. I hope that you have found this article helpful.
How to: Hack a Class Library Project into a Web Application Project
Kind of a weird tip here, but I have ran into a situation where I have needed to do this. Basically, I have had an existing class library (for SharePoint development) and for some reason, I have decided I need to add ASP.NET file types to it (i.e. User Controls, Master Pages, etc.). A class library doesn't have these file types in the Add Item menu so you need a Web Application Project. When it comes down to it a Web Application Project really is the same thing as a class library, it just has some extra settings. So when it comes down to it, you would either have to recreate the project and add your existing files back into it or just hack the XML of your .csproj file. I obviously prefer the latter.
To do this, start by Unloading the Project by right clicking your project and choosing Unload Project. Next Right click on your unloaded project and choose Edit <PrjectName>.csproj. Paste the line below in the first ProjectGroup element. Usually Visual Studio puts it underneath the ProjectGuid element.
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
That is the only change that is required. There are some optional settings that you can put in regarding the configuration of Cassini, but none of them are required to get you going. You can always configure them in Visual Studio. Once you have made the change, save the .csproj file and Reload Project. Once the project is loaded, all of the ASP.NET file types will be present in your Add Item menu. When you compile, it will still compile everything down to a single DLL and you can deploy it just as if it was a regular class library.
About me
Categories
- Code behind variable in aspx pages (1)
- InfoPath (4)
- Search (1)
- SharePoint (3)
- SharePoint 2007 (2)
- SQL Server (1)
- UserProfiles (1)
- VS2008 (1)
Text
About Me
- milap shah
- I am a solution architect working with Microsoft Corporation having 8 years of consolidated experience.
©2008. All rights Reserved



