Error registering SharePoint WebDeleting event receiver in some environments - sharepoint

I am trying to register a WebDeleting event receiver within SharePoint. This works fine in my development environment, but not in several staging environments. The error I get back is "Value does not fall within the expected range.". Here is the code I use:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite elevatedSite = new SPSite(web.Site.ID))
{
using (SPWeb elevatedWeb = elevatedSite.OpenWeb(web.ID))
{
try
{
elevatedWeb.AllowUnsafeUpdates = true;
SPEventReceiverDefinition eventReceiver = elevatedWeb.EventReceivers.Add(new Guid(MyEventReciverId));
eventReceiver.Type = SPEventReceiverType.WebDeleting;
Type eventReceiverType = typeof(MyEventHandler);
eventReceiver.Assembly = eventReceiverType.Assembly.FullName;
eventReceiver.Class = eventReceiverType.FullName;
eventReceiver.Update();
elevatedWeb.AllowUnsafeUpdates = false;
}
catch (Exception ex)
{
// Do stuff...
}
}
}
});
I realize that I can do this through a feature element file (I am trying that approach now), but would prefer to use the above approach.
The errors I consistently get in the ULS logs are:
03/11/2010 17:16:57.34 w3wp.exe (0x09FC) 0x0A88 Windows SharePoint Services Database 6f8g Unexpected Unexpected query execution failure, error code 3621. Additional error information from SQL Server is included below. "The statement has been terminated." Query text (if available): "{?=call proc_InsertEventReceiver(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}"
03/11/2010 17:16:57.34 w3wp.exe (0x09FC) 0x0A88 Windows SharePoint Services General 8e2s Medium Unknown SPRequest error occurred. More information: 0x80070057
Any ideas?
UPDATE - Some interesting things I have learned...
I modified my code to do the following:
I call EventReceivers.Add() without the GUID since most examples I see do not do that
Gave the event receiver a Name and Sequence number since most examples I see do that
I deployed this change along with some extra trace statements that go to the ULS logs and after doing enough iisresets and clearing the GAC of my assembly, I started to see my new trace statements in the ULS logs and I no longer got the error!
So, I started to go back towards my original code to see what change exactly helped. I finally ended up with the original version in source control and it still worked :-S.
So the answer is clearly that it is some caching issue. However, when I was originally trying to get it to work I tried IISRESETs, restarting some SharePoint services OWSTimer (this, I believe runs the event hander, but probably isn't involved in the event registration where I am getting the error), and even a reboot to make sure no assembly caching was going on - and that did not help before.
The only thing I have to go on is maybe following steps such as:
Clear the GAC of the assembly that contains the registration code and event hander class.
Do an IISRESET.
Uninstall the WSP.
Do an IISRESET.
Install the WSP.
Do an IISRESET.
To get it working I never did a reboot or restarted SharePoint services, but I had done those prior to getting it working (before changing my code).
I suppose I could dig more with Reflector to see what I can find, but I believe you get to a dead end (unmanaged code) pretty quick. I wonder what could be holding on to the old DLL? I can't imagine that SQL Server would be in some way. Even so, a reboot would have fixed that (the entire farm, including SQL Server are on the same machine in this environment).

So, it appears that the whole problem was creating the event receiver by providing the GUID.
EventReceiverDefinition eventReceiver = elevatedWeb.EventReceivers.Add(new Guid(MyEventReciverId));
Now I am doing:
EventReceiverDefinition eventReceiver = elevatedWeb.EventReceivers.Add();
Unfortunately this means when I want to find out if the event is already registered, I must do something like the code below instead of a single one liner.
// Had to use the below instead of: web.EventReceivers[new Guid(MyEventReceiverId)]
private SPEventReceiverDefinition GetWebDeletingEventReceiver(SPWeb web)
{
Type eventReceiverType = typeof(MyEventHandler);
string eventReceiverAssembly = eventReceiverType.Assembly.FullName;
string eventReceiverClass = eventReceiverType.FullName;
SPEventReceiverDefinition eventReceiver = null;
foreach (SPEventReceiverDefinition eventReceiverIter in web.EventReceivers)
{
if (eventReceiverIter.Type == SPEventReceiverType.WebDeleting)
{
if (eventReceiverIter.Assembly == eventReceiverAssembly && eventReceiverIter.Class == eventReceiverClass)
{
eventReceiver = eventReceiverIter;
break;
}
}
}
return eventReceiver;
}
It's still not clear why things seemed to linger and require some cleanup (iisreset, reboots, etc.) so if anyone else has this problem keep that in mind.

Related

Trouble Updating Observable Collection when Bound to Gridview - UWP C#

Observablecollection is bound to gridview in UWP project. If I try to clear and add data it fails with an error because it can only be modified on the UI thread.
I have set up service broker with SQL to notify the app when there is a change to the data. This is working correctly. However, every time I try to clear and modify the observablecollection I get an exception thrown.
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
EmployeeLists.Add(new Employee { Name = dr[0].ToString(), Loc = dr[2].ToString() });
}
}
This is the code I'm using at first to populate the observable collection. I want to listen for changes which is working. But how do I update the changes and sync them to the observable collection?
I have tried clearing the employeelists observablecollection and then adding everything again. It seems clunky, but doesn't work anyway because It says I cannot modify from another thread. I have tried several solutions online, but I'm not that familiar with ASYNC programming. Can anyone point me in the right direction?!

