Welcome to Comunidade Bloggers |create|it| Sign in | Join | Help
High Availability Configuration in Velocity

If you create a new cache with secondaries enabled

 new-cache -CacheName NamedCache1 -Secondaries 1

you need to have more than one cache host, otherwise the cache won't work. In my first velocity test I only had one server and created the cache with the previous command. After that I was trying to put objects to the cache with no success.

Taken from the Velocity CTP 2 documentation:

"High availability is configured at the cache level in the cluster configuration settings. You can only enable it when you create the cache. To do this, use the PowerShell 1.0 new-cache command, with the secondaries parameter equal to 1. This tells the cache administration PowerShell cmdlets that you want one copy of each cached object or region."

The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>)

Because I have pages with the markup <%= someVariable%> like

<script type="text/javascript">
            
  function ConfirmCallBack(arg)
  {
    if (arg)
     <%= this._nextPostBack%>
  }
</script>

I get the following error: "The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %><% ... %>)."

To correct it I had to change from

<%= this._nextPostBack%>

to

<%# this._nextPostBack%>

and in the PageLoad event add the call to Page's DataBind method

protected void Page_Load(object sender, EventArgs e)
{
  ...
  Page.DataBind();
}
Codesmith, netTiers and reserved words

Started today using Codesmith tools today after a year or so since the last time that I used this great generation template based tool.

I had to generate all the layers of an existent portal and I decided to use the netTiers templates to accomplish this task.

And here are the problems that I had to solve:

  • In the Entities templates:

I have a table named Entity that conflicts with the auxiliary class of the netTiers templates. It seems that the templates already generate a class called Entity and because there is a table called Entity there was a conflict.

I solved that using the alias text file feature of the templates that allows me to define a alias for any table that I have. So I just inserted a new line in my alias text file like this:

Entity:MyEntity

With this alias, netTiers generated a class for my table named MyEntity that didn't conflict with his own class Entity.

  • In the Data templates:

I had a table with two foreign keys. But the problem was that the foreign keys were on the same column of the table but referencing two different tables.

The problem was that netTiers generated two methods with the same name and signature GetByColumnForeingKey.

I had to change the schema and use two columns, each one referencing a different column in a different table.

  • In the Domain templates:

I have views in my database and I had compilation problems with the generated classes for these views.

For each view there are two generated files/classes:

MyView.cs and MyViewServiceBase.generated.cs

Where MyView inherits from MyViewBase. Because MyViewBase doesn't exist there was a compilation problem. I just had to strip the "Service" word from the netTiers templates so the file/class generated was MyViewBase.cs instead of MyViewServiceBase.cs

Another problem was with a table with a "Type" column. This gives this error:

Error    1    An object reference is required for the non-static field, method, or property 'TableBase.Type.get'    Domain\TableBase.generated.cs    1394    57    Domain

The generated code was

DeepLoad(entity, false, DeepLoadType.ExcludeChildren, Type.EmptyTypes);

I had to change the template so to genreate

DeepLoad(entity, false, DeepLoadType.ExcludeChildren, System.Type.EmptyTypes);

  • In the Data.SqlClient templates:

There was an ambiguous table named Parameter. netTiers already creates a class named Parameter so I just had to add another line in my alias text file

Parameter:MyParameter

  • And finally in the web templates:

There was an ambiguous table named Page. I just had to add another line in my alias text file.

Page:MyPage

Conditional Post-build event in Visual Studio 2008

I have a class library project where I want to add the assembly to the GAC but only when the configuration is Debug.

The solution is:

if "$(ConfigurationName)" == "Debug" "C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\"gacutil /i "$(TargetPath)" /f

PCNS Installation

First of all, thanks to Mário Rufino and Luis Guido from Microsoft Portugal for providing support during the PCNS installation.

PCNS was installed in two domain controllers for the same domain in a large forest. Because none of the servers had the Schema Master role, the first time that the PASSWORD CHANGE NOTIFICATION SERVICE.MSI was executed was to update the schema in the Schema Master.

After the schema update we had to wait for the schema propagation to take place so we waited until the schema was updated thru all the domain controllers.

After that we just had to execute once more the PASSWORD CHANGE NOTIFICATION SERVICE.MSI in the two domain controllers that are going to receive the requests for password changes.

Change MOSS 2007 server to another Windows 2003 Domain

 

Last week I found that some emails weren't sent by sharepoint. When I created an alert I received an email saying that the alert was just created but after some change in the list no email was sent.

The same problems happened with approval workflows. The email saying the the workflow just started was sent to the document owner but the other emails for the approvers never arrived.

