I started getting the following error message:
0x80040E09 on SPListItem.Update.
Resolved by granting Update permissions to the WSS database.
Random outpourings of a software developer
I started getting the following error message:
0x80040E09 on SPListItem.Update.
Resolved by granting Update permissions to the WSS database.
Here is an article on fixing SharePoint in a Kerberos environment.
This code will create the list with all of the columns from the Content Type and all of the columns from the BDC Entity. It then updates the default view of the list to show all of these.
This code does use one class that microsoft has marked as do not use in your own application. But since it is the only way that I have found to get this to work….
Identifying the required using clauses is left as an exercise to the reader.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Microsoft.SharePoint;
using Microsoft.Office.Server;
using Microsoft.Office.Server.ApplicationRegistry.MetadataModel;
using Microsoft.Office.Server.ApplicationRegistry.Infrastructure;
using Microsoft.SharePoint.Portal;
using Microsoft.SharePoint.Portal.WebControls;
namespace AddSharePointBDCListNS
{
/// <summary>
/// This console application will add a SharePoint list to a site based upon a content type and a bdc entity.
/// The content type will contain the key field for the bdc data so that the bdc data can be removed and replaced.
/// </summary>
class Program
{
/// <summary>
///
/// </summary>
/// <param name=”args”></param>
static void Main(string[] args)
{
if (args.Length != 8)
{
Console.WriteLine(“AddSharePointBDCList http://site:1234 listName ssp contentType CoreInstance core.Trade_BigList_v TradeRef Trade”);
}
else
{
try
{
AddSharePointBDCList(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
static string ObtainBdcFields(string application,
string entity,
string entityTitle)
{
LobSystemInstance instance = ApplicationRegistry.GetLobSystemInstanceByName(application);
Entity requiredEntity = instance.GetEntities()[entity];
List<string> rawField = new List<string>();
foreach (Field field in requiredEntity.GetFinderView().Fields)
{
rawField.Add(field.Name);
}
rawField.Sort();
StringBuilder fieldList = new StringBuilder();
bool isFirst = true;
foreach (string field in rawField)
{
if (!isFirst)
{
fieldList.Append(“:”);
}
isFirst = false;
fieldList.Append(field);
}
return fieldList.ToString();
}
/// <remarks>
/// This is serious black belt sharepoint. It required a lot of trial and error to get this far.
/// I would like to be able to simply pass the application and the entity but have run out of time.
/// </remarks>
///<summary>
///<param name=”siteUrl”></param>
///
///</summary>
static void AddSharePointBDCList(string siteUrl,
string listName,
string ssp,
string contentType,
string bdcSystemInstance,
string bdcEntity,
string bdcField,
string bdcDisplayField)
{
SPSite site;
try
{
site = new SPSite(siteUrl);
}
catch (Exception ex)
{
throw new Exception(“Unable to find site (” + siteUrl + “)”, ex);
}
SPWeb web = site.OpenWeb();
SPContentType newCT;
try
{
newCT = web.ContentTypes[contentType];
}
catch (Exception ex)
{
throw new Exception(“Unable to find content type (” + contentType + “)”, ex);
}
// I have moved these here since it will prevent a list being created if any of the data is wrong.
try
{
SqlSessionProvider.Instance().SetSharedResourceProviderToUse(ssp);
}
catch(Exception ex)
{
throw new Exception(“Unable to find SSP (” + ssp + “)”, ex);
}
string rawFields;
try
{
rawFields = ObtainBdcFields(bdcSystemInstance, bdcEntity, bdcDisplayField);
}
catch (Exception ex)
{
throw new Exception(“There is something wrong with at least one of the following:: bdcSystemInstance: ” + bdcSystemInstance + ” bdcEntity: ” + bdcEntity + ” bdcDisplayField: ” + bdcDisplayField , ex);
}
/* At this point we have all of the data that we need to recreate the lists! */
// You can’t create a list based upon a user-defined content type but you can do this:
// Add a generic list
Guid listGuid = web.Lists.Add(listName, listName, SPListTemplateType.GenericList);
// … Why that did’nt return the list I’ll never know, use the guid instead
SPList list = web.Lists[listGuid];
// Now mess with the content types:
SPContentType old = list.ContentTypes[0];
list.ContentTypes.Add(newCT);
list.ContentTypes.Delete(old.Id);
list.Update();
// Now add the missing fields to the view.
SPView view = list.DefaultView;
foreach( SPField field in newCT.Fields)
{
if (!view.ViewFields.Exists(field.InternalName))
{
view.ViewFields.Add(field);
}
}
view.Update();
/* I think that this is now minimal */
const string contentTemplate = @”<Field Type=’BusinessData’
DisplayName='{0}’
Required=’FALSE’
StaticName='{0}’
BaseRenderingType=’Text’
Name='{0}’
RowOrdinal=’0′
SystemInstance='{1}’
Entity='{2}’
BdcField='{3}’
Profile=’/_layouts/ProfileRedirect.aspx?Application={1}&Entity={2}&ItemId=’
HasActions=’True’
RelatedField='{4}’
RelatedFieldWssStaticName='{4}’
AddFieldOption=’AddToDefaultContentType, AddFieldToDefaultView’
/>”;
string fieldContent = string.Format(contentTemplate,
bdcDisplayField, //0
bdcSystemInstance, //1
bdcEntity, //2
bdcField, //3
bdcEntity.Replace(“.”,”_x002e_”) + “_ID” //4
);
string fieldName = list.Fields.AddFieldAsXml(fieldContent);
list.Update();
// … You would think that this would be enough, you now need to convince the bdc column to save the
// bdc specific details.
BusinessDataField busField = list.Fields[fieldName] as BusinessDataField;
busField.SystemInstanceName = bdcSystemInstance;
busField.EntityName = bdcEntity;
busField.BdcFieldName = bdcField;
string[] names = rawFields.Split(new char[1] { ‘:’ });
busField.SetSecondaryFieldsNames(names);
busField.Profile = string.Format(“/_layouts/ProfileRedirect.aspx?Application={0}&Entity={1}&ItemId=”, bdcSystemInstance, bdcEntity);
busField.HasActions=true;
busField.Update();
list.Update();
// Lets see if the bdc fields can now be added…
foreach (SPField field in list.Fields)
{
if (!view.ViewFields.Exists(field.InternalName))
{
if (!field.Hidden)
{
view.ViewFields.Add(field);
}
}
}
view.Update();
}
}
}
=== addpage.boo ===
import Microsoft.SharePoint
import System.IO
def addPage(_site as string, _web as string, _page as string, _url as string):
site = SPSite(_site)
web = site.OpenWeb(_web)
folder = web.GetFolder(“”)
folder.Files.Add(_url, File.OpenRead(_page), true)
addPage(argv[0], argv[1], argv[2], argv[3])
The first component is a boo script:
This requires the Boo.Lang.Dll and needs to be compiled with the boo compiler booc (booc warmup.boo)
==== warmup.boo ======
import System.Net
def warmup(url as string):
request = WebRequest.Create(url)
request.Credentials = CredentialCache.DefaultCredentials
request.Method = “GET”
response = request.GetResponse()
response.Close()
for url as string in argv:
print(url)
warmup(url)
The second component is a batch file:
==== Warmup.bat ====
@cscript iisapp.vbs /a MyAppPool /r
@Start /min warmup http://myurl:50002/page1.aspx http://myurl:50002/page2.aspx
@Start /min warmup http://myurl:50002/page3.aspx
These should save you hours of waiting around for SharePoint at the cost of a little bit of load. Beware I am unable to test the first line of the script as I am not currently at a W2k3 box. It recycles a given app pool.
The following is the code from a feature receiver event.
This allows a page to be added to a sharepoint site without using a page library.
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWeb web = properties.Feature.Parent as SPWeb;
FileStream fStream = File.OpenRead(properties.Definition.RootDirectory + \NewPage.aspx);
Web.AllowUnsafeUpdates = true;
SPFolder folder = web.GetFolder(“”);
Folder.Files.Add(“NewPage.aspx”, fStream);
fStream.Close();
}