How to pass a value to SharePoint list event receiver? - sharepoint

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.

Related

Hit event on before every action in liferay means pre action event

I need to call the one method before action method calls in portlet controller.
So here I am using a hook like:
Create Hook
Create a class and extend Action.
Override run method write my own logic.
Create portal.properties file and added following line
servlet.service.events.pre=com.liferay.sample.hook.LoginAction
Pointing it fron liferay-hook.xml
Every thing was went fine but here the problem with this one is the created hook is executed each and every time page load but I want execute this hook is only when I click on the Action buttons(Action urls) in any portlet.
Can any help me out on it?
Thanks in Advance.
Naresh Kallamadi
The property you are using relates to service actions, which are invoked before or after every Action. From my experience service actions happens every time a page loads. This would explain the behavior you are seeing.
For more in-depth understanding, the article Overriding Events and working with preactions and postactions in EXT will help.
I think you may want to dig more into the portlet actions and phases to achieve what you may need. Please post back if you have more details (code example of what you have tried etc.) on the exact behavior in the portlet you need help with.
Hope this helps.

How to avoid BusyConversationException in jsf

I'm getting BusyConversationException while navigating through pages in my jsf project. This mostly happens if the user tries to navigate to another page during an ajax call. This also happens when the user clicks on a link right after clicking on another link without waiting for loading of the page.
For example if the user clicks on more than one link which are generated through a code similar to below one we definitely get this exception. Another example is, lets say the user enter a query on a text field, and our application make an ajax call for searching this query. During that query if the user click on some button to navigate to another page BusyConversationException occurs too.
<h:commandLink value="#{theProfile.profileName}"
title="#{theProfile.profileName}"
action="#{profileBean.aProfileSelected}">
<f:setPropertyActionListener target="#{currentProfileWebBean.theProfile}" value="#{theProfile}"/>
</h:commandLink>
I can catch this type of exception in an ExceptionHandler class which extends ExceptionHandlerWrapper class but I can't save my current state and the best I can do for this case is to redirect to main page when this exception occurs.
Is there any solution for avoiding this? Thanks in advance for answers and comments.
As mentioned in the other answers, this happens if an ajax request is still being processed or if an ajax event is triggered prior to the actual click on the submitting commandLink or commandButton (for instance by a change event on an input field).
Therfore it is not possible to avoid BusyConversationExceptions with onclick="preventEventPropagation(event)";, since the AJAX events are not triggered via propagation.
The issue can easily be avoided by listening for running ajax requests and blocking submits until the pending ajax events have been completed.
The issue and solution are explained in more detail in this blog post JSF2 AJAX/Submit conversation issue.
i found this,
Indicates that the container has rejected a request because a concurrent request is associated with the same conversation context.
The container ensures that a long-running conversation may be associated with at most one request at a time, by blocking or rejecting concurrent requests. If the container rejects a request, it must associate the request with a new transient conversation and throw an exception of type BusyConversationException from the restore view phase of the JSF lifecycle.
refer here
I've been seeing this occasionally too. I'm starting to think it's a good idea to put some effort into serializing access to conversations:
Avoid propagating the conversation ID (cid) when you don't need that conversation instance for the target view. Specifically, unrelated navigation links/buttons should suppress the cid parameter (haven't thought about exactly how to do that)
When starting a request that uses an active conversation, disable other UI elements that propagate the conversation and could therefore cause concurrent access. The PrimeFaces or (even better) PrimeFaces Extensions blockUI components work well as a translucent overlay, along with a PrimeFaces p:ajaxStatus to show the busy status.
Begin conversations as late as possible. This will minimize the cases where a long-running conversation would be propagated.
I don't think that any of this is a complete solution, though. As soon as the cid ends up in the location bar (which happens when you do a non-ajax post back of a form when a conversation is active), you potentially lose control over the timing of access to that conversation due to multiple tabs/windows, bookmarks, etc.
I also faced the same problem, when I used to click the .
I have read in one of the book, busyConevrsation happens with that event two actions are happening, so they said use : onclick="preventEventPropagation(event)"; in commandLink to prevent the event propagation for that click. So I have used the same and it's working for me.
So now am not getting the BusyConversationException :)

Communicating between IFRAME and an entity

