We had a requirement to upload the document to SharePoint document library whenever a file has been attached to our entities in Microsoft Dynamics CRM. So the obvious way of doing that was to use web service within the CRM. We had already written a utility using SharePoint Object Model that would be doing so. So we thought of reusing the existing logic defined over there and wrap it inside one our custom web service’s method. We created the web service and we deployed it in our SharePoint Server but outside the context of the SharePoint i.e. as a separate web site. However when trying to use that web service from other machines we ran into security issues, it was always giving Unauthorized Access error. We tried running the web service app pool with identity of administrator and also tried out impersonation defined through web.config again passing the account of administrator. But it didn’t work
Then finally tried out this article within MSDN which guides us on creating a web service that operates within the context of WSS 3.0.
Basic steps for creating a custom web service are following
1) Create a new asp.net web service project.
2) Add a new class library project in that solution.
3) Move Service1.cs file from web service project to class library project
4) Delete the Service1.cs file in web service project and class1.cs file in the class library project.
5) Put your custom logic in service.cs file that is now in the class library project.
6) Give strong name to the class library i.e. Sign the assembly.
7) Put the assembly in GAC. Get its public key token.
8) Now make modification to the service.asmx to use the assembly.
9) Replace code behind attribute with the class attribute to refer to the assembly
<%@ WebService Language=“C#” Class=“Service, MyServiceAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8f2dca3c0f2d0131” %>
10) Generate static discovery and wsdl file.
11) Copy the .asmx file of the Web service to \Program FilesCommon FilesMicrosoft Sharedweb server extensions12TEMPLATELAYOUTS
12) From visual studio command prompt run the following command
disco http://MyServer:port/_layouts/MyCustomWebService.asmx
13) open both the .disco and .wsdl files and replace the opening XML processing instruction — <?xml version="1.0" encoding="utf-8"?> — with instructions such as the following
<%@ Page Language=“C#” Inherits=“System.Web.UI.Page” %>
<%@ Assembly Name=“Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Import Namespace=“Microsoft.SharePoint.Utilities” %>
<%@ Import Namespace=“Microsoft.SharePoint” %>
<% Response.ContentType = “text/xml”; %>
14) In the .disco file, modify the contract reference and SOAP address tags
<contractRef ref=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request) + “?wsdl”),Response.Output); %>
docRef=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>
<soap address=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>
<soap address=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>
15) In the .wsdl file, make the following changes for the SOAP address
<soap:address location=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %> />
16) Rename both files in the respective formats MyCustomWebServicedisco.aspx and MyCustomWebServicewsdl.aspx so that your service is discoverable through Windows SharePoint Services.
17) Copy the new MyCustomWebServicewsdl.aspx and MyCustomWebServicedisco.aspx files, and also the MyCustomWebService.asmx fil to _Drive:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions12ISAPI directory
18) Open the spdisco.aspx files located in Program FilesCommon FilesMicrosoft SharedWeb Server Extensions12ISAPI and add the following code, specifying the .asmx file for your Web service.
<contractRef ref=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(spWeb.Url + “/_vti_bin/MyCustomWebService.asmx?wsdl“), Response.Output); %>
docRef=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(spWeb.Url + “/_vti_bin/MyCustomWebService.asmx“), Response.Output); %>
<discoveryRef ref=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(spWeb.Url + “/_vti_bin/MyCustomWebService.asmx?disco“),Response.Output); %>
xmlns=“http://schemas.xmlsoap.org/disco/” />
Any modification done to the custom logic would require putting the new assembly in GAC followed by generating the static disco and wsdl file and making all the necessary modification in disco and wsdl file as mentioned in the above steps.
Now in our case finally putting the custom logic of uploading the document within the class library for the web service helped us to solve the issues that we were facing.
[WebMethod]
public string UploadDocumentToSharePoint(string fileName, byte[] fileContents, string folderName)
{
if (fileContents == null)
{
return “Null Attachment”;
}
try
{
SPWeb web = SPContext.Current.Web;
web.AllowUnsafeUpdates = true;
SPFolder folder = web.GetFolder(folderName);
string fileURL = fileName;
folder.Files.Add(fileURL, fileContents);
return “File added successfully!”;
}
catch (System.Exception ex)
{
return “Error: “ + ex.Source + “| Message: “ + ex.Message;
}
}
And this is how we used it in within our custom application after adding the web reference to it.
FileStream oFileStream = File.OpenRead(@”C:g.doc”);
byte[] content = new byte[oFileStream.Length];
// store the contents in a byte array
oFileStream.Read(content, 0, (int)oFileStream.Length);
// close the stream
oFileStream.Close();
// instantiate the service
DocService.Service docService = new DocService.Service();
// pass the current logged in user credentials
docService.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
// pass the name of the doc, content and document library name
string message = docService.UploadDocumentToSharePoint(“G1.doc”, content, “CrmDoc”);
MessageBox.Show(message);
Bye…
Posted in SharePoint Tagged: SharePoint
*This post is locked for comments