Showing posts with label Web Service. Show all posts
Showing posts with label Web Service. Show all posts

Thursday, 13 October 2011

Building a Document Management System with SharePoint 2010 - Part 11–Creating Content Types from the Client Model

This post is more about how to improve the performance of your DMS to the extreme using the client model:
Microsoft.SharePoint.Client.Runtime.dll
Microsoft.SharePoint.Client.dll
Well, what I mean with best performance is to be able to not just create Content Types with the Client Model (I don’t cover this part here because I assume you already have the content types), it is the fact we can assign Content Types, something that is not allowed in the client model unless you use some tricks.

What I am going to do is to assign two different Content Types (Client Folder, Matter Folder) so we can have a client/matter structure in our DMS. Both Content Types are already created and inherits from the native folder Content Type. So we will have something like this:


+Client1----+Matter1
                   |
                   +Matter2
                   |
                   +Matter3

Before going ahead wit the chunk of code, I will explain you how it works.
1- You create your folder.
2- You get the id from your content type.
3- You apply the id into this field: “ContentTypeId”. I update the client number and client description.

ListItem item = items[0];
item["ContentTypeId"] = _ctClientFolder.Id;
item["client"] = _sClientNumber;
item["clientdescription"] = _sClientDescription;
item.Update();
clientContext.ExecuteQuery();



I am going to add the code below, to use it, be sure you add:
Microsoft.SharePoint.Client.Runtime.dll
Microsoft.SharePoint.Client.dll
Into your references and :

