If you see one of my previous post (http://netsourcecode.blogspot.com/2011/09/using-javascript-spjs-in-web-parts-in.html) you will notice I play around with an ASP.NET Application page and one web part from Sharepoint 2010 to display the current user in a message box. I also query a list with another button. I do all of this with JavaScript(SP.js)
The fact is that Andy, my work mate, came on Friday with the idea of detecting a user, query it by getting the properties of the USER PROFILE in a modal form. Good challenge isn’t it?, he is a good man so I always I accept his challenges. I start studying the documentation for the SP.js library and after hours trying to find the way to access to custom user properties I couldn't find anything. You can only get the name, email etc… basic stuff but if you want something else, forget it.
Andy was looking for two fields he created:
- Department
- Title
My limitation was extreme, I didn’t have access to the Sharepoint.Client.dll, JavaScript or the Server Model, so I decided to implement the Sharepoint Web Services against JavaScript and use both platforms JavaScript (SP.js) and Web Services (/_vti_bin/UserProfileService.asmx with the method GetUserPropertyByAccountName()).
I have to admit it was hard work, but at the end I managed to make it work.
In the code I am going to post are three buttons which call 3 functions:
- SayHello(): It says hello.
- DisplauUser(): It displays the current user.
- DisplayList(): Displays the “remaining seats”(custom metadata field) of the Shared Documents list.
What do we need to make this work?
- Visual Studio 2010.
- Sharepoint 2010.
- A list called “Shared Documents” with an extra field called remaining seats.
- Two extra fields in the user profile (Department, Title).
- Change the references in the JavaScript to the URLs
- And good luck…
You need to create an application page to run this thing. You can download the project I create in http://netsourcecode.blogspot.com/2011/09/using-javascript-spjs-in-web-parts-in.html and paste the code in the form, if you don’t want to work.
2 PARTS
-First Part: JavaScript Code
-Second Part: ASP.NET Code behind.
1 Part JavaScript:
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %><%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %><%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %><%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %><%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %><%@ Import Namespace="Microsoft.SharePoint" %><%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %><%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GetUsers.aspx.cs" Inherits="netsourcecodeJavaScript.Layouts.netsourcecodeJavaScript.GetUsers" DynamicMasterPageFile="~masterurl/default.master" %><asp:Content ID="PageHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server"><% #if SOME_UNDEFINED_CONSTANT %><script type="text/javascript" src="/_layouts/SP.debug.js" ></script><script type="text/ecmascript" src="/_layouts/SP.js" ></script><script type="text/ecmascript" src="/_layouts/SP.Core.js" ></script><script type="text/ecmascript" src="/_layouts/SP.Runtime.Debug.js" ></script><% #endif %><script language="ecmascript" type="text/ecmascript">//## Activate this function if you want to load the script at the very beginig//ExecuteOrDelayUntilScriptLoaded(DisplayList, "sp.js");//## Variablesvar context = null;var web = null;var currentUser = null;var collListItems = null;var username = null;var loginname = null;var isgettinglist = false;//## 1//## This function gets the login name and display it in a MessageBoxfunction DisplayUser() {isgettinglist = false;GetUserData();}//## 2//## This function displays the values from the listfunction DisplayList() {isgettinglist = true;GetUserData();}//## 3//## This function says hello.function SayHello() {alert('Hellow!');}//## Getting the userfunction GetUserData() {//## Getting the contextcontext = new SP.ClientContext.get_current();//## Getting the webweb = context.get_web();//## Getting the current usercurrentUser = web.get_currentUser();//## Load the querycurrentUser.retrieve();context.load(web);//## Execute the query Asynccontext.executeQueryAsync(Function.createDelegate(this, this.onSuccessMethod), Function.createDelegate(this, this.onFailureMethod));}//## SUCCESS FOR USER EVENTfunction onSuccessMethod(sender, args) {//## Setting the object to get the current user...again...var userObject = web.get_currentUser();//## Adding the user into a Variableusername = userObject.get_title();loginname = userObject.get_loginName();if (isgettinglist == false) {alert('User name:' + username + '\n Login Name:' + loginname);}if (isgettinglist == true) {//## Getting the results from the listvar department = GetPropertyFromUserProfile("http://ecmdemo.panint.com/lms/_vti_bin/UserProfileService.asmx", "Department", loginname);var title = GetPropertyFromUserProfile("http://ecmdemo.panint.com/lms/_vti_bin/UserProfileService.asmx", "Title", loginname);GetListByName(loginname,department,title);}}//## FAILURE FOR USER EVENTfunction onFailureMethod(sender, args) {alert('request failed ' + args.get_message() + '\n' + args.get_stackTrace());}//## It gets the property froma user profilefunction GetPropertyFromUserProfile(url,name,value){var responsefromwebservice = null;var parameters = new SOAPClientParameters();parameters.add("acountName", value);parameters.add("propertyName", name);//## SYNC MODEvar response = SOAPClient.invoke(url, "GetUserPropertyByAccountName", parameters, false);//#############//## ASYNC MODE//SOAPClient.invoke("http://ecmdemo.panint.com/lms/_vti_bin/UserProfileService.asmx", "GetUserPropertyByAccountName", pl, true, GetDepartMentFromUserProfile_callBack);//function GetDepartMentFromUserProfile_callBack(r)//{alert(r);}//alert(response.Values[0].Value);//#############if (response != null) responsefromwebservice = response.Values[0].Value;return responsefromwebservice;}//## It gets the number of seats quering the login, department and titlefunction GetListByName(username,department,title) {//## Get the context againcontext = new SP.ClientContext.get_current();//## Get the listvar list = context.get_site().get_rootWeb().get_lists().getByTitle('Shared Documents');//## Builds a CAMEL querty to return itemsvar query = new SP.CamlQuery();//query.set_viewXml('<View><Query><Where><Eq><FieldRef Name="Author"/><Value Type="User">' + username + '</Value></Eq></Where></Query><ViewFields><FieldRef Name="Title"/><FieldRef Name="FileLeafRef"/></ViewFields></View>');query.set_viewXml('<Query> <Where> <And> <Contains><FieldRef Name="Grade" /> <Value Type="Text">' + title + '</Value> </Contains> <And><Contains><FieldRef Name="Group" /><Value Type="Text">' + department + '</Value></Contains><And> <Geq> <FieldRef Name="Start" /> <Value IncludeTimeValue="TRUE" Type="DateTime">' + GetDateTimeNowForCAMLQuery() + '</Value> </Geq> <Gt><FieldRef Name="Remaining_x0020_Seats" /> <Value Type="Number">0</Value> </Gt> </And></And> </And></Where></Query>');//## Geting the itemsthis.collListItems = list.getItems(query);context.load(collListItems);//## Execute the query Asynccontext.executeQueryAsync(Function.createDelegate(this, this.GetListByNameSuccessFunctionEvent), Function.createDelegate(this, this.GetListByNameFailFunctionEvent));}//## SUCCESS FOR LIST EVENTfunction GetListByNameSuccessFunctionEvent() {//## Do something useful like loop through your returned list items and output in a variablevar listItemEnumerator = this.collListItems.getEnumerator();var strHtml = "";while (listItemEnumerator.moveNext()) {var oListItem = listItemEnumerator.get_current();strHtml += oListItem.get_item('Remaining_x0020_Seats').toString();}return strHtml;//alert(strHtml);}//## FAIL FOR USER EVENTfunction GetListByNameFailFunctionEvent() { alert('Request fail'); }//###################################################################//###################################################################//################ U T I L I T I E S ################################//###################################################################//###################################################################function GetDateTimeNowForCAMLQuery(){//## FORMAT 2011-09-16T16:15:18zvar currentTime = new Date()return currentTime.getFullYear()+'-'+currentTime.getMonth()+'-'+currentTime.getDay()+'T'+currentTime.getHours()+':'+currentTime.getMinutes()+':'+currentTime.getSeconds()+'z';}function SOAPClientParameters() {var _pl = new Array();this.add = function (name, value) {_pl[name] = value;return this;}this.toXml = function () {var xml = "";for (var p in _pl) {switch (typeof (_pl[p])) {case "string":case "number":case "boolean":case "object":xml += "<" + p + ">" + SOAPClientParameters._serialize(_pl[p]) + "</" + p + ">";break;default:break;}}return xml;}}SOAPClientParameters._serialize = function (o) {var s = "";switch (typeof (o)) {case "string":s += o.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); break;case "number":case "boolean":s += o.toString(); break;case "object":// Dateif (o.constructor.toString().indexOf("function Date()") > -1) {var year = o.getFullYear().toString();var month = (o.getMonth() + 1).toString(); month = (month.length == 1) ? "0" + month : month;var date = o.getDate().toString(); date = (date.length == 1) ? "0" + date : date;var hours = o.getHours().toString(); hours = (hours.length == 1) ? "0" + hours : hours;var minutes = o.getMinutes().toString(); minutes = (minutes.length == 1) ? "0" + minutes : minutes;var seconds = o.getSeconds().toString(); seconds = (seconds.length == 1) ? "0" + seconds : seconds;var milliseconds = o.getMilliseconds().toString();var tzminutes = Math.abs(o.getTimezoneOffset());var tzhours = 0;while (tzminutes >= 60) {tzhours++;tzminutes -= 60;}tzminutes = (tzminutes.toString().length == 1) ? "0" + tzminutes.toString() : tzminutes.toString();tzhours = (tzhours.toString().length == 1) ? "0" + tzhours.toString() : tzhours.toString();var timezone = ((o.getTimezoneOffset() < 0) ? "+" : "-") + tzhours + ":" + tzminutes;s += year + "-" + month + "-" + date + "T" + hours + ":" + minutes + ":" + seconds + "." + milliseconds + timezone;}// Arrayelse if (o.constructor.toString().indexOf("function Array()") > -1) {for (var p in o) {if (!isNaN(p)) // linear array{(/function\s+(\w*)\s*\(/ig).exec(o[p].constructor.toString());var type = RegExp.$1;switch (type) {case "":type = typeof (o[p]);case "String":type = "string"; break;case "Number":type = "int"; break;case "Boolean":type = "bool"; break;case "Date":type = "DateTime"; break;}s += "<" + type + ">" + SOAPClientParameters._serialize(o[p]) + "</" + type + ">"}else // associative arrays += "<" + p + ">" + SOAPClientParameters._serialize(o[p]) + "</" + p + ">"}}// Object or custom functionelsefor (var p in o)s += "<" + p + ">" + SOAPClientParameters._serialize(o[p]) + "</" + p + ">";break;default:break; // throw new Error(500, "SOAPClientParameters: type '" + typeof(o) + "' is not supported");}return s;}function SOAPClient() { }SOAPClient.username = null;SOAPClient.password = null;SOAPClient.invoke = function (url, method, parameters, async, callback) {if (async)SOAPClient._loadWsdl(url, method, parameters, async, callback);elsereturn SOAPClient._loadWsdl(url, method, parameters, async, callback);}// private: wsdl cacheSOAPClient_cacheWsdl = new Array();// private: invoke asyncSOAPClient._loadWsdl = function (url, method, parameters, async, callback) {// load from cache?var wsdl = SOAPClient_cacheWsdl[url];if (wsdl + "" != "" && wsdl + "" != "undefined")return SOAPClient._sendSoapRequest(url, method, parameters, async, callback, wsdl);// get wsdlvar xmlHttp = SOAPClient._getXmlHttp();xmlHttp.open("GET", url + "?wsdl", async);if (async) {xmlHttp.onreadystatechange = function () {if (xmlHttp.readyState == 4)SOAPClient._onLoadWsdl(url, method, parameters, async, callback, xmlHttp);}}xmlHttp.send(null);if (!async)return SOAPClient._onLoadWsdl(url, method, parameters, async, callback, xmlHttp);}SOAPClient._onLoadWsdl = function (url, method, parameters, async, callback, req) {var wsdl = req.responseXML;SOAPClient_cacheWsdl[url] = wsdl; // save a copy in cachereturn SOAPClient._sendSoapRequest(url, method, parameters, async, callback, wsdl);}SOAPClient._sendSoapRequest = function (url, method, parameters, async, callback, wsdl) {// get namespacevar ns = (wsdl.documentElement.attributes["targetNamespace"] + "" == "undefined") ? wsdl.documentElement.attributes.getNamedItem("targetNamespace").nodeValue : wsdl.documentElement.attributes["targetNamespace"].value;// build SOAP requestvar sr ="<?xml version=\"1.0\" encoding=\"utf-8\"?>" +"<soap:Envelope " +"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +"xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +"<soap:Body>" +"<" + method + " xmlns=\"" + ns + "\">" +parameters.toXml() +"</" + method + "></soap:Body></soap:Envelope>";// send requestvar xmlHttp = SOAPClient._getXmlHttp();if (SOAPClient.userName && SOAPClient.password) {xmlHttp.open("POST", url, async, SOAPClient.userName, SOAPClient.password);// Some WS implementations (i.e. BEA WebLogic Server 10.0 JAX-WS) don't support Challenge/Response HTTP BASIC, so we send authorization headers in the first requestxmlHttp.setRequestHeader("Authorization", "Basic " + SOAPClient._toBase64(SOAPClient.userName + ":" + SOAPClient.password));}elsexmlHttp.open("POST", url, async);var soapaction = ((ns.lastIndexOf("/") != ns.length - 1) ? ns + "/" : ns) + method;xmlHttp.setRequestHeader("SOAPAction", soapaction);xmlHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");if (async) {xmlHttp.onreadystatechange = function () {if (xmlHttp.readyState == 4)SOAPClient._onSendSoapRequest(method, async, callback, wsdl, xmlHttp);}}xmlHttp.send(sr);if (!async)return SOAPClient._onSendSoapRequest(method, async, callback, wsdl, xmlHttp);}SOAPClient._onSendSoapRequest = function (method, async, callback, wsdl, req) {var o = null;var nd = SOAPClient._getElementsByTagName(req.responseXML, method + "Result");if (nd.length == 0)nd = SOAPClient._getElementsByTagName(req.responseXML, "return"); // PHP web Service?if (nd.length == 0) {if (req.responseXML.getElementsByTagName("faultcode").length > 0) {if (async || callback)o = new Error(500, req.responseXML.getElementsByTagName("faultstring")[0].childNodes[0].nodeValue);elsethrow new Error(500, req.responseXML.getElementsByTagName("faultstring")[0].childNodes[0].nodeValue);}}elseo = SOAPClient._soapresult2object(nd[0], wsdl);if (callback)callback(o, req.responseXML);if (!async)return o;}SOAPClient._soapresult2object = function (node, wsdl) {var wsdlTypes = SOAPClient._getTypesFromWsdl(wsdl);return SOAPClient._node2object(node, wsdlTypes);}SOAPClient._node2object = function (node, wsdlTypes) {// null nodeif (node == null)return null;// text nodeif (node.nodeType == 3 || node.nodeType == 4)return SOAPClient._extractValue(node, wsdlTypes);// leaf nodeif (node.childNodes.length == 1 && (node.childNodes[0].nodeType == 3 || node.childNodes[0].nodeType == 4))return SOAPClient._node2object(node.childNodes[0], wsdlTypes);var isarray = SOAPClient._getTypeFromWsdl(node.nodeName, wsdlTypes).toLowerCase().indexOf("arrayof") != -1;// object nodeif (!isarray) {var obj = null;if (node.hasChildNodes())obj = new Object();for (var i = 0; i < node.childNodes.length; i++) {var p = SOAPClient._node2object(node.childNodes[i], wsdlTypes);obj[node.childNodes[i].nodeName] = p;}return obj;}// list nodeelse {// create node refvar l = new Array();for (var i = 0; i < node.childNodes.length; i++)l[l.length] = SOAPClient._node2object(node.childNodes[i], wsdlTypes);return l;}return null;}SOAPClient._extractValue = function (node, wsdlTypes) {var value = node.nodeValue;switch (SOAPClient._getTypeFromWsdl(node.parentNode.nodeName, wsdlTypes).toLowerCase()) {default:case "s:string":return (value != null) ? value + "" : "";case "s:boolean":return value + "" == "true";case "s:int":case "s:long":return (value != null) ? parseInt(value + "", 10) : 0;case "s:double":return (value != null) ? parseFloat(value + "") : 0;case "s:datetime":if (value == null)return null;else {value = value + "";value = value.substring(0, (value.lastIndexOf(".") == -1 ? value.length : value.lastIndexOf(".")));value = value.replace(/T/gi, " ");value = value.replace(/-/gi, "/");var d = new Date();d.setTime(Date.parse(value));return d;}}}SOAPClient._getTypesFromWsdl = function (wsdl) {var wsdlTypes = new Array();// IEvar ell = wsdl.getElementsByTagName("s:element");var useNamedItem = true;// MOZif (ell.length == 0) {ell = wsdl.getElementsByTagName("element");useNamedItem = false;}for (var i = 0; i < ell.length; i++) {if (useNamedItem) {if (ell[i].attributes.getNamedItem("name") != null && ell[i].attributes.getNamedItem("type") != null)wsdlTypes[ell[i].attributes.getNamedItem("name").nodeValue] = ell[i].attributes.getNamedItem("type").nodeValue;}else {if (ell[i].attributes["name"] != null && ell[i].attributes["type"] != null)wsdlTypes[ell[i].attributes["name"].value] = ell[i].attributes["type"].value;}}return wsdlTypes;}SOAPClient._getTypeFromWsdl = function (elementname, wsdlTypes) {var type = wsdlTypes[elementname] + "";return (type == "undefined") ? "" : type;}// private: utilsSOAPClient._getElementsByTagName = function (document, tagName) {try {// trying to get node omitting any namespaces (latest versions of MSXML.XMLDocument)return document.selectNodes(".//*[local-name()=\"" + tagName + "\"]");}catch (ex) { }// old XML parser supportreturn document.getElementsByTagName(tagName);}// private: xmlhttp factorySOAPClient._getXmlHttp = function () {try {if (window.XMLHttpRequest) {var req = new XMLHttpRequest();// some versions of Moz do not support the readyState property and the onreadystate event so we patch it!if (req.readyState == null) {req.readyState = 1;req.addEventListener("load",function () {req.readyState = 4;if (typeof req.onreadystatechange == "function")req.onreadystatechange();},false);}return req;}if (window.ActiveXObject)return new ActiveXObject(SOAPClient._getXmlHttpProgID());}catch (ex) { }throw new Error("Your browser does not support XmlHttp objects");}SOAPClient._getXmlHttpProgID = function () {if (SOAPClient._getXmlHttpProgID.progid)return SOAPClient._getXmlHttpProgID.progid;var progids = ["Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];var o;for (var i = 0; i < progids.length; i++) {try {o = new ActiveXObject(progids[i]);return SOAPClient._getXmlHttpProgID.progid = progids[i];}catch (ex) { };}throw new Error("Could not find an installed XML parser");}SOAPClient._toBase64 = function (input) {var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output = "";var chr1, chr2, chr3;var enc1, enc2, enc3, enc4;var i = 0;do {chr1 = input.charCodeAt(i++);chr2 = input.charCodeAt(i++);chr3 = input.charCodeAt(i++);enc1 = chr1 >> 2;enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);enc4 = chr3 & 63;if (isNaN(chr2)) {enc3 = enc4 = 64;} else if (isNaN(chr3)) {enc4 = 64;}output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) +keyStr.charAt(enc3) + keyStr.charAt(enc4);} while (i < input.length);return output;}</script></asp:Content><asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server"><SharePoint:FormDigest ID="FormDigest1" runat="server" /><asp:Button ID="Button1" runat="server" Text="Get User" /><asp:Button ID="Button2" runat="server" Text="Query List" /><asp:Button ID="Button3" runat="server" Text="Say Hello" /></asp:Content><asp:Content ID="PageTitle" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">Application Page</asp:Content><asp:Content ID="PageTitleInTitleArea" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server" >My Application Page</asp:Content>
2 Part ASP.NET:
using System;using Microsoft.SharePoint;using Microsoft.SharePoint.WebControls;namespace netsourcecodeJavaScript.Layouts.netsourcecodeJavaScript{public partial class GetUsers : LayoutsPageBase{protected void Page_Load(object sender, EventArgs e){Button1.Attributes.Add("onclick", "DisplayUser()");Button2.Attributes.Add("onclick", "DisplayList()");Button3.Attributes.Add("onclick", "SayHello()");}}}
Conclusion: As you can see you can achieve almost everything with the native webservices. Unfortunately Intellisense doesn't work properly for JavaScript in Visual Studio 2010…so it is a nightmare to do something with it.
1 comment:
Wow, incredible blog layout! How long have you been blogging for?
you made blogging look easy. The overall look of your site is
great, as well as the content!
Feel free to visit my homepage: Male enhancement
Post a Comment