After digging a while in sharepoint admin I found that in the timer job definitions haven't run for some days. Even those jobs with a frequency of minutes.

I also found that the last day that they ran successfully was the day that the IT team decided to change the moss server from one domain to another :)

I've followed these instructions How to change service accounts and service account passwords in SharePoint Server 2007 and in Windows SharePoint Services 3.0 and every thing seems fine now. I'll wait for now...

@echo off
rem other app pools
echo *** Updating app pool passwords
"%commonprogramfiles%\Microsoft Shared\Web server extensions\12\BIN\Stsadm.exe" -o updateaccountpassword
-userlogin %1 -password %2 -noadmin
rem central admin
echo *** Updating Central Admin password
"%commonprogramfiles%\Microsoft Shared\Web server extensions\12\BIN\Stsadm.exe" -o updatefarmcredentials
-userlogin %1 -password %2
rem ssp - new
echo *** Updating ssp password for new installs
"%commonprogramfiles%\Microsoft Shared\Web server extensions\12\BIN\Stsadm.exe" -o editssp
-title "SharedServices1" -ssplogin %1 -ssppassword %2
rem ssp - upgrade
echo *** Updating ssp password for upgraded installs
"%commonprogramfiles%\Microsoft Shared\Web server extensions\12\BIN\Stsadm.exe" -o editssp
-title "Default Web Site" -ssplogin %1 -ssppassword %2
rem osearch
echo *** Updating osearch password
"%commonprogramfiles%\Microsoft Shared\Web server extensions\12\BIN\Stsadm.exe" -o osearch
-farmserviceaccount %1 -farmservicepassword %2
echo *** MANUAL UPDATE NEEDED. To update the password, visit the SSP Web application page,
click Search Settings, and then click Default Content Access Account.
rem spsearch
echo *** Updating spsearch password
"%commonprogramfiles%\Microsoft Shared\Web server extensions\12\BIN\Stsadm.exe" -o spsearch
-farmserviceaccount %1 -farmservicepassword %2
echo *** Updating spsearch content access account
"%commonprogramfiles%\Microsoft Shared\web server extensions\12\BIN\stsadm.exe" -o spsearch
–farmcontentaccessaccount %1 -farmcontentaccesspassword %2
rem restarting IIS
echo *** Doing soft restart of IIS
iisreset /noforce
echo on
Approval status, MOSS and Sharepoint Designer

I was creating a SPD workflow that checks the approval status field. When you add this condition in SPD, the designer automatically gives you a combo box with all the possible values for the approval status field: 1;#Rejected, ...

This works fine if you have your site in English. In my case, I have my site in Portuguese, so the designer gives me the options in Portuguese: 1,#Rejeitado

But, when the workflow is running the actual value for the approval status that is used to check the IF condition is the English value

if 1;#Rejected equals 1;#Rejeitado then

This always returns false. The first argument is given by moss and the other is from the workflow rules built with the SPD.

To solve this bug I found a workaround. I've created a workflow string variable that whaen the workflow starts receives the approval status value.

Next, instead of comparing the approval status field, I compare the workflow variable with "1;Rejected". This is possible because in this case I have a text box to fill the value instead of the combo box.

Enable Soap logs for Windows Live MA 2.0

At c: you find an xml file - SoapTraceConfig.xml - where you can enable the soap logs.

<?xml version='1.0'?>
<SoapTrace>
    <!--Possible Flag values: AllRequests, FailedRequests, SuccessfulRequests, NoRequests-->
    <Flag>NoRequests</Flag>
    <!--Absolute path to store Soap Request/Response Xmls.  -->
    <FilePath>C:\SoapLogs\</FilePath>
</SoapTrace>

You just have to replace the Flag value by AllRequests to get detailed log files

Windows Live MA 2.0 additionally attributes

Thanks to Shawn Lloyd from Microsoft support team for this information.

I tried to set some additionally attributes like country, timezone, ..., but I was getting some errors in the export log file