Coded UI Test change user causes FatalExecutionEngineError returning a AgentRestart.dat

Issue:
I'm running a Coded UI Test with CUITe in VS 2012 Update in C#.
QA agent is falling over and producing a dat file
running in Debug mode
It successfully opens the IE browser window , logs in, attempts to change user in a combo box. the format for these names are 'Mr First Last (username)'
CUITe_HtmlComboBox cboUsers = bw.Get<HtmlComboBox>("Id~user");
string terminatingString = ")";
int i = -1;
foreach(string userPart in cboUsers.Items) //'Mr'
{
if(userPart.EndsWith(terminatingString))
{
if(userPart.Contains("username"))
cboUsers.SelectItem(i);
i++;
}
}
Logs
During debugging VS will throw this
FatalExecutionEngineError was detected
Message: The runtime has encountered a fatal error.
The address of the error was at 0x69c08d3b, on thread 0x1410.
The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code.
Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.
Running through MSTest.exe there is a AgentRestart.dat as follows ( apologies for the
ÿÿÿÿ sMicrosoft.VisualStudio.QualityTools.AgentObject, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 7Microsoft.VisualStudio.TestTools.Agent.AgentRestartInfo m_runIdm_testsCompleted System.Guid ýÿÿÿSystem.Guid _a_b_c_d_e_f_g_h_i_j_k ÂTíÚi©D¹È›ë¤÷
I'm working through the Managed Debugging Assistants. As the debugging is done in the Test Explorer it may not get called. I've kept the code to a minimum, and will include more if needed
Found the answer, couldn't connect to the
telnet ip port for the data source

Why does my SharePoint workflow fail when the client is running Vista or Windows 7?

I have a similar situation to this question.
I have a custom sequential SharePoint workflow, deleoped in Visual Studio 2008. It is associated with an InfoPath form submitted to a form library. It is configured to automatically start when an item is created.
It works sometimes. Sometimes it just fails to start.
Just like the question linked above, I checked in the debugger, and the issue is that the InfoPath fields published as columns in the library are empty when the workflow fires. (I access the fields with workflowProperties.Item["fieldName"].) But there appears to be a race condition, as those fields actually show up in the library view, and if I terminate the failed workflow and restart it manually, it works fine!
After a lot of head-scratching and testing, I've determined that the workflow will start successfully if the user is running any version of IE on Windows XP, but it fails if the same user submits the same form data from a Vista or Windows 7 client machine.
Does anyone have any idea why this is happening?
I have used another solution which will only wait until InfoPath property is available (or max 60 seconds):
public SPWorkflowActivationProperties workflowProperties =
new SPWorkflowActivationProperties();
private void onOrderFormWorkflowActivated_Invoked(object sender, ExternalDataEventArgs e)
{
SPListItem workflowItem;
workflowItem = workflowProperties.List.GetItemById(workflowProperties.ItemId);
int waited = 0;
int maxWait = 60000; // Max wait time in ms
while (workflowItem["fieldName"] == null && (waited < maxWait))
{
System.Threading.Thread.Sleep(1);
waited ++;
workflowItem = workflowProperties.List.GetItemById(workflowProperties.ItemId);
}
// For testing: Write delay time in Workflow History Event
SPWorkflow.CreateHistoryEvent(
workflowProperties.Web,
workflowProperties.WorkflowId,
(int)SPWorkflowHistoryEventType.WorkflowComment,
workflowProperties.OriginatorUser, TimeSpan.Zero,
waited.ToString() + " ms", "Waiting time", "");
}
workflowProperties.Item will never get the InfoPath property in the code above.
workflowProperties.List.GetItemById(workflowProperties.ItemId) will after some delay.
This occurs due to the fact that Vista/7 saves InfoPath forms through WebDAV, however XP uses another protocol (sorry, can't remember at the time). SharePoint catches the "ItemAdded" event before the file is actually uploaded (that is, the item is already created, but file upload is currently in progress).
What you can do for a workaround is to add a dealay activity and wait for 10 seconds as the first thing in your workflow (will actually be longer than ten seconds due to the way workflows are built in SPPS). This way the upload will already have ended when you perform to read the item. To inform the users about what's happening, you can add a "logToHistoryList" activity before the delay.

SPSite.Exists() returns true although the site collection doesn't exists

I'm currently working on a TimerJob which does some site collections management. When the job runs it looks into a list to retrieve the Url of a site collection then it calls SPSite.Exists() to check if the site still exists or not.
To test the TimerJob I delete a site collection but left the corresponding entry in the list. Then I start the TimerJob and step through its code in debug mode. When it comes to the point to check whether the site exists SPSite.Exists() returns true.
When I run the TimerJob a second time for the same site collection the SPSite.Exists() method returns false as it should.
So now I'm wondering why SPSite.Exists() returns the false result when I run the job for the first time. Could this be caused by caching?
When I run the same code outside of the TimerJob SPSite.Exists() returns the correct result every time.
UPDATE
So I did some more debugging and it seems as this problem is really caused by some caching mechanism as it doesn't occur when the Windows SharePoint Services Timer Service was restarted after the test site collection has been deleted and before the TimerJob was started.
At the moment I can't imagine another solution than trying to access the deleted site and catching the exception that will be thrown to determine if the site really exists.
UPDATE 2
After some more tests I realized that the problem doesn't occur for the first call of SPSite.Exists() ( within the TimerJob) after the Timer Service is restarted. The second call (for a different site collection) still leads to the known problem.
UPDATE 3
At the moment I'm using an ugly hack to solve my problem. When SPSite.Exists() returns true although it actually doesn't exist, I create a SPSite object and try to provoke a FileNotFoundException by calling its Usage property. When the exceptions arise I know that the site doesn't exist. Strangely enough after the exception was thrown SPSite.Exists() returns the correct result (false).
Any other suggestions out there?
Bye,
Flo
I had this same issue and tried the HTTP request method but found it to be somewhat slow for checking a large number of sites at once. Instead i ended up using something like this:
public bool SPSiteExists(string url) {
SPSite.InvalidateCacheEntry(new Uri(url), Guid.Empty);
return SPSite.Exists(uri);
}
Same for me. I had a similar problem after I deleted a site-collection I still got true for SPSite.Exists();
The strange thing was, that if i opened the deleted site-collection URL in a browser - the first request resulted in a HTTP 400 error message, whereas the second request was the expected HTTP 404.
My workaround was to just create a HTTP GET for the URL to create the first request and then check for site existence again.
private void touchWeb(string url, System.Net.ICredentials credentials)
{
try
{
Uri uri = new Uri(url);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Credentials = credentials;
request.Method = "GET";
string result = "";
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader readStream = new StreamReader(responseStream, System.Text.Encoding.UTF8))
{
result = readStream.ReadToEnd();
}
}
}
}
catch (Exception) { }
}

