Monday, 19 September 2011

RESTful, Sharepoint Web Services , JavaScript(SP.js) and ASP.NET all together in a Sharepoint 2010 application form

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?

  1. Visual Studio 2010.
  2. Sharepoint 2010.
  3. A list called “Shared Documents” with an extra field called remaining seats.
  4. Two extra fields in the user profile (Department, Title).
  5. Change the references in the JavaScript to the URLs
  6. 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");
       
    //## Variables
    var 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 MessageBox
    function DisplayUser() {
        isgettinglist = false;
        GetUserData();
    }
    //## 2
    //## This function displays the values from the list
    function DisplayList() {
        isgettinglist = true;
        GetUserData();
    }
    //## 3
    //## This function says hello.
    function SayHello() {
        alert('Hellow!');
    }
    //## Getting the user
    function GetUserData() {
        //## Getting the context
        context = new SP.ClientContext.get_current();
        //## Getting the web
        web = context.get_web();
        //## Getting the current user
        currentUser = web.get_currentUser();
                             
        //## Load the query
        currentUser.retrieve();
        context.load(web);
       
        //## Execute the query Async
        context.executeQueryAsync(Function.createDelegate(this, this.onSuccessMethod), Function.createDelegate(this, this.onFailureMethod));
    }
   
    //## SUCCESS FOR USER EVENT
    function onSuccessMethod(sender, args) {
        //## Setting the object to get the current user...again...
        var userObject = web.get_currentUser();
       
        //## Adding the user into a Variable
        username = 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 list
            var 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 EVENT
    function onFailureMethod(sender, args) {
        alert('request failed ' + args.get_message() + '\n' + args.get_stackTrace());
    }   
    //## It gets the property froma  user profile
    function GetPropertyFromUserProfile(url,name,value)
    {
        var responsefromwebservice = null;
        var parameters = new SOAPClientParameters();
        parameters.add("acountName", value);
        parameters.add("propertyName", name);
        //## SYNC MODE
        var 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 title
    function GetListByName(username,department,title) {
        //## Get the context again
        context = new SP.ClientContext.get_current();
        //## Get the list
        var list = context.get_site().get_rootWeb().get_lists().getByTitle('Shared Documents');
        //## Builds a CAMEL querty to return items
        var 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 items
        this.collListItems = list.getItems(query);
        context.load(collListItems);
        //## Execute the query Async
        context.executeQueryAsync(Function.createDelegate(this, this.GetListByNameSuccessFunctionEvent), Function.createDelegate(this, this.GetListByNameFailFunctionEvent));
    }
    //## SUCCESS FOR LIST EVENT
    function GetListByNameSuccessFunctionEvent() {
        //## Do something useful like loop through your returned list items and output in a variable        
        var 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 EVENT
    function GetListByNameFailFunctionEvent() { alert('Request fail'); }
    //###################################################################
    //###################################################################
    //################ U T I L I T I E S ################################
    //###################################################################
    //###################################################################
    function GetDateTimeNowForCAMLQuery()
    {
        //## FORMAT 2011-09-16T16:15:18z
        var 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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); break;
            case "number":
            case "boolean":
                s += o.toString(); break;
            case "object":
                // Date
                if (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;
                }
                // Array
                else 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 array
                            s += "<" + p + ">" + SOAPClientParameters._serialize(o[p]) + "</" + p + ">"
                    }
                }
                // Object or custom function
                else
                    for (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);
        else
            return SOAPClient._loadWsdl(url, method, parameters, async, callback);
    }
    // private: wsdl cache
    SOAPClient_cacheWsdl = new Array();
    // private: invoke async
    SOAPClient._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 wsdl
        var 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 cache
        return SOAPClient._sendSoapRequest(url, method, parameters, async, callback, wsdl);
    }
    SOAPClient._sendSoapRequest = function (url, method, parameters, async, callback, wsdl) {
        // get namespace
        var ns = (wsdl.documentElement.attributes["targetNamespace"] + "" == "undefined") ? wsdl.documentElement.attributes.getNamedItem("targetNamespace").nodeValue : wsdl.documentElement.attributes["targetNamespace"].value;
        // build SOAP request
        var 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 request
        var 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 request
            xmlHttp.setRequestHeader("Authorization", "Basic " + SOAPClient._toBase64(SOAPClient.userName + ":" + SOAPClient.password));
        }
        else
            xmlHttp.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);
                else
                    throw new Error(500, req.responseXML.getElementsByTagName("faultstring")[0].childNodes[0].nodeValue);
            }
        }
        else
            o = 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 node
        if (node == null)
            return null;
        // text node
        if (node.nodeType == 3 || node.nodeType == 4)
            return SOAPClient._extractValue(node, wsdlTypes);
        // leaf node
        if (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 node
        if (!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 node
        else {
            // create node ref
            var 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();
        // IE
        var ell = wsdl.getElementsByTagName("s:element");
        var useNamedItem = true;
        // MOZ
        if (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: utils
    SOAPClient._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 support
        return document.getElementsByTagName(tagName);
    }
    // private: xmlhttp factory
    SOAPClient._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.

2 comments:

Anonymous said...

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

chenmeinv0 said...

borse louis vuitton
moncler outlet
michael kors outlet online
michael kors handbags
coach outlet online
christian louboutin sale
louis vuitton handbags
cheap ugg boots
ray ban glasses
oakley canada
2016.12.17xukaimin