<Export>
<BeginExport time="12-11-2007 10:37:06">
</BeginExport>
<ExportEntry time = "12-11-2007 10:37:10" SigninName = "XXX@YYY.pt" ModType = "Add">
<error action="Exception" time="12-11-2007 10:37:14">
<Message>
<![CDATA[[Exception] : <ErrorCode>0x80048112</ErrorCode>
<ErrorDescription>Multiple Errors Occurred</ErrorDescription>
<MultipleErrors>
  <Error>
    <ErrorCode>0x80044513</ErrorCode>
    <ErrorDescription>No error description</ErrorDescription>
  </Error>
</MultipleErrors><p:userData xmlns:p="http://schemas.microsoft.com/Passport/User"><p:dataOwner>00037FFE8B02F0CF</p:dataOwner><p:propertyCollection name="Addresses_CS"><p:property name="Home.Country">PT</p:property></p:propertyCollection><p:propertyCollection name="Authorization_CS"><p:property name="MSNTOUVersion">-1</p:property><p:property name="F2_Hotmail">1</p:property></p:propertyCollection></p:userData>
[Stack trace] :    at Microsoft.Passport.MIIS_ExtensibleMA.PassportMA.HandleSoapException(String strExceptionSource, String strRelatedInfo, SoapException e)
   at Microsoft.Passport.MIIS_ExtensibleMA.PassportMA.CreateUserProfile(ProfilePropertyBag ProfBag, Boolean fF2Hotmail, Boolean& fProfDup)
   at Microsoft.Passport.MIIS_ExtensibleMA.PassportExtensibleMA.ExportEntry(ModificationType modType, String[] astrChangedAttributes, CSEntry csEntry)
[Source] :
]]>
</Message>
</error>

</ExportEntry>
<EndExport time="12-11-2007 10:37:14"/>
</Export>

It seems that there are some attributes that are interdependent so here is the dependencies that I'm aware:

-------------------------------------------------------
| Attribute | Required Attributes |
-------------------------------------------------------
|Birthdate | Country | | |
|Country | Birthdate | | |
|TimeZone | CountryCode | RegionCode | |
|RegionCode | Country | | |
-------------------------------------------------------

I tried to set the birthday (dd:mm:yyyy) (yes! colons instead of hyphens) and the country and it worked!

Install Live@Edu pfx certificate

Before install Windows Live ID Management Agent 2.0 place the PassportMA_GlobalConfig.xml under \Extensions folder.

The PassportMA_GlobalConfig.xml that Microsoft gives you doesn't have defaultcertski element specified. But after you install the MA with the correct certificate the defaultcertski will be filled with the correct value.

Windows Live ID and MIIS Service Account

To the management agent work correctly with Windows Live the MIIS Service Account must be a member of the local administrators group.

If you don't follow this rule you get a stop-extension-dll-exception and in the event log you get:

"System.NullReferenceException: Object.reference not set to an instance of an object"
at
Microsoft.Passport.MIIS_ExtensibleMA.PassportExtensibleMA.WriteLog(String type, String message, String action, String SigninName, string Password, String strNow)"

Custom Action for Sharepoint Designer

I'm going to create a custom action for Sharepoint Designer that creates a discussion thread in a discussion list based on the current list item.

I'm going to use the code found here and put it into a SPD custom action.

First create a Workflow Activity Library project in Visual Studio 2005.

 

Rename the Activity1 to MyCustomActivity and add a Code activity.

 

Add the Microsoft.Sharepint.dll and Microsoft.Sharepoint.WorkflowActions.dll assembly reference

Now we're going to create the input properties from where we're going to receive input data from the workflow.

public static DependencyProperty ListIdProperty = DependencyProperty.Register

("ListId", typeof(string), typeof(MyCustomActivity));

 

The ListIdProperty is going to receive the list ID of the list item that we're going to copy to the discussion list (a string representation of the Guid)..

public static DependencyProperty ToListIdProperty = DependencyProperty.Register

("ToListId", typeof(string), typeof(MyCustomActivity));

 

The ToListIdProperty is going to receive the discussion's list ID (a string representation of the Guid).

public static DependencyProperty ListItemProperty = DependencyProperty.Register

("ListItem", typeof(Int32), typeof(MyCustomActivity));

 

This is the list item ID

public static DependencyProperty __ContextProperty = DependencyProperty.Register

("__Context", typeof(WorkflowContext), typeof(MyCustomActivity));

 

And this is a special property that is going to have the workflow context to have access to the current SPWeb.

Then add the public properties

[Description("My description which can be any text I want.")]

[Category("My category which could be anything.")]

[ValidationOption(ValidationOption.Required)]

[Browsable(true)]

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

public string ListId

{

get {return ((string) (base.GetValue(MyCustomActivity.ListIdProperty)));}

set {base.SetValue(MyCustomActivity.ListIdProperty, value);}

}

 

[Description("My description which can be any text I want.")]

[Category("My category which could be anything.")]

[ValidationOption(ValidationOption.Required)]

[Browsable(true)]

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

public string ToListId

{

get {return ((string) (base.GetValue(MyCustomActivity.ToListIdProperty)));}

set {base.SetValue(MyCustomActivity.ToListIdProperty, value);}

}

 

[Description("My description which can be any text I want.")]

[Category("My category which could be anything.")]

[ValidationOption(ValidationOption.Required)]

