2

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) {
        base.ItemAdded(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(),
    userJSON,
    serverUrl = document.location.protocol + "//" + document.domain,
    absoluteWebUrl = serverUrl + _spPageContextInfo.webServerRelativeUrl,
    userUrl = serverUrl + _spPageContextInfo.siteServerRelativeUrl + "/_vti_bin/listdata.svc/UserInformationList(" + userId + ")",
    postUrl,
    loginName;

req.open("GET", userUrl, false);
req.setRequestHeader("Content-Type", "application/json");
req.setRequestHeader("Accept", "application/json");
req.send();
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");
req.send();

}

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.

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

1 Answer 1

1

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;
1
  • I tried this with my credentials, but it didn't work. I used DefaultCredentials and it worked like a charm. Thank you. Mar 25, 2013 at 13:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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