• Home
  • Library
  • Wiki
  • Learn
  • Gallery
  • Downloads
  • Support
  • Forums
  • Blogs
Resources For IT Professionals
Microsoft Technet Image
United Kingdom (Proper English-like)
Skip to locale bar
    •  
    Wiki  >  TechNet Articles  > 
    • Article
    • History

    Write a Custom Web Service for SharePoint in Supported Mode - TechNet Articles - United States (English) - TechNet Wiki

    Table of Contents
    • Introduction
    • How SharePoint process web services
    • Create Custom Web Service for SharePoint
    • More Information
    • Source code
    • Demo

    Introduction

    If you have read my comments on the Writing Custom Web Service for SharePoint, Is it supported? (http://blog.libinuko.com/2011/02/16/sharepoint-writing-custom-web-service-for-sharepoint-is-it-supported/) ; you may have already created standard ASPNET web services. It is working, but with some limitation:

    1. You can not have path virtualization
      Virtualization is one of SharePoint’s technique provided by SPVirtualPath provider, that enable virtualization of your web service path. For example, list.asmx will be available for http://mysite.com/_vti_bin/lists.asmx , or http://mysite.com/sites/myothersitecollection/_vti_bin/lists.asmx. The site collection has been virtualized by SharePoint.
      Without virtualization any web service consumer will have to access to the same path, usually in the root; for example /_services/mywebservice.asmx">http://<webapps>/_services/mywebservice.asmx
    2. You can not have SPContext
      SPContext is very powerful object in SharePoint development. Using this context, we can retrieve current SharePoint context without having to instantiate it. For example, you can get current SPWeb by calling SPContext.Current.Web – and you don’t need to dispose it (in fact you’re not suppose to dispose it). Still using SPContext you can have direct access to list and everything under SharePoint.
      Without having direct access to SPContext, you have to instantiate SPWeb or SPSite using normal constructor with URL as parameter. It means new SPSite/SPWeb thread in the server memory, and you have to dispose it once you’ve done working with it.

    So, how can we write custom web service for SharePoint in supported mode?

    Before we start, we have to understand SharePoint architecture and how does the processing works for web services. I take following picture from SharePoint Architecture in MSDN. It describe how SharePoint process our request. There is SPHttpApplication which has SPRequestModule and any additional ASP.NET Module; and before the request returned back to the user SPHttpHandler is doing the job.

     

    How SharePoint process web services

     

    If we dig into into the process on how SharePoint process request to web services in _vti_bin.

    There are 3 scenarios of http request to the web services,

    1. Disco request, identified by suffix ?DISCO in the web service address. For example, */_vti_bin/list.asmx?Disco
    2. WSDL request, identified by suffix ?WSDL in the web service address. For example, */_vti_bin/list.asmx?Wsdl
    3. Web service post request. For example, */_vti_bin/list.asmx?op=GetListItems

    Every request will be processed by SPHttpHandler (SharePoint) and ScriptHandlerFactory (system.web.extension), but the SPHttpHandler will be selective only for Disco and Wsdl request.

    On disco/wsdl request, SPHttpHandler will transfer the request to wsdisco.aspx or wswsdl.aspx using Server.Execute operation. This operation ensure that wsdisco.aspx/wswsdl.aspx is receiving same request object. wsDISCO.aspx or wsWSDL.aspx will then instantiate SharePoint Context object. Any *.aspx will be successfully instantiate SharePoint context object because they are managed by SPHttpApplication and hence it also impacted by SPVirtualPath provider from SharePoint which will activate path virtualization.

    Next, wsDISCO.aspx will transfer the request to the <service>DISCO.aspx and wsWSDL.aspx will transfer to the <service>WSDL.aspx – using Server.Execute operation. So here we have seen 2 transfer operation. At the end, the result is correct WSDL/DISCO request. The correct WSDL/DISCO will point to the correct virtual path of the request. (Remember how do you create <service>disco.aspx / <service>wsdl.aspx)

    When a consumer use the contract and tries to consume it. The SPHttpHandler will no longer intercept the request, but the normal ScriptHandlerFactory from System.Web.Extensions. However with the correct path in disco/wsdl, now the asmx now have the ability to look into current context from SharePoint. And hence you will be able to use SPContext.Current.Web in custom web services.

    Create Custom Web Service for SharePoint

    Create Visual Studio Solution

    1. Open Visual Studio 2010
    2. Create Blank Visual Studio Solution. Give name for example DemoCustomWS.

    Create ASP.NET Web Services

    1. Add ASP.NET Web Service Application project. Give name for example CustomWS
    2. Open Service1.asmx.cs and change the implementation accordingly. For example change the namespace, class name etc.
    3. Open CustomWS project property and sign the assembly
    4. Build and open the new web service in the browser
    5. Open command prompt and run disco againts the web service url.

          disco http://webserviceurl/customservice.asmx

      The results are CustomService.disco

      Create Custom Web Service for SharePoint

      Create Visual Studio Solution

      1. Open Visual Studio 2010
      2. Create Blank Visual Studio Solution. Give name for example DemoCustomWS.

      Create ASP.NET Web Services

        and CustomService.wsdl which will be useful later in this process.
      1. Still in the command prompt, execute 

             sn -T DemoCustomWS.dll
      2. Open Service1.asmx markuppage, and change the markup accordingly using the PublicKeyToken from previous operation.
        For example:  
           <% WebService Language="C#" Class="CustomWS.CustomService, CustomWS, PublicKeyToken=2938173ce" %>

      Create SharePoint 2010 Project

      1. Add Empty SharePoint Project. Give a name for example DemoWS.
      2. Open DemoWS project property and sign the assembly.
      3. Inside DemoWS open package designer and add Assembly from project output.
      4. Select CustomWS project deploy in the GAC
      5. Inside DemoWS add SharePoint Mapped Folder, select ISAPI\CustomWS. If the folder is not available, you can create ISAPI\CustomWS under SharePoint hive.
      6. Add CustomService.disco and CustomService.wsdl to the CustomWS folder.
      7. Rename CustomService.disco into CustomServiceDisco.aspx and CustomService.wsdl into CustomServiceWSDL.aspx
      8. Change the implementation of CustomServiceDisco.aspx and CustomServiceWsdl.aspx in order to support path virtualization (See Writing Custom Web Services for SharePoint Products and Technology)
      9. Add CustomService.asmx file to the CustomWS folder in DemoWS project.
      10. Inside DemoWS add SharePoint Mapped folder, select ISAPI
      11. Copy spdisco.aspx from ISAPI folder in SharePoint hive into the mapped folder ISAPI in the project.
      12. Rename spdisco.aspx into spdisco.disco.aspx.
      13. Create copy of spdisco.disco.aspx and rename it into DemoWS.spdisco.aspx
      14. Remove all lines from DemoWS.spdisco.aspx leaving only registration for the new web services
      15. Add new HttpHandler class to the DemoWS , the most important is  on the ProcessRequest it will merge original SPDISCO.aspx and DemoWS.SPDISCO.aspx

        01.public void ProcessRequest(HttpContext context)
        02.        {
        03.            StringWriter sw1 = new StringWriter();
        04.            // Original - cop spdisco.aspx
        05.            context.Server.Execute("spdisco.disco.aspx", sw1);
        06.            XmlDocument spdiscoXml = new XmlDocument();
        07.            spdiscoXml.LoadXml(sw1.ToString());
        08.  
        09.            var files = Directory.GetFiles(context.Server.MapPath(""), "*.spdisco.aspx");
        10.            foreach (var file in files)
        11.            {
        12.                StringWriter sw2 = new StringWriter();
        13.                context.Server.Execute(System.IO.Path.GetFileName(file), sw2);
        14.  
        15.                XmlDocument otherSPDiscoXml = new XmlDocument();
        16.                otherSPDiscoXml.LoadXml(sw2.ToString());
        17.                foreach (XmlNode importedNode in otherSPDiscoXml.DocumentElement.ChildNodes)
        18.                {
        19.                    spdiscoXml.DocumentElement.AppendChild(spdiscoXml.ImportNode(importedNode, true));
        20.                }
        21.            }
        22.  
        23.            context.Response.Write(String.Format("<?xml version='1.0' encoding='utf-8' ?> {0}", spdiscoXml.InnerXml));
        24.        }
      16. Inside DemoWS add SharePoint Mapped folder, select CONFIG
      17. Add webconfig.demows.xml to the CONFIG folder. Inside webconfig.demows.xml we will register configuration changes for the web config.

      Finally you can build and deploy the solution.

      More Information

      1. Writing Custom Web Services for SharePoint Products and Technology (http://msdn.microsoft.com/en-us/library/dd583131(v=office.11).aspx)
      2. SharePoint Architecture (http://msdn.microsoft.com/en-us/library/bb892189(v=office.12).aspx )
      3. Architectural Overview of Windows SharePoint Services (http://msdn.microsoft.com/en-us/library/dd583133(v=office.11).aspx)  
      4. Modifying Built-In SharePoint Files (http://msdn.microsoft.com/en-us/library/bb803457(v=office.12).aspx)

      Source code

      1. SharePoint 2010 and Visual Studio 2010 Sample Code : Demo Custom WS (http://code.msdn.microsoft.com/Writing-SharePoint-Web-in-cb9de1be )

      Demo

    • C 2015 Microsoft Corporation. All rights reserved.
    • Terms of Use
    • Trademarks
    • Privacy Statement
    • [Copied from] v5.6.915.0
    • This page has been extacted by Pete Laker, Microsoft Azure MVP & Microsoft IT Implementer
    X