Sending Email Asynchronously inside a SharePoint workflow - sharepoint

I'm getting a weird threading issue inside a SharePoint workflow that I'd like to learn more about. I'm trying to send an email using SPUtility.SendEmail asynchronously by firing up a new thread to do it. This successfully works at the end of a workflow for a summary email. I tried doing the same to replace a task notification email but ended up receiving the following error:
Microsoft.SharePoint.SPException:
Attempted to make calls on more than
one thread in single threaded mode.
The only difference I can think of is that the task is inside a replication activity so it can create several of these tasks (although testing this it's only creating just the one). What specifically is the replication activity doing behind the scenes that might cause this error when I try to spawn a new thread?
[NOTE]
The reason I'm using threads to send the emails is because SPUtility.SendEmail is a blocking call, and in the case of a slow SMTP server the user might be getting their page back for up to a minute. And the reason I'm sending emails in the first place is because the standard task emails suck big time.

SPUtility.SendEmail uses an SPWeb parameter which is NOT thread-safe. SPSite, SPWeb objects are actually thread-specific so you shouldn't pass them from one thread to another. You should pass the site ID and web URL to the new thread and recreate the SPWeb object there.

Related

Azure Logic App : Gmail Connector "Reply to email (V2)" Action is Creating a different Thread

When using Azure Logic App : Gmail Connector, "When a new email arrives" Trigger, we are receiving Message ID and Thread ID
But on calling "Reply to email (V2)" Action with Message ID received, it is creating a separate thread with the existing thread data but I am not understanding why it is creating a different thread. Is there any way we can get reply in the same thread, the way it happens with Outlook Connector.
Is there any way I can use Thread Id for replying to the same thread? I am not sure what is the use of Thread ID. Please help me.
After reproducing from our end it works fine and we can able to see only one thread Id while using Reply to email (V2). One of the reasons you might be receiving this is that you have applied filters on a particular type of mail and then are moved to another location/folder.
RESULTS:
RUN-1
RUN-2
NOTE: When you are triggering this email and consider if the mail is being replied back to the same location/folder then it would create a loop and trigger many times unless you diable the logic app.

Sharepoint Concurrency Issue

I am totally new to Sharepoint development (Sharepoint 2013), and could use some help.
I inherited a console application where I'm getting this message below:
Your changes conflict with those made concurrently by another user. If you want your changes to be applied, click Back in your Web browser, refresh the page, and resubmit your changes.
Actually, within the application and another console application (both running as jobs), there are numerous using blocks where they are newing up SPSite and SPWeb, opening the same list, and looping through the entries and posting update. These loop are incredibly slow. So the SPSite and SPWeb stays open for a long time, while additional SPSite/SPWeb are new'ed up to the same list.
Should I new up only one SPSite and SPWeb per application and use them globally within the application? Should I grab my list objects and assign them to a .NET List and close out the SPSite/SPWeb and then when I'm ready to update the record to temporarily new up a SPSite/SPWeb for the duration of the Update()? These list items are being updated by the other job as well while marching thru the list and posting updates to the same list. Is that an issue?
In reality, the notion of a Error Log list exists as well. Items are constantly being appended to this list. Would that cause that error message above?
Would create a Retry loop for the Update() work? Or is the issue of the list item updated by another process prevent a successful update?
Thanks.

CRM plugin execution of operations before Exception

I have a plugin that needs to create a bunch of entities, and does so using;
service.Create(Entity);
At the end of the plugin (pre-operation on Update, synchronous) I sometimes need to cancel the save operation. The only way I know how is to throw an exception, but if I do that my service.Create(Entity) does not get executed.
How do I force the service to execute the operations inside the plugin, and then cancel the save by throwing an exception?
EDIT: The code is;
var id = service.Create(newEntity);
throw new Exception("Cancelled Save but created the new entity");
If I throw the exception, the entity does not get created. If I do not throw the exception, the entity does create. I need it to create and also throw the exception so that the save operation is cancelled.
Thanks for any pointers.
Nicknow's answer is correct, but there are still a few ways to accomplish what you want to do.
In your plugin, don't use the OrganizationService from the plugin context. Create your own new OrganizationService just like you would if you were creating a console app. This new OrganizationService won't be subject to the transaction scope of the original OrganizationService.
Create a web service that does the work. From your plugin, call this web service. The web service won't be subject to the transaction scope of the original OrganizationService.
Use ExecuteMultiple. I've never tried this but here's somebody who claims it works: http://crmtidbits.blogspot.com/2014/02/bypass-plug-in-transaction-to-log.html
Hope that helps!
If IPluginExecutionContext.IsInTransaction == true then when an Exception is thrown anything that has been written to the database will be rolled back. You can try registering in the Pre-Validation stage and sometimes that is outside the transaction, but not always.
Just be aware that there is no guarantee it'll always be outside of the transaction. The SDK documents make this very clear - so at anytime an update could occur that puts it in a transaction.
https://msdn.microsoft.com/en-us/library/gg327941.aspx#bkmk_DatabaseTransactions:
Plug-ins may or may not execute within the database transaction of the
Microsoft Dynamics CRM platform. Whether a plug-in is part of the
transaction is dependent on how the message request is processed by
the pipeline. You can check if the plug-in is executing in-transaction
by reading the IsInTransaction property inherited by
IPluginExecutionContext that is passed to the plug-in. If a plug-in is
executing in the database transaction and allows an exception to be
passed back to the platform, the entire transaction will be rolled
back. Stages 20 and 40 are guaranteed to be part of the database
transaction while stage 10 may be part of the transaction.
Any registered plug-in that executes during the database transaction
and that passes an exception back to the platform cancels the core
operation. This results in a rollback of the core operation. In
addition, any pre-event or post event registered plug-ins that have
not yet executed and any workflow that is triggered by the same event
that the plug-in was registered for will not execute.

How to pass a value to SharePoint list event receiver?

I have a SharePoint site page with a document library web part on it, once a document is uploaded to this library, some of the library fields need to be updated according to a parameter of the page url.
I tried doing this with Event Receiver binding on the library, only to find that I cannot get the page url, or rather the parameter, in the Event Receiver. Then Session occurred to my mind, but after asking around and searching a lot, I can only get HttpContext in itemAdding but not itemAdded, what's worse, HttpContext.Current.Session always give me nulll and I'm sure I have put some value into session earlier in somewhere else.
Can someone shed some light on this, any help or advise is deeply appreciated.
SharePoint allows synchronous and asynchronous event receivers. You can get access to HttpContext and SPContext in synchronous receiver, as it runs in worker thread. Read more for accessing HttpContext and how to bind synchronous receiver programmatically.
It's a bit late but for reference I've just seen solution on this page.
It leverages custom control in master page and stores the information into HttpRuntime.Cache. Then access it from within the synchronous event.
The event receiver is not called in the page context. Therefor you can't access the page information. The only approach to this that I can see is to write custom code that prefills the values of the page before you save the item.

Why does my Workflow Service (4.0) variable go null in a DoWhile Activity?

I have a WF service that I'm trying to setup receive activities to "Subscribe" and "Unsubscribe". I'm using This WF Durable Duplex Tutorial as a basis because my service performs callbacks to clients. Basically, think of it as a chat service.
I can make client calls to the two receive activities just fine. What happens is the callback address of the client is passed in to Subscribe() on the service. The address is stored as a variable in the WF service and everything looks like it would work as to be expected.
When a client calls Unsubscribe(), my watch I have set on the address var during debugging shows it as null. So what gives?
Here's the basic setup of my WF service layout...
Everything is enveloped in a DoWhile activity. Inside of that is a Pick activity and two Pick branches. The first branch is for subscribing activities. It has a receive-sendreply activity that assigns the string passed by the client to the WF address var. The second branch handles unsubscribing. The trigger is the Request activity and the client address is again passed in.
From there it goes into a sequence, starting with an If. It checks to see if the unsubscribeAddress equals the address already subscribed. If it does, then it sets the address to String.Empty and sends a success message back to the client.
Why would a variable that's scoped to the enveloping DoWhile activity be implicitly assigned to null? I'm trying to get this to work so I can implement multiple client subscribers from there and work on triggers that invoke callbacks to multiple clients.
CONCAT EDIT: I set a breakpoint at the DoWhile level and my var is null once Unsubscribe() is called. When Subscribe() is invoked, the watch shows a value in the var all the way through. Until I Unsubscribe() with a client. Should I be using a While Activity instead?
Without seeing the workflow I can only make a few guesses but the things I would look for are:
Is the variable scoped to a sequence or something that is inside of the DoWhile activity? BTW there is no benefit ti changing it to a While activity, the only difference is that the condition is tested at the beginning or the end.
Is the variable used somewhere else and cleared that way. Try renaming it and see what gives.
Is there persitence in play and is the type not persisted> I assume its either a string or a Uri and both should be good to go.
Is there a problem with correlation and is your Unsubscribe message being processed by a different workflow? Mare sure the CanCreateInstance is set to false.
try making a class scoped private {get; set;} and see if the problem still rears its head, thats the best I can do without seeing the actual source code as from what you described I cant see any issues.
Wow, ok scary stuff. I had to hand edit the xamlx file earlier and the references I edited for the SendReplyToReceive saved funny when I switched back to the activity designer. It made it look like I had two Unsubscribe()'s and not only that but the correlation handles for each branch were crossing between branches.
I'm all set now. To fix the issue I removed all the messaging activities, dropped in a new ReceiveAndSendReply activity into branch 1's action block. Then I dragged the Receive activity to the Trigger for branch 1 and configured it as I had before. I did the same for branch 2, except I placed the SendReplyToReceive activity below my If activity that validates matching addresses.

Resources