Tuesday, March 13, 2012

Fixing the Elements.xml file causing a deployment error

Here is the error that I got:
Error occurred in deployment step 'Activate Features': Operation is not valid due to the current state of the object
This occurs when you rename your namespace without also updating the "class" value in the Elements.xml file.

Here are the contents of the Elements.xml file:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Receivers ListTemplateId="108">
    <Receiver>
      <Name>EmailReciever</Name>
      <Type>EmailReceived</Type>
      <Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>
      <Class>MyNameSpace.MyProject.MyClass</Class>
      <SequenceNumber>10000</SequenceNumber>
    </Receiver>
  </Receivers>
</Elements>


Here is the Feature's code:
using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
namespace MyNameSpace.MyProject
{

 public class MyClass : SPEmailEventReceiver
 {
  public override void EmailReceived(SPList list, SPEmailMessage emailMessage, String receiverData)
  {
   base.EmailReceived(list, emailMessage, receiverData);
  }
 }
}


The error occurs when the "class" value is not exactly "Namespace" dot "ClassName"  I've highlighted the pieces above, that make up the "class" value.  Since 2-part namespaces are common I've used that as an example.

Thursday, February 23, 2012

Comparing Fields to See if Values Have Changed in the ItemUpdating Method

You cannot get information about what was before the event in the '-ed' EventReceiver, only in the '-ing'.

So, within the public override void ItemUpdating(SPItemEventProperties properties) method...

- The "before" updating value is obtained like this;
var beforeValue = properties.ListItem["Column Name"].ToString();

- The "after" updating value is obtained like this;
var afterValue = properties.AfterProperties[properties.ListItem.Fields["Column Name"].InternalName];

Before making a beforeValue == afterValue comparison you may need to type check these values.

Changing the "Created By" Value in a SharePoint List Item

C#


// Where "item" is of type SPItem
item["Created By"] = web.EnsureUser("AD account name").ID;
item.UpdateOverwriteVersion();

Thursday, January 26, 2012

Toggle Debugging on/off for a Custom Code Web Part in SharePoint

C#
When I render my custom coded SharePoint Web Part, it helps to display extra information to assist me in troubleshooting. I can do this by constructing my web part like this...

...
using System.Web.UI.WebControls.WebParts;
...
public class MyCustomWebPart : WebPart
{
  protected override void CreateChildControls()
  {
    string paramOne = "One";
    this.Controls.Add(new LiteralControl("paramOne=" + paramOne + <br/>));
  }
}

So that my custom Web Part displays "paramOne=One"  Useful for debugging when I want know the value of internal parameters in code.

However, I don't want my user's to see my debugging information. I only want to turn it on in my local browser instance. I do this by adding to the Query String "?debug=true"  So on the end of my URL I append the Query String and update my Controls.Add statement with the following code.

bool.TryParse(Page.Request.QueryString["debug"], out debugOn);
if (debugOn) this.Controls.Add(new LiteralControl("paramOne=" + paramOne));

Wednesday, January 25, 2012

SharePoint Set the Value of a Yes/No Field in Code

C#


// Where "item" is of type SPItem
// how to read
bool result = Convert.ToBoolean(item["YesNoField"]);

// how to write
item["YesNoField"] = true;
item.Update();

Thursday, January 12, 2012

Available Headers in the SPEmailMessage Object

It couldn't find a complete list of email headers for Microsoft.SharePoint.Utilities.SPEmailHeader, so I've compiled one here;

Here's a sample usage that will return the raw email address of the sender...
// emailMessage is of the type SPEmailMessage
string EmailAddress = emailMessage.Headers["Return-Path"].ToString();
// will return "sender@domain.com"

string EmailAddress = emailMessage.Headers["From"].ToString();
// will return "Sender Contact Name <sender@domain.com>"


Ordinal Name Example
1 x-reciever "recipient@domain.com"
2 Received "from IncomingMailServer([IP])..."
3 Received "from IncomingMailServer([IP])..."
4 From "Sender Contact Name <sender@domain.com>"
5 To "Recipient Contact Name <recipient@domain.com>"
6 Subject "Subject Text"
7 Thread-Topic "Topic Text"
8 Thread-Index guid
9 Date ddd, dd mmm yyyyy hh:mm:ss +0000
10 Message-ID "UniqueId@IncomingMailServer"
11 Accept-Language "en-US"
12 Content-Language "en-US"
13 X-MS-Has-Attach "yes" or ""
14 X-MS-TNEF-Correlator ""
15 x-originating-ip "[IP]"
16 Content-Type ??
17 MIME-Version "1.0"
18 Return-Path "sender@domain.com

Here's a handy way to parse out the date...
DateTime sent = DateTime.Parse(emailMessage.Headers["Date"]);