Testing Workflow History Autocleanup

I am facing a rather peculiar problem here. We have an OOTB approval workflow, which logs all the workflow history into a workflow history list. This list gets purged every 60 days. To increase this time period for which the workflow history is retained, I googled around and found that I have run this code:
using (SPSite wfSite = new SPSite(siteUrl))
{
using (SPWeb wfWeb = wfSite.OpenWeb(webName))
{
SPList wfList = wfWeb.Lists[listName];
SPWorkflowAssociation _wfAssociation = null;
foreach (SPWorkflowAssociation a in wfList.WorkflowAssociations)
{
if("approval 1" == wfAssociationName.ToLowerInvariant())
{
a.AutoCleanupDays = newCleanupDays;
_wfAssociation = a;
assoCounter++;
}
else
{
_wfAssociation = a;
}
}
wfList.UpdateWorkflowAssociation(_wfAssociation);
}
}
The code works fine, in the sense that it does not throw any exceptions. So far so good. But my problem now is that I need to test whether my code works. So i set the newCleanupDays variable to 0. But i see that new workflow activities are still getting logged in the workflow history list. I can set the variable to 1, but that would mean waiting an entire day to see if the code works..
Is there any way in which I can test my scenario, so that I can set the autocleanup days to 1, and I dont't have to wait an entire day to see if my code works? Is there any way I can "Fool" the system into thinking that 1 day has elapsed? I tried changing the system time and restarting the server and everything, but it didn't work for me.
Changing the system time should work, but you are going to have to kick off the timer job that initiates the workflows. Don't restart the server after the time change.
One warning is that SharePoint really really does not like travelling back in time. Any documents that are created in the "future" are going to have issues. So remember to test in a new web site that can be deleted when you roll back to "now".

Resources