using Microsoft.SharePoint.Client;
To call the method just try this:
CreateClientMatter(@"http://mysharepointserver", "Documents", "00000272", "my client", "00000018", "my matter");
Just copy and paste this code into your project, if the client/matter is not there it will created and add the properties:
        private List ListCheck(ClientContext clientContext, Web _wListWeb, string _sListName)
        {
            List _lExistingList = null;
            try
            {
                //###############################
                //## We check if the file exists
                //###############################
                _wListWeb = clientContext.Web;
                ListCollection _lCollectionOfLists = _wListWeb.Lists;
                IEnumerable<List> existingLists = clientContext.LoadQuery(
                        _lCollectionOfLists.Where(
                        list => list.Title == _sListName)
                        );
                clientContext.ExecuteQuery(); 
                _lExistingList = existingLists.FirstOrDefault();
                //############################### 
            }
            catch (Exception ex)
            {
                throw new ArgumentNullException();
            }
            return _lExistingList;
        }
        private void CreateClientFolder(string _sServerURL, ClientContext clientContext, Web _wListWeb, List _lList, string _sListName, string _sClientNumber, string _sClientDescription)
        {
            //## Variables.
            Folder _fExistingFolder = null;
            ContentType _ctClientFolder = null; 
            //## We get all the folders
            FolderCollection _afolders = _lList.RootFolder.Folders; 
            //## Building the URL (folder)
            String _sClientfolderUrl = String.Format("/{0}/{1}", _sListName, _sClientNumber);
            //## We check if the URL exists
            IEnumerable<Folder> _iClientExistingFolders = clientContext.LoadQuery<Folder>(
                _afolders.Where(
                folder => folder.ServerRelativeUrl == _sClientfolderUrl)
                );
            clientContext.ExecuteQuery();
            //## Getting the result
            _fExistingFolder = _iClientExistingFolders.FirstOrDefault();
            if (_fExistingFolder == null)                       
            {
                //## Adding the folder
                _wListWeb.Folders.Add(_sServerURL + @"/" + _sListName + @"/" + _sClientNumber);
                clientContext.ExecuteQuery();
                //## Quering our folder
                CamlQuery query = new CamlQuery();
                query.ViewXml = @"       <View>
                                             <Query>
                                                <Where>
                                                   <Eq>
                                                      <FieldRef Name='FileLeafRef'/>
                                                      <Value Type='Text'>"+_sClientNumber+@"</Value>
                                                   </Eq>
                                                </Where>
                                             </Query>
                                             <RowLimit>1</RowLimit>
                                          </View>"; 
                ListItemCollection items = _lList.GetItems(query);
                clientContext.Load(items);
                //## Getting the content types
                ContentTypeCollection _ctListOfContentTypes = clientContext.Web.AvailableContentTypes;
                clientContext.Load(_ctListOfContentTypes);
                clientContext.ExecuteQuery();
                //## Getting the Content Type Id
                foreach (ContentType _ctItem in _ctListOfContentTypes)
                {
                    if (_ctItem.Name == "Client Folder")
                    {
                        _ctClientFolder = _ctItem;
                        break;
                    }
                }
                //## This is the tricky part, where we convert our folder
                //## Into a content type. We add some metadata as well               
                if (items.Count > 0)
                {
                    ListItem item = items[0];
                    item["ContentTypeId"] = _ctClientFolder.Id;
                    item["client"] = _sClientNumber;
                    item["clientdescription"] = _sClientDescription;
                    item.Update();
                    clientContext.ExecuteQuery();
                }
            }
        }
 
        private void CreateMatterFolder(string _sServerURL, ClientContext clientContext, Web _wListWeb, List _lList, string _sListName,string _sClientNumber, string _sMatterNumber,string _sMatterDescription)
        {
            Folder _fExistingFolder = null;
            ContentType _ctMatterFolder = null; 
            FolderCollection _afolders = _lList.RootFolder.Folders; 
            String _sMatterfolderUrl = String.Format("/{0}/{1}/{2}", _sListName, _sClientNumber, _sMatterNumber); 
            IEnumerable<Folder> _iMatterExistingFolders = clientContext.LoadQuery<Folder>(
                _afolders.Where(
                folder => folder.ServerRelativeUrl == _sMatterfolderUrl)
                );
            clientContext.ExecuteQuery();
            _fExistingFolder = _iMatterExistingFolders.FirstOrDefault(); 
            if (_fExistingFolder == null)
            {
                _wListWeb.Folders.Add(_sServerURL + @"/" + _sListName + @"/" + _sClientNumber + @"/" + _sMatterNumber);
                clientContext.ExecuteQuery();
                //## Quering our folder
                CamlQuery query = new CamlQuery();
                query.ViewXml = @"       <View Scope='RecursiveAll'>
                                             <Query>
                                                <Where>
                                                   <Eq>
                                                      <FieldRef Name='FileLeafRef'/>
                                                      <Value Type='Text'>" + _sMatterNumber + @"</Value>
                                                   </Eq>
                                                </Where>
                                             </Query>
                                             <RowLimit>1</RowLimit>
                                          </View>";
 
                ListItemCollection items = _lList.GetItems(query);
                clientContext.Load(items); 
                //## Getting the content types
                ContentTypeCollection _ctListOfContentTypes = clientContext.Web.AvailableContentTypes;
                clientContext.Load(_ctListOfContentTypes);
                clientContext.ExecuteQuery(); 
                //## Getting the Content Type Id
                foreach (ContentType _ctItem in _ctListOfContentTypes)
                {
                    if (_ctItem.Name == "Matter Folder")
                    {
                        _ctMatterFolder = _ctItem;
                        break;
                    }
                }
                //## This is the tricky part, where we convert our folder
                //## Into a content type. We add some metadata as well               
                if (items.Count > 0)
                {
                    //## This is just in case the client number
                    //## has the same name than the new matter
                    ListItem item = items.Count == 2 ? items[1] : items[0];
                    item["ContentTypeId"] = _ctMatterFolder.Id;
                    item["matter"] = _sMatterNumber;
                    item["matterdescription"] = _sMatterDescription;
                    item.Update();
                    clientContext.ExecuteQuery();
                }
            }
        }
 
        public bool CreateClientMatter(string _sServerURL, string _sListName, string _sClientNumber, string _sClientName, string _sMatterNumber, string _sMatterName)
        {
            bool _bResult = false;
            List _lList = null;           
            try
            {
                using (var clientContext = new ClientContext(_sServerURL))
                {
                    Web _wListWeb = clientContext.Web;
                    //###############################
                    //## We check if the list exists
                    //###############################                   
                    _lList = ListCheck(clientContext, _wListWeb, _sListName);
                    //###############################                  
                    if (_lList != null)
                    {                       
                        //#################################
                        //## CREATE FOLDER CONTENT TYPES
                        //## IF THEY DON'T EXIST
                        //##################################
                        CreateClientFolder(_sServerURL, clientContext, _wListWeb, _lList, _sListName, _sClientNumber, _sClientName);
                        CreateMatterFolder(_sServerURL, clientContext, _wListWeb, _lList, _sListName, _sClientNumber,_sMatterNumber,_sMatterName);                    
                        //##################################
                        _bResult = true;
                    }
                }
            }
            catch (Exception ex)
            {
                string _sError = ex.ToString();               
            }
            return _bResult;
        }


Conclusion: In order to create a decent DMS be always sure you keep your server clean of web services and workflows, anything it can be done in the client side, it will leave the server free to do what it has to do, SERVE!

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.