I couldn't make a request to a remote server using JavaScript in the onload function due to access is denied insanity. So, just to make CRM obey, I set up an IFRAME and connect that to a HTML page running my JavaScript. Now, provided that I get some values inside the script (run in an IFRAME) how can I communicate them to a method in the holding parent?
Not quite sure how to explain it more detailed so please feel free to ask.
The access is denied is the Same Origin Policy. You're going to run into the same problem from the IFRAME unless you're serving the page or just the script src from the same server you're subsequently trying to make the AJAX request to.
Assuming you are doing the latter then you just need to make sure you have unchecked the "Restrict cross-frame scripting" option on the IFRAME you added to the CRM form. From the IFRAME you will now have access to your function that you've defined at global scope on the parent CRM form via window.parent.yourfunctionNameHere(xyz).
postMessage sounds like it might fit.
window.postMessage, when called, causes a MessageEvent to be dispatched at the target window when any pending script that must be executed completes (e.g. remaining event handlers if window.postMessage is called from an event handler, previously-set pending timeouts, etc.). The MessageEvent has the type message, a data property which is set to the string value of the first argument provided to window.postMessage, an origin property corresponding to the origin of the main document in the window calling window.postMessage at the time window.postMessage was called, and a source property which is the window from which window.postMessage is called.
To use window.postMessage, an event listener must be attached:
// Internet Explorer
window.attachEvent('onmessage',receiveMessage);
// Opera/Mozilla/Webkit
window.addEventListener("message", receiveMessage, false);
And a receiveMessage function must be declared:
function receiveMessage(event) {
// do something with event.data;
}
The off-site iframe must also send events properly via postMessage:
<script>window.parent.postMessage('foo','*')</script>
Any window may access this method on any other window, at any time, regardless of the location of the document in the window, to send it a message. Consequently, any event listener used to receive messages must first check the identity of the sender of the message, using the origin and possibly source properties. This cannot be understated: Failure to check the origin and possibly source properties enables cross-site scripting attacks.
Source: https://developer.mozilla.org/en/DOM/window.postMessage
Recently I had the joy of connecting to a web service and retrieve some data. When that’s been achieved, I found myself sitting on the said data not exactly knowing where to put it.
To make the long story short, I used the following source code.
parent.window.Xrm.Page.data.entity.attributes
.get("new_Konrad").setValue("Viltersten");
Notable is the fact that in order to communicate with the parent form, the HTML file (where my JavaScript resided), needed to be placed as a web resource within the CRM structure. By other words, just by pointing to an external “http://some.where/some.thing” we can consume a service but won’t be able to convey the obtained information up the CRM server, at least not when developing a solution for the on-line version.

Sending Email Asynchronously inside a SharePoint workflow

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.

Sharepoint : Event Receiver : Item Adding

Anybody used the "ItemAdding" method successfully in an Event Receiver in Sharepoint for validation?
I think it just can't work properly for validation purposes because it seems that :
You can't access the data you just
entered in a form
If you add an error message,
instead of displaying the form
back with your error, Sharepoint
display the big ugly error page.
Here's what I found so far on the web for the ItemAdding method :
http://www.sharepoint-tips.com/2006/09/synchronous-add-list-event-itemadding.html
http://www.moss2007.be/blogs/vandest/archive/2007/07/20/wss-3-0-event-handler-pre-event-cancelling-issues.aspx
http://www.synergyonline.com/blog/blog-moss/Lists/Posts/Post.aspx?ID=25
Anyway, if somebody successfully used that method, please tell me how because I think that it's just broken/missing something!
Thanks!
You can't use ItemAdding to perform that kind of "friendly" validation checking. If you set e.Cancel = true and set e.ErrorMessage, sharepoint will redirect you to the standard error page and display your message. You can't make it redirect back to your form page.
Rather than trying to hack the built in pages, you should use an infopath or aspx form bound to a content type. Infopath has built-in validation controls and with aspx forms you build yourself you can treat it like any web app and choose your own validation.
No easy way out here I'm afraid.
-Oisin
You can access data that was just added in the form. Look at properties.AfterProperties in the adding/updating event receivers.
An example would be properties.AfterProperties["Title"].
I agree that error handling is a little hard, but I recommend that you do validation in your event receivers in addition to having your UI do validation. If it is not a custom page, then you can add JavaScript to existing pages using a Content Editor Web Part to do the validation.

Resources