I have written a RESTful web service that writes calendar events from Sharepoint to personal exchange calendars. The web service is hosted in sharepoint. When I make the call using javascript from the browser, the webservice works. I am trying to make the call from the item added event receiver. When I do this I get a 401 error. We have kerberos set up and I have checked that the identity of the event receiver is the person who created the event. Here is the code form my event receiver:

public override void ItemAdded(SPItemEventProperties properties) {

            using (SPSite site = new SPSite(properties.SiteId)) {
                SPWeb web = site.OpenWeb(properties.Web.ID);
                SPList list = web.Lists[properties.ListTitle];
                string serverUrl = properties.Web.Site.Url;
                String webUrl = properties.Web.Url;
                String itemUrl = properties.ListItem.Url;
                SPFieldUser userField = properties.ListItem.Fields["Absentee"] as SPFieldUser;
                SPFieldUserValue userFieldValue = userField.GetFieldValue(properties.ListItem["Absentee"].ToString()) as SPFieldUserValue;
                SPUser user = userFieldValue.User;
                string requestUrl = webUrl + "/_vti_bin/spews/exchange.svc/" + user.LoginName.Substring(5) + "/appointments?eventUrl=" + webUrl + "/" + itemUrl;
                HttpWebRequest exchangeRequest = (HttpWebRequest)WebRequest.Create(requestUrl);
                exchangeRequest.Method = "POST";
                exchangeRequest.ContentLength = 0;
                WebResponse exchangeResponse = exchangeRequest.GetResponse();

This is my browser code:

function callExchange(userId, itemUrl) {
var req = new XMLHttpRequest(),
    serverUrl = document.location.protocol + "//" + document.domain,
    absoluteWebUrl = serverUrl + _spPageContextInfo.webServerRelativeUrl,
    userUrl = serverUrl + _spPageContextInfo.siteServerRelativeUrl + "/_vti_bin/listdata.svc/UserInformationList(" + userId + ")",

req.open("GET", userUrl, false);
req.setRequestHeader("Content-Type", "application/json");
req.setRequestHeader("Accept", "application/json");
userJSON = $.parseJSON(req.responseText);
loginName = userJSON.d.UserName;
postUrl = absoluteWebUrl + "/_vti_bin/spews/Exchange.svc/" + loginName + "/appointments?eventUrl=" + serverUrl + "/" + itemUrl;
req.open("POST", postUrl, true);
req.setRequestHeader("Content-Length", "0");


Does any one have any idea why the server version would be denied? Is there a better way to make the call? I would really like to have this work in the event receiver so I don't have to write this browser code for every form and view. Thanks.

  • Is this in a Sandboxed solution by any chance? – James Love Mar 22 '13 at 19:52
  • No. It is a farm solution. You can't call a web service from sandboxed code without a full trust proxy. – Blue Murphy Mar 22 '13 at 22:06
  • Does adding authentication to your HttpWebRequest help? This may help get you started: stackoverflow.com/questions/4334521/… – Ryan Erickson Mar 22 '13 at 22:38
  • Yep, was just making sure. – James Love Mar 22 '13 at 22:54

The 401 error is likely because there are no credentials being passed in the web request. Add the following before getting the response. At first use your credentials (or an admin account) to verify that it can work:

exchangeRequest.Credentials = new NetworkCredential("username", "password");

Then to have it run as the current user you can replace it with:

exchangeRequest.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
| improve this answer | |
  • I tried this with my credentials, but it didn't work. I used DefaultCredentials and it worked like a charm. Thank you. – Blue Murphy Mar 25 '13 at 13:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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