[Browsable(true)]

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

public Int32 ListItem

{

get {return ((Int32) (base.GetValue(MyCustomActivity.ListItemProperty)));}

set {base.SetValue(MyCustomActivity.ListItemProperty, value);}

}

 

[Description("My description which can be any text I want.")]

[Category("My category which could be anything.")]

[ValidationOption(ValidationOption.Required)]

[Browsable(true)]

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

public WorkflowContext __Context

{

get {return ((WorkflowContext)(base.GetValue(MyCustomActivity.__ContextProperty)));}

set {base.SetValue(MyCustomActivity.__ContextProperty, value);}

}

 

Now just add the following code to the Code activity handler

private void _mainCodeActivity_ExecuteCode(object sender, EventArgs e)

{

// get the list

SPList sourceList = __Context.Web.Lists[new Guid(ListId)];

 

// get list item

SPListItem item = __Context.GetListItem(sourceList, ListItem);

 

// get the discussion list

SPList targetList = __Context.Web.Lists[new Guid(ToListId)];

 

// create the discussion item

SPListItem discussionItem = SPUtility.CreateNewDiscussion(targetList.Items, item.Title);

discussionItem.Update();

}

 

Sign the project with a key, compile and put the assembly in GAC.

 

Now you have to define the new action in the WSS.ACTIONS file found in \12\TEMPLATE\1033\Workflow

<Action Name="My Custom Action"

ClassName="SPDCustomActions.MyCustomActivity"

Assembly="SPDCustomActions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a980f97a0f622f27"

AppliesTo="all"

Category="List Actions">

<RuleDesigner Sentence="Create discussion item in %1 to %2.">

<FieldBind Field="ListId,ListItem" Text="this list" Id="1" DesignerType="ChooseListItem" />

<FieldBind Field="ToListId" Text="this list" Id="2" DesignerType="ListNames" />

</RuleDesigner>

<Parameters>

<Parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />

<Parameter Name="ListItem" Type="System.Int32, mscorlib" Direction="In" />

<Parameter Name="ToListId" Type="System.String, mscorlib" Direction="In" />

<Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In" />

</Parameters>

</Action>

 

Then add the following line to the web.config file of your site collection

<authorizedType Assembly=" SPDCustomActions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a980f97a0f622f27" Namespace=" SPDCustomActions" TypeName="*" Authorized="True" />

 

That's it! Test the action in Sharepoint Designer:

 

Add a custom section to web.config

If you have created a custom section like this, and if you want to add it programmatically to web.config then you have to:

  1. Use the WebConfigurationManager class and open the web

Configuration config = WebConfigurationManager.OpenWebConfiguration(path, site);

From MSDN

path

The virtual path to the configuration file.

site

The name of the application Web site, as displayed in IIS configuration.

 

  1. Create a ConfigurationSectionGroup and add it to the Configuration object

ConfigurationSectionGroup sectionGroup = new ConfigurationSectionGroup();

config.SectionGroups.Add("GROUP_NAME", sectionGroup);

 

  1. Create a new instance of your section (MyCustomSection) and add it to the section group

MyCustomSection section = new MyCustomSection ();

sectionGroup.Sections.Add("SECTION_NAME", section);

 

  1. Fill your custom section properties

section.Property1 = "0123456789";

section.Property2 = "Lorem ipsum dolor sit amet";

 

  1. And save the configuration

config.Save();

If you take a look at your web.config you will see that it was modified programmatically as you specified. I use this technique in the setup process of sites. Cool!

How to upload a list template

public static SPFile UploadListTemplate(string siteUrl, string templatePath)

{

using (SPSite site = new SPSite(siteUrl))

{

SPDocumentLibrary templates = (SPDocumentLibrary)site.GetCatalog(SPListTemplateType. ListTemplateCatalog);

 

System.IO.FileInfo fileInfo = new System.IO.FileInfo(templatePath);

byte[] bytes = System.IO.File.ReadAllBytes(fileInfo.FullName);

 

return templates.RootFolder.Files.Add(fileInfo.Name, bytes);

}

}

How to upload a site template

public static SPFile UploadWebTemplate(string siteUrl, string templatePath)

{

using (SPSite site = new SPSite(siteUrl))

{

SPDocumentLibrary templates = (SPDocumentLibrary)site.GetCatalog(SPListTemplateType.WebTemplateCatalog);

 

System.IO.FileInfo fileInfo = new System.IO.FileInfo(templatePath);

byte[] bytes = System.IO.File.ReadAllBytes(fileInfo.FullName);

 

return templates.RootFolder.Files.Add(fileInfo.Name, bytes);

}

}

More Posts Next page »