5

Survey is set to respond only once. However, is there way to show friendly message instead of following error?

Server Error in '/' Application.
You are not allowed to respond again to this survey.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Runtime.InteropServices.COMException: You are not allowed to respond again to this survey.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:


[COMException (0x81020039): You are not allowed to respond again to this survey.]
   Microsoft.SharePoint.Library.SPRequestInternalClass.IsVotingAllowed() +0
   Microsoft.SharePoint.Library.SPRequest.IsVotingAllowed() +116

[SPException: You are not allowed to respond again to this survey.]
   Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx) +27825266
   Microsoft.SharePoint.Library.SPRequest.IsVotingAllowed() +199
   Microsoft.SharePoint.WebPartPages.ListFormWebPart.OnInit(EventArgs e) +2068
   System.Web.UI.Control.InitRecursive(Control namingContainer) +143
   System.Web.UI.Control.AddedControl(Control control, Int32 index) +271
   System.Web.UI.WebControls.WebParts.WebPartManagerControlCollection.AddWebPartHelper(WebPart webPart) +305
   System.Web.UI.WebControls.WebParts.WebPartManagerControlCollection.AddWebPart(WebPart webPart) +1937774
   System.Web.UI.WebControls.WebParts.WebPartManagerInternals.AddWebPart(WebPart webPart) +63
   Microsoft.SharePoint.WebPartPages.SPWebPartManager.AddWebPartWithRetry(WebPart webPart) +746
   Microsoft.SharePoint.WebPartPages.SPWebPartManager.CreateWebPartsFromRowSetData(Boolean onlyInitializeClosedWebParts) +7123
   Microsoft.SharePoint.WebPartPages.SPWebPartManager.LoadWebParts() +146
   Microsoft.SharePoint.WebPartPages.SPWebPartManager.OnPageInitComplete(Object sender, EventArgs e) +288
   System.EventHandler.Invoke(Object sender, EventArgs e) +0
   System.Web.UI.Page.OnInitComplete(EventArgs e) +11070286
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1674


Version Information: Microsoft .NET Framework Version:2.0.50727.5456; ASP.NET Version:2.0.50727.5456 
2
  • 1
    The solutions from @Vadim is working and should be marked as an answer for this question.
    – Mika A.
    May 21, 2015 at 8:45
  • still I got error page I add the javascript in "../../Siteassets/SurveyOps.js" but still
    – user47824
    Oct 14, 2015 at 8:17

2 Answers 2

8

The suggested solution is to add client side validation if user has already responded to survey when the "Respond to this event" button clicked. If validation will fail then display user friendly message otherwise display the original response form. It will allow to avoid this exception to occur.

Solution

Override JavaScript function for opening response form NewItem2

//override NewItem2 function
var NewItem2 = (function () {
    var NewItem2Orig = NewItem2;

    return function() {
        var evt = arguments[0];
        var url = arguments[1];

        //Read survey for current user to find out if he have already voted   
        readSurveyVotes(function(votesCount){
            //if voted then display custom message 
            if(votesCount > 0) {
                window.alert('You have already voted to this survey.');
            }
            //if not, call original function for opening response form
            else {
                NewItem2Orig(evt, url);
            } 
        });
    };

})();

Reading survey votes for current user

function readSurveyVotes(cbSurveyResult)
{
        var context = new SP.ClientContext.get_current();
        var web = context.get_web();
        var list = web.get_lists().getByTitle("Survey");
        var viewXml = '<View><Where><Eq><FieldRef Name="Author"/><Value Type="Integer"><UserID Type="Integer"/></Value></Eq></Where></View>';
        var query = new SP.CamlQuery();
        query.set_viewXml(viewXml);
        var items = list.getItems(query);
        context.load(items);
        context.add_requestSucceeded(onLoaded);
        context.add_requestFailed(onFailure);
        context.executeQueryAsync();
        function onLoaded() {
            var voteCount = items.get_count();
            cbSurveyResult(voteCount)
        }
        function onFailure() {
            cbSurveyResult(null);
        }
}

Usage

Save the code to JavaScript file and add reference to this file in overview.aspx page, like shown below:

<asp:content contentplaceholderid="PlaceHolderAdditionalPageHead" runat="server">
    <SharePoint:RssLink runat="server"/>
    <SharePoint:CssRegistration runat="server" name="Themable/survey.css">
    </SharePoint:CssRegistration>
    <script type="text/javascript" src="/_layouts/SE/SurveyOps.js"></script>
</asp:content>

enter image description here

4
  • 1
    Vadim, This looks promising. I am trying to incorporate this code but need to understand what are these arguments that you have in your code. What values do they bring in with them, and pass them to NewItem2Orig(evt, url): var evt = arguments[0]; var url = arguments[1]; I am trying to place this code on a custom web part page, on a button [Take the Survey] click. So do I need to hard-code these values or anything like that? Any advice would help. Thanks, NCH.
    – user39639
    Feb 13, 2015 at 16:22
  • The arguments object is an Array-like object corresponding to the arguments passed to a function, so this is how arguments from original NewItem2 function are passed. I believe you could just follow the instruction that I've provided in the answer. That's it ;) Feb 13, 2015 at 20:29
  • 1
    I have used this code in SP2013 and it works fine. I have added some improvement to let it work with any survey list. I replaced : var list = web.get_lists().getByTitle("Survey"); with: var list = web.get_lists().getById(_spPageContextInfo.pageListId);
    – Mika A.
    May 20, 2015 at 15:00
  • 1
    This was super helpful! I expanded upon this a little bit and made a more generic solution to use for multiple surveys: (sregan.com/2018/04/sharepoint-survey-creating-friendly.html)
    – Sean Regan
    Apr 6, 2018 at 20:54
4

While working with the above answer by Vadim Gremyachev instead of showing the alert message to the user who is already responded, it shows to all the users. By modifying the above code to some extent it is working fine.

//override NewItem2 function
var NewItem2 = (function () {
    var NewItem2Orig = NewItem2;

    return function() {
        var evt = arguments[0];
        var url = arguments[1];

        //Read survey for current user to find out if he have already voted   
        readSurveyVotes(function(isCurrentUserRespond){
            //if voted then display custom message 
            if(isCurrentUserRespond) {
                window.alert('You have already voted to this survey.');
                return ;
            }
            //if not, call original function for opening response form
            else {
                NewItem2Orig(evt, url);
            } 
        });
    };

    function readSurveyVotes(cbSurveyResult)
    {
        var isCurrentUserRespond = undefined;
        var context = new SP.ClientContext.get_current();
        var web = context.get_web();
        var list = web.get_lists().getByTitle("Survey");      
        var viewXml = '<View><Where><Eq><FieldRef Name="Author"/><Value Type="Integer"><UserID Type="Integer"/></Value></Eq></Where></View>';
        var query = new SP.CamlQuery();
        query.set_viewXml(viewXml);
        var items = list.getItems(query);
        context.load(items);
        context.add_requestSucceeded(onLoaded);
        context.add_requestFailed(onFailure);
        context.executeQueryAsync(function(){
            var enumerator = items.getEnumerator();
            while (enumerator.moveNext()) {
                var item = enumerator.get_current().get_fieldValues().Author;
                if(item.get_lookupId() == web.get_currentUser().get_id()){
                    isCurrentUserRespond = true;
                    cbSurveyResult(isCurrentUserRespond);                    
                    break;
                }
            }
        });
        function onLoaded() { 
                  if(!isCurrentUserRespond){
                       cbSurveyResult(null); 
                  }
         }
         function onFailure() {
             cbSurveyResult(null);
         }
     }   
})();

Not the answer you're looking for? Browse other questions tagged or